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.