Forum: Compiler & IDEs naked ISR + register inc. SREG speichern ?


von Frank Roch (Gast)


Lesenswert?

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..

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Frank Roch (Gast)


Lesenswert?

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

von Peter (Gast)


Lesenswert?

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
}

von Peter (Gast)


Lesenswert?

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!





von Frank Roch (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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
Noch kein Account? Hier anmelden.