Forum: Compiler & IDEs interrupts deaktivieren


von schnudl (Gast)


Lesenswert?

im avr-libc user manual wird folgende vorgangsweise für das aus- und 
wiedereinschalten des globalen Interruptflags empfohlen:

uint8_t tmp_sreg = SREG;
// ??
cli();
...
SREG = tmp_sreg;

Soweit klar, nur was passiert, wenn ein anderer Interrupt genau an der 
mit ?? bezeichneten Stelle zuschlägt ? Der kann dann SREG verändern, und 
das Programm könnte dadurch durcheinanderkommen, da der unter tmp_sreg 
gespeicherte Wert u.U nicht mehr aktuell ist. Oder sehe ich das falsch ?

Falls das stimmt, wie kann man dieses Problem umgehen ?


--
Danke
Michael

von Uhu U. (uhu)


Lesenswert?

Dann wird der Vordergrund an genau der Stelle unterbrochen. Da die ISR 
das SREG speichern und wiederherstellen muß, passiert nichts.

von Johannes M. (johnny-m)


Lesenswert?

Im SREG interessiert an der Stelle ausschließlich das I-Bit. Wenn das 
vorher schon gelöscht war, dann kann gar kein Interrupt dazwischenhauen. 
Wenn es gesetzt war, dann wird es auch hinterher wieder gesetzt, auch 
wenn ein Interrupt dazwischenkommt.

von schnudl (Gast)


Lesenswert?

Danke für die Antworten - Schon klar. Mir ist es um den 
unwahrscheinlichen Fall gegangen, dass die ISR dass I Flag löscht und 
somit Interrupts ausschaltet - oder ist das "nicht erlaubt" ? Könnte ja 
sein, dass dieses I Flag dann im Hauptthread wieder gesetzt wird, 
nachdem einige Dinge abgearbeitet worden sind. Ich selbst würde das zwar 
nicht so machen, aber in einem solchen Fall wäre das Löschen des Bits 
jedenfalls verschwunden.

Die Frage geht auch darauf hinaus, ob es möglich ist, zusammengehörende 
Programmbereiche ununterbrechbar zu machen. Woanders kenne ich zB. ein 
"atomic" Schlüsselwort.

von schnudl (Gast)


Lesenswert?

Und da gleich nochwas:

Kann man sich darauf verlassen, dass zB eine Zuweisung von Werten an 
variablen mit mehr als 1 Byte (zB long) nicht "zerrissen" werden kann? 
Oder wäre dies denkbar ? Denn es stecken ja mehrere Maschinenbefehle 
dahinter. Dann müsste man wieder mit dem I-Bit arbeiten, wenn man es 
vermeiden möchte?

von Peter D. (peda)


Lesenswert?

schnudl wrote:
> Danke für die Antworten - Schon klar. Mir ist es um den
> unwahrscheinlichen Fall gegangen, dass die ISR dass I Flag löscht und
> somit Interrupts ausschaltet - oder ist das "nicht erlaubt" ?

Erlaubt schon, allerding kein guter Programmierstil.
In der Regel macht man sowas nur, wenn man vorher die Aufgabe nicht 
durchdacht hat. Wenn ein Interrupt schon was sperren muß, dann nur 
einzelne Interrupts, aber nicht global.


Ich setze mir allerdings das Ziel, daß ich nicht über längere 
Funktionsaufrufe Interrupts sperre und auch Funktionen nicht 
gleichzeitig im Main und in Interrupts aufrufe.
Dann kann man sich das Sichern des SREG sparen und schreibt direkt 
CLI+SEI um den atomaren Ausdruck.

Du kannst Dir ja Macros schreiben:
1
#define atomic cli();
2
#define end_atomic sei();


Peter

von Falk B. (falk)


Lesenswert?

@ schnudl (Gast)

>unwahrscheinlichen Fall gegangen, dass die ISR dass I Flag löscht und

Eine ISR löscht beim AVR IMMER das I-Bit. Und am Ende wird es immer mit 
RETI wieder gesetzt.

>somit Interrupts ausschaltet - oder ist das "nicht erlaubt" ? Könnte ja

Dasist SEHR unüblich. Interruptsrutinen setzen/löschen bestenfalls die 
inidividuellen Maskenbits für Timer, UARt etc., aber so gut wie nie das 
I-Bit der CPU.

>Die Frage geht auch darauf hinaus, ob es möglich ist, zusammengehörende
>Programmbereiche ununterbrechbar zu machen. Woanders kenne ich zB. ein
>"atomic" Schlüsselwort.

Eben mit der gezeigten Abfolge werden deine Befehle atomar. NAch dem 
cli() spuckt dir keiner mehr dazwischen.

Interrupt

MFg
Falk

von schnudl (Gast)


Lesenswert?

alles klar. danke

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.