Assembler Code in Cprogramm

#4111254
Lesenswert?

Liebe Kollegen,

ich bin ein "Controller Anfänger". Ich habe mit Bascom begonnen und bin 
jetzt bei C gelandet.

Ich versuche gerade ein Programm für die Arduino IDE in C zu übersetzen.
Folgende Befehlszeile funktioniert in C allerdings nicht.

asm(" sbi %0,%1" : : "I" (_SFR_IO_ADDR(PINB)), "I" (5));
sollte ein der Schleifengeschwindigkeit entsprechendes Signal ausgeben !

Auch mit Recherche im Internet für mich nicht lösbar )-:
#4111357
Lesenswert?

Ich hab den Buchtext mal überflogen und würde es immer noch mit C-Code 
schreiben
1
PINB |= 1<<5;

Daraus sollte der compiler einen "sbi"-Befehl generieren, sonst, wie 
bereits erwähnt, den compiler in die tonne treten!

Wenn du aber weiter an deiner ASM-Lösung festhalten möchtest, so poste 
doch mal den genauen wortlaut der Fehlermeldung.
Moderator Persönliche Seite #4111407
Lesenswert?

SBI ist da sowieso Unsinn, verplempert nur einen zusätzlichen
Taktzyklus.
1
PINB = 1<<5;

ist doppelt so schnell.

Andererseits: ist natürlich völlig schnuppe, da die Arduino-Umgebung
sowieso einen langweiligen CALL für loop() machen muss.  Maximale
Geschwindigkeit würde man so bekommen:
1
void loop(void) {
2
  for(;;) PINB = 1<<5;
3
}
#4111411
Lesenswert?

@Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite

>SBI ist da sowieso Unsinn, verplempert nur einen zusätzlichen
>Taktzyklus.

>PINB = 1<<5;

>ist doppelt so schnell.

Aber nur, wenn zufällig schon eine 0x20 in einem Register steht ;-)

Geht aber alles am Ursprungsproblem vorbei.

@OP

Lass diese Assemblertricks weg, die brauchst du nicht. Programmier 
ordentlich in C und alles wird gut. Schnelle Takte erzeugt man so oder 
so mit einem Timer und der Output Compare Funktion.
(Firma: www.harerod.de) Persönliche Seite #4111555
Lesenswert?

Das ist ein schönes Beispiel, wie nah man bei Assembler am spezifischen 
Silizium ist. Und wie wichtig bei solchen Fragen die genaue 
Spezifikation der Randbedingungen ist.

Dieser "Toggle-Trick" funktioniert z.B. beim mega328, der auch im 
Arduino Uno sitzt. Bei vielen anderen AVRs funktioniert das nicht.

Wenn man durch Inline-Assembler noch besser sein will als der 
Compiler-/Bibliothekenbauer, so ist die Lektüre der entsprechenden 
MCU-Datenblätter Pflicht. Beim AVR ist das zum Glück recht 
übersichtlich.
Persönliche Seite #4111740
Lesenswert?

Marcus H. schrieb:
> Wenn man durch Inline-Assembler noch besser sein will als der
> Compiler-/Bibliothekenbauer, so ist die Lektüre der entsprechenden
> MCU-Datenblätter Pflicht. Beim AVR ist das zum Glück recht
> übersichtlich.

Ob der µC die genannte Funktionalität bei PINx bietet, muss man so oder 
so wissen.  Ohne das Verhalten des µC zu kennen kann das nicht optimial 
codiert werden — in C nicht und in Assembler auch nicht.
Persönliche Seite #4113461
Lesenswert?

Axiom schrieb:
> Jörg Wunsch schrieb:
>> PINB = 1<<5;
>>
>> ist doppelt so schnell.
>
> Was für ein Quatsch! Diese Instruktion macht was völlig anderes als
> gewünscht. Sie setzt alle anderen Bits im Register auf NULL.

Schau mal ins Manual was das genau macht bevor du hier Peinlichkeiten 
loslässt.

Laut o.g. PDF geht es darum, ein Pin (Port B5) zu toggeln, und neuere 
Devices wie bei Arduino im Einsatz implementieren das u.a. indem eine 1 
nach PINx (sic!) geschrieben wird.
(Firma: CIA) #4113882
Lesenswert?

Johann L. schrieb:
> Schau mal ins Manual was das genau macht bevor du hier Peinlichkeiten
> loslässt.
>
> Laut o.g. PDF geht es darum, ein Pin (Port B5) zu toggeln, und neuere
> Devices wie bei Arduino im Einsatz implementieren das u.a. indem eine 1
> nach PINx (sic!) geschrieben wird.

Trotzdem Quatsch!

Weil der GCC selbst bei (-OS) aus einer Zuweisung mittels "=" immer mit 
einem "immediate register load" reagiert, wie bei dem vorgeschlagenen
1
PINB = 1<<5;

hier wird immer folgendes gemacht
1
00000023  LDI R24,0x20    Load immediate 
2
00000024  OUT 0x03,R24    Out to I/O location

und das sind immer noch zwei Takte genau so viel wie eine sbi 
instruction. Wo das doppelt so schnell sein soll muss Herr Wunsch erst 
mal erklären.

Lediglich das von Little Basdart vorgeschlagene C-Äquivalent
1
PINB |= 1<<5;

führt zu einem
1
00000023  SBI 0x03,5    Set bit in I/O register


Die benötigten Prozessortakte sind die selben.
Persönliche Seite #4113907
Lesenswert?

Thomas Holmes schrieb:
> und das sind immer noch zwei Takte genau so viel wie eine sbi
> instruction. Wo das doppelt so schnell sein soll muss Herr Wunsch erst
> mal erklären.

Schon, aber...
Der Compiler wird einfach vor der Schleife (dem Sprung) das Register 
laden. Damit entsteht einmal ein Takt laden und danach dauert es immer 
nur einen anstatt 2 Takten.
Also
1
LDI...
2
label: OUT ...
3
RJMP label
und nicht
1
label:
2
LDI...
3
OUT...
4
RJMP label
#4115605
Lesenswert?

Thomas Holmes schrieb:
> Weil der GCC selbst bei (-OS) aus einer Zuweisung mittels "=" immer mit
> einem "immediate register load" reagiert, wie bei dem vorgeschlagenen

Thomas Holmes schrieb:
> Die benötigten Prozessortakte sind die selben.

weisst du zufällig wie die Arduino IDE das handhabt?

Die Compiler Optimierung -OS ist mir da nie begegnet oder wo ich sie 
einstellen kann, komme vom AVR Studio 4.18 da konnte ich diese noch 
wählen.
#4115816
Lesenswert?

Falk Brunner schrieb:
> DIESE Worte vom Chefmikrooptimierer himself? ;-)

Ich gebe zu, meine Entprellroutine ist ziemlich optimiert.
Aber es ist kein Inlineassemblerkauderwelsch drin, keine Instruktionen, 
die targetabhängig sind und keine Instruktionen, die was völlig anderes 
machen, als sie implizieren.

Ich fand dieses Togglen bei Input zuerst auch ganz lustig, aber keine 
sinnvolle Anwendung dafür.
Ich habe es daher noch nie benutzt, sondern immer nur:
1
  PORTB ^= 1<<PB0;

Wenn die Lesbarkeit oder Portierbarkeit drastisch leidet, hat bei mir 
die Optimierung ihre Grenzen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren