SREG innerhalb ISR speichern?

OP #497376
Lesenswert?

Hallo,

ich habe mich gerade im AVR-GCC-Tutorial den Abschnitt gelesen, wie man 
Codesequenzen schreibt, welche via Interrupt nicht unterbrochen werden 
können.

Macht es Sinn, diesen Ansatz auch innerhalb von ISR zu nutzen?

//timer 2 overflow
SIGNAL(SIG_OVERFLOW2)
{
  uint8_t tmp_sreg = SREG;
  cli();

  TCNT2 = 0xE0;
  //mach irgendwas...

  SREG = tmp_sreg;
}

Viele Grüße
Tommy
Gast #497393
Lesenswert?

Ernsthaft:
Er arbeitet die ISR zuende ab, springt dahin zurück, wo er herkam, gibt 
wieder alle Interrupts frei und stellt fest, dass da ein freigegebener 
Interrupt aufgetreten ist. Und springt in dessen ISR.

AVR haben keine Interrupt-Prioritäten wie sie z.B. die 8051er haben.
Gast #497419
Lesenswert?

Wenn eine ISR verlassen wird und in der Zwischenzeit (also während die 
ISR ausgeführt wurde) andere Interrupts aufgetreten sind, werden diese 
nach dem Rücksprung ins Hauptprogramm in der Reihenfolge abgearbeitet, 
wie sie in der Vektortabelle stehen (je niedriger die Vektoradresse, 
desto höher die "Pseudo-Priorität". "Pseudo" deshalb, weil es keine 
"echte" Priorität im Sinne von "höhere Priorität unterbricht niedrigere 
Priorität" ist, sondern lediglich eine Abarbeitungsreihenfolge). Es kann 
natürlich dadurch passieren, dass ein Interrupt mit niedriger Adresse so 
oft auftritt, dass nur noch dieser bearbeitet wird, aber das ist dann 
ein Fehler des Programmierers...

Außerdem wird beim Einsprung in eine ISR automatisch durch die Hardware 
des Controllers das I-Bit im SREG gelöscht, so dass man das nicht von 
Hand machen muss. Es wird erst beim Verlassen der ISR wieder gesetzt 
(auch automatisch durch die Hardware). Deshalb ist ein cli() am Anfang 
der ISR überflüssig.
#497436
Lesenswert?

Mit Ausnahme des alten AT90S1200 hat bei den AVRs jede Interruptquelle 
ein Pending-Flag. Damit merkt sich der AVR, daß noch ein Interrupt 
anhängig ist und versucht ihn sobald wie möglich auszuführen.

Alternativ kann man dieses Pending-Flag auch pollen und löschen, wenn 
man das Ereignis ohne Interrupt behandeln will.

Auch kann es sein, daß man nach Verlassen des Interrupts oder längerer 
Interruptsperre garnicht mehr an älteren Ereignissen interessiert ist, 
dann löscht man das Pending-Bit unmittelbar vor dem RETI bzw. SEI.

Und daß man Pending Bits beim AVR nicht mit 0 löschen kann, weiß ja 
jeder.


Peter

Gast #497438
Lesenswert?

@johnny.m

>(auch automatisch durch die Hardware). Deshalb ist ein cli() am Anfang
>der ISR überflüssig.

Um die Restaurierung des SREG braucht man sich in ISR und C doch sowieso 
keine Gedanken zu machen, das macht der Compiler doch automatisch.

MFG
Falk
Gast #497459
Lesenswert?

@Falk:
Habe ich mit irgendeinem Wort die SREG-Restaurierung erwähnt? Es ging 
mir nur darum, dass das cli() und sei() durch die Controller-Hardware 
erledigt wird und deshalb im Programm überflüssig ist. Der Controller 
sorgt ganz alleine (und zwar völlig unabhängig von der Art der 
Programmierung) dafür, dass ISRs ohne weiteren Eingriff des 
Programmierers nicht unterbrochen werden können. Das SREG-sichern und 
zurückschreiben ist eine ganz andere Sache.
Gast #497515
Lesenswert?

>Außerdem wird beim Einsprung in eine ISR automatisch durch die Hardware
>des Controllers das I-Bit im SREG gelöscht, so dass man das nicht von
>Hand machen muss.

Richtig.

>Es wird erst beim Verlassen der ISR wieder gesetzt
>(auch automatisch durch die Hardware).

Kleine Korrektur: Nicht automatisch.  Das I-Flag wird durch die 
"reti"-Instruktion genau im Moment (!) des Rücksprungs wieder gesetzt. 
Schreibt der Programmierer fälschlicherweise (oder auch absichtlich) nur 
ein "ret", so bleibt das I-Flag gelöscht, und alle Interrupts auch nach 
Verlassen des Interruptshandlers gesperrt.
Gast #497527
Lesenswert?

@AVRFan:
Eine ISR dauert grundsätzlich so lange, bis ein "reti" auftaucht, egal 
was sonst noch an programmiertechnischem Wahnsinn getrieben wird. Wenn 
kein "reti" da ist, obwohl da eins sein sollte, dann hat der 
Programmierer großen Mist gebaut. Das läuft dann unter "grober 
Programmfehler". Ich meinte oben natürlich "beim ordnungsgemäßen 
Verlassen der ISR" (hätte ich vll. direkt dazuschreiben sollen...). Und 
dabei macht die Hardware dann auch das, was sie soll. Solche Sachen 
nimmt einem aber tatsächlich der Compiler ab (genau wie das 
SREG-Sichern).
Moderator Persönliche Seite #497528
Lesenswert?

Peter Dannegger wrote:

> Mit Ausnahme des alten AT90S1200 hat bei den AVRs jede Interruptquelle
> ein Pending-Flag. Damit merkt sich der AVR, daß noch ein Interrupt
> anhängig ist und versucht ihn sobald wie möglich auszuführen.

Eine Einschränkung: pegelgesteuerte Externinterrupts bleiben nur
so lange anhängig, wie der entsprechende Pegel tatsächlich anliegt.
Verschwindet er also wieder, während die Interruptbearbeitung
gerade gesperrt ist, dann wird danach die zugehörige ISR nicht
abgearbeitet.  (War zumindest bis ATmega16...128 noch so, aktuell
habe ich da lange nicht mehr das Kleingedruckte im Datenblatt
gelesen.)
Gast #497759
Lesenswert?

>Eine ISR dauert grundsätzlich so lange, bis ein "reti" auftaucht, egal
>was sonst noch an programmiertechnischem Wahnsinn getrieben wird.

Ein "ret" beendet eine ISR gleichermaßen. Auch dann kehrt das Programm 
schließlich an die Stelle zurück, wo der Interrupt aufgetreten ist, und 
macht mit der nächsten Instruktion dort weiter. Lediglich das I-Flag 
bliebe bei "ret" gelöscht - so what?  Ich könnte mir sogar 
Anwendungsfälle vorstellen, in denen das gewünscht ist (Beispiel: ein 
externer Interrupt soll nur genau einmal ausgelöst werden können). Dann 
spräche nicht das Geringste dagegen, ans Ende der entsprechenden ISR 
tatsächlich ein "ret" statt eines "reti" zu schreiben.

>Solche Sachen nimmt einem aber tatsächlich der Compiler ab (genau wie das
>SREG-Sichern).

Sofern man mit einem solchen arbeitet. Aber bitte keine 
Grundsatzdiskussion über Vor- und Nachteile von 
Assemblern/Compilern/Whatever jetzt... lach
Gast #497802
Lesenswert?

@AVRFan:
Naja, da kann man jetzt tatsächlich endlos drüber diskutieren... Fest 
steht: Wenn man eine ISR mit einem ret beendet anstatt mit reti, dann 
sollte man schon ganz genau wissen, was man da tut. Oder die "i"-Taste 
ist kaputt...;-)

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