Hallo, eher eine theoretische Frage als ein konkretes Problem. Beim avr-gcc ist es ja oft so, dass wenn man versucht etwas möglichst dynamisch zu machen der Compiler schlechter optimieren kann, da ihm zur Compile-Zeit wichtige Infos fehlen. Beliebtes Beispiel ist ja eine Funktion, der ein Port übergeben werden soll, z.B.: void set_pin(port *, pin); So eine Funktion erzeugt viel Code im Vergleich zu PORTA |= (1 << 3); Der Compiler kann keinen "sbi" Befehl verwenden da er nicht weiß, dass der Port (die übergebene Adresse) im I/O-Bereich liegt. Ebenso muss er eine hässliche Schleife für die Schiebeoperation erzeugen. Aber da ich als Systemprogrammierer ja weiß, dass meine Funktion nur Ports (also I/O-Adressen) bekommt (kann man evtl auch prüfen)könnte ich doch per Inline-Assembler den "sbi"-Befehl vorgeben. Leider kenn ich mich mit inline-Assembler sogut wie garnicht aus. Gibt es eine Möglichkeit so ein Konstrukt zu verwenden: asm("sbi port, pin"); und die Variablen port und pin im C-Code zu befüllen? Viele Grüße, lex
le x. schrieb: > Der Compiler kann keinen "sbi" Befehl verwenden da er nicht weiß, dass > der Port (die übergebene Adresse) im I/O-Bereich liegt. > Ebenso muss er eine hässliche Schleife für die Schiebeoperation > erzeugen. > > Aber da ich als Systemprogrammierer ja weiß, dass meine Funktion nur > Ports (also I/O-Adressen) bekommt (kann man evtl auch prüfen)könnte ich > doch per Inline-Assembler den "sbi"-Befehl vorgeben. Und wie machst du das, wenn alles was du hast eine Adresse ist. Ob du jetzt weißt, dass es sich dabei um einen Port handelt oder nicht, spielt da herzlich wenig Rolle. Oder kannst du zaubern? > Leider kenn ich mich mit inline-Assembler sogut wie garnicht aus. > > Gibt es eine Möglichkeit so ein Konstrukt zu verwenden: > asm("sbi port, pin"); dann schau dir doch mal an, was du beim sbi Befehl für Argumente benutzen kannst. Wenn das möglich wäre, dann könnte das auch der COmpiler für dich tun.
le x. schrieb: > Gibt es eine Möglichkeit so ein Konstrukt zu verwenden: > asm("sbi port, pin"); Ja, so wird das gemacht. Allerdings steige ich durch die Variablenübergabe nicht durch. Deswegen habe ich mich lieber mit dem GAS beschäftigt und würde sowas als Funktion in eine eigene Datai/ extra Modul packen. Wenn's kurz genug ist, schiebt der Compiler das auch 'inline' rein (vermute ich mal stark).
So etwas müsste sich doch mit Makros machen lassen. Natürlich mit einem Haufen if's und nicht besonders wartungsfreundlich. Das Resultat müsste aber auch in einem sbi resultieren, falls der Port das zulässt und ein einer Ersatzkonstruktion wenn nicht.
Karl Heinz Buchegger schrieb: > dann schau dir doch mal an, was du beim sbi Befehl für Argumente > benutzen kannst Ralf G. schrieb: > Ja, so wird das gemacht. Allerdings steige ich durch die > Variablenübergabe nicht durch. was unter anderem daran liegen wird, daß sbi mit Variablen nix anfangen kann. Doku zum sbi-Befehl:
1 | SBI A,b mit 0 ≤ A ≤ 31, 0 ≤ b ≤ 7 |
Das sind alles zur Compilezeit bekannte Konstanten. Da könnte man höchstens was mit einen define-Makro basteln, das dann aber auch nur mit zur Compilezeit bekannten "echten" C-Konstanten gefüttert werden darf. amateur schrieb: > So etwas müsste sich doch mit Makros machen lassen. Natürlich mit einem > Haufen if's und nicht besonders wartungsfreundlich und im Endeffekt damit kaum schneller oder kürzer als der vom Compiler aus >void set_pin(port *, pin); erzeugte Code. Oliver
Sobald Du aus Konstanten Variablen machst, ist der Kuchen gegessen. Du kannst aus Variablen keinen Befehl mehr basteln, dazu müßtest Du den Code patchen, d.h. er müßte aus dem RAM ausgeführt werden. Nimm Macros, am besten mit meiner "sbit.h", damit ist es einfach und gut lesbar. Beitrag "Re: Port als Variable"
Man muß die Funktion lediglich als inline-Funktion ausführen, dann geht das ohne Probleme.
Jein. Auch nur, wenn du die Funktion mit konstanten Werten aufrufst. Sobald du deine inline-Funktion aus einem Funktionskontext mit Parameter aufrufst, muss der Compiler wieder das schlimmste annehmen und den kompletten Code reinklatschen. Unter Umständen sogar eher kontraproduktiv...
Rolf Magnus schrieb: > Man muß die Funktion lediglich als inline-Funktion ausführen, dann geht > das ohne Probleme. Inline oder nicht inline ist nicht die Frage. Solange da etwas in der Art steht:
1 | set_pin(PORTA, 3); |
kann der Compiler das in ein sbi umsetzen. Aus so etwas hier:
1 | for (uint8_t i=0;i<8;i++) |
2 | set_pin(PORTA, i); |
oder
1 | for (uint8_t i=0;i<3;i++) |
2 | set_pin(portlist[i], 3); |
lässt sich aber nun mal kein einzelnes sbi erzeugen. Oliver
bal schrieb: > Sobald du deine inline-Funktion aus einem Funktionskontext mit Parameter > aufrufst, muss der Compiler wieder das schlimmste annehmen und den > kompletten Code reinklatschen. > > Unter Umständen sogar eher kontraproduktiv... Es verhält sich genau so, als ob ich ein PORTA = (1 << X) direkt hinschreibe. Eine Verschlechterung demgegenüber gibt es nicht. Nur wenn X eine Compilezeit-Konstante ist, bekomme ich die schnelle Variante. Oliver schrieb: > Rolf Magnus schrieb: >> Man muß die Funktion lediglich als inline-Funktion ausführen, dann geht >> das ohne Probleme. > > Inline oder nicht inline ist nicht die Frage. Doch. Wenn die Funktion nicht inline aufgelöst wird, bekommst du immer die langsame Variante, egal was du übergibst.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.