Hallo, Ich habe eine counter Variable die bei mir in Register r2:r3 liegt. Diese wird bei einem "timer compare interrupt" um 1 erhöht. Da dieser Interrupt häufig aufgerufen wird versuche ich den Interrupt-Aufruf 'abzuspecken' (naked interrupt). register uint16_t counter asm("r2"); __attribute__((naked)) ISR(TIM1_COMPA_vect) { counter++; asm volatile ( "reti" ); } Da counter in einem Register liegt brauche ich die standard Interrupt Pro,Eplioge ja vorrauss. nicht. Sehe ich das richtig ? Muss ich evtl. doch Register speichern (SREG für Carry) ? Danke..
Du musst alles sichern, was du kaputt machst. SREG gehört dazu, ja. __attribute__((naked)) und ISR() sind gemeinsam sinnlos: hinter ISR steht ja weiter nichts als __attribute__((signal)), und das will etwas anderes tun als __attribute__((naked)). Eigentlich kommst du besser, wenn du die ganze ISR gleich in eine separate Assemblerdatei legst, statt dich im Compilerverbiegen und inline-Assemblieren zu üben. Das Ergebnis dürfte allemal übersichtlicher sein.
Danke für die antwort .. habe gerade bemerkt dass die verlegung des counters in ein register schon automatisch die ISR optimiert :) //////////////// von counter im RAM: ISR(TIM1_COMPA_vect) { ae2: 1f 92 push r1 ae4: 0f 92 push r0 ae6: 0f b6 in r0, 0x3f ; 63 ae8: 0f 92 push r0 aea: 11 24 eor r1, r1 aec: 8f 93 push r24 aee: 9f 93 push r25 counter++; af0: 80 91 83 00 lds r24, 0x0083 af4: 90 91 84 00 lds r25, 0x0084 af8: 01 96 adiw r24, 0x01 ; 1 afa: 90 93 84 00 sts 0x0084, r25 afe: 80 93 83 00 sts 0x0083, r24 b02: 9f 91 pop r25 b04: 8f 91 pop r24 b06: 0f 90 pop r0 b08: 0f be out 0x3f, r0 ; 63 b0a: 0f 90 pop r0 b0c: 1f 90 pop r1 b0e: 18 95 reti //////////////// auf counter im REG: ISR(TIM1_COMPA_vect) { ac6: 1f 92 push r1 ac8: 0f 92 push r0 aca: 0f b6 in r0, 0x3f ; 63 acc: 0f 92 push r0 ace: 11 24 eor r1, r1 counter++; ad0: 08 94 sec ad2: 21 1c adc r2, r1 ad4: 31 1c adc r3, r1 ad6: 0f 90 pop r0 ad8: 0f be out 0x3f, r0 ; 63 ada: 0f 90 pop r0 adc: 1f 90 pop r1 ade: 18 95 reti
Ist trotzdem seltsam, wieso in der zweiten Version nicht auch ein "adiw" genutzt wird, so würde die ISR noch viel kürzer...? //////////////// auf counter im REG: ISR(TIM1_COMPA_vect) { push r0 in r0, 0x3f ; 63 push r0 adiw r2, 0x01 ; 1 // counter++; pop r0 out 0x3f, r0 ; 63 pop r0 reti }
Oups, alles klar! "adiw" geht ja nur mit r24, r26, r28 und r30 Und diese Register sollten nicht ständig mit dem Counter-Wert besetzt sein!
Könnte man theoretisch das innerste push und pop für r0 weglassen ? Kommt mir irgendwie sinnlos vor... ISR(TIM1_COMPA_vect) { ac6: 1f 92 push r1 ac8: 0f 92 push r0 aca: 0f b6 in r0, 0x3f ; 63 ace: 11 24 eor r1, r1 counter++; ad0: 08 94 sec ad2: 21 1c adc r2, r1 ad4: 31 1c adc r3, r1 ad8: 0f be out 0x3f, r0 ; 63 ada: 0f 90 pop r0 adc: 1f 90 pop r1 ade: 18 95 reti
> Könnte man theoretisch das innerste push und pop für r0 weglassen?
Nö, damit würdest du ja jedem anderen das r0 klauen, der es gerade
in Beschlag hat.
Das push/pop und xor von r1 könnte man im Prinzip weglassen -- wenn
es nicht die leidige Multiplikation gäbe, die dieses Register
verändert. Ansonsten ist es im Compiler immer gleich 0.
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.