Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage atomare Operationen durch cli/sei


von McLovin (Gast)


Lesenswert?

Manchmal muss man verhindern, dass sich main-Code und ISR in die Quere 
kommen, beispielsweise wenn man mit int16_t arbeitet, da die zur 
Behandlung immer mindestens zwei Anweisungen brauchen.

Es wird dann immer die Vorgehensweise mittels cli und sei bzw. die 
Methoden aus util/atomic.h empfohlen, also
1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
2
// Kritische Sektion, die in einem Zug abgearbeitet werden soll
3
}

Meine Frage wäre jetzt, ob man dadurch nicht evtl. wichtige Updates 
verpasst? Bei einem Timer ist es vielleicht noch OK, weil der dann eben 
später noch mal auslöst, aber was ist mit TWI/SPI/UART oder externen 
PIN-Interrupts, die verpasst man dann evtl. doch, wenn man ab und zu die 
Interrupts ausschaltet, oder habe ich da einen Denkfehler?

von McLovin (Gast)


Lesenswert?

Ach so, es geht hier natürlich um Atmel AVRs, das sollte der 
Vollständigkeit halber noch erwähnt werden.

von holger (Gast)


Lesenswert?

>Bei einem Timer ist es vielleicht noch OK, weil der dann eben
>später noch mal auslöst, aber was ist mit TWI/SPI/UART oder externen
>PIN-Interrupts, die verpasst man dann evtl. doch, wenn man ab und zu die
>Interrupts ausschaltet, oder habe ich da einen Denkfehler?

Das kommt darauf an wie lang deine ATOMIC_BLOCK sind.
Wenn du da Unsinn machst wie LCD Ausgaben oder printf()
Dann kannst du auch beim Timer Probleme bekommen.

Halt den Kram kurz der im ATOMIC_BLOCK steht und du hast auch
keine Probleme mit andere Peripherie.

von Cyblord -. (cyblord)


Lesenswert?

McLovin schrieb:
> Manchmal muss man verhindern, dass sich main-Code und ISR in die Quere
> kommen, beispielsweise wenn man mit int16_t arbeitet, da die zur
> Behandlung immer mindestens zwei Anweisungen brauchen.
>
> Es wird dann immer die Vorgehensweise mittels cli und sei bzw. die
> Methoden aus util/atomic.h empfohlen, also
>
>
1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
2
> // Kritische Sektion, die in einem Zug abgearbeitet werden soll
3
> }
>
> Meine Frage wäre jetzt, ob man dadurch nicht evtl. wichtige Updates
> verpasst? Bei einem Timer ist es vielleicht noch OK, weil der dann eben
> später noch mal auslöst, aber was ist mit TWI/SPI/UART oder externen
> PIN-Interrupts, die verpasst man dann evtl. doch, wenn man ab und zu die
> Interrupts ausschaltet, oder habe ich da einen Denkfehler?

Verpasst wird zumindest der 1. Interrupt pro Quelle nicht, da das 
Interrupt-Flag gesetzt wird und somit die ISR sofort nach dem Ende 
deines Atomic Blocks angesprungen wird. Er wird natürlich dann etwas 
verzögert ausgeführt und weitere Interrupts werden natürlich auch nicht 
erfasst.
Einen Tod musst du sterben, entweder sofortige Reaktion auf Interrupts 
oder Unterbrechungsfreien Code.

gruß cyblord

von McLovin (Gast)


Lesenswert?

OK, also wenn ich nur eine Variable vergleiche und auf 0/1 setze sind 
das zusammen mit abschließendem sei() ca. 8 Taktzyklen, ich denke mal 
das ist schnell genug.

Das mit dem 1. Interrupt ist schon mal gut zu wissen, das Datenblatt vom 
ATmega8 ist zu dem ganzen Thema relativ knapp gehalten. Das heißt, 
selbst wenn in den 8 Taktzyklen ein Timer überläuft, wird die Timer-ISR 
direkt nach dem Aufruf von sei() ausgeführt?

von c-hater (Gast)


Lesenswert?

McLovin schrieb:

> Manchmal muss man verhindern, dass sich main-Code und ISR in die Quere
> kommen, beispielsweise wenn man mit int16_t arbeitet, da die zur
> Behandlung immer mindestens zwei Anweisungen brauchen.
>
> Es wird dann immer die Vorgehensweise mittels cli und sei bzw. die
> Methoden aus util/atomic.h empfohlen, also
>
>
1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
2
> // Kritische Sektion, die in einem Zug abgearbeitet werden soll
3
> }
>
> Meine Frage wäre jetzt, ob man dadurch nicht evtl. wichtige Updates
> verpasst?

Das ist einerseits möglich, andererseits leider aber auch unvermeidbar.

Man kann die Gefahr nur minimieren, indem man an allen Fronten die 
Phasen exclusiver Codeausführung minimiert. Dazu gehören neben den 
expliziten cli..sei-Konstrukten insbesondere auch die ISRs, denn die 
implizieren ein cli..sei.

> Bei einem Timer ist es vielleicht noch OK, weil der dann eben
> später noch mal auslöst, aber was ist mit TWI/SPI/UART oder externen
> PIN-Interrupts, die verpasst man dann evtl. doch

Du hast das nicht ganz verstanden. Wirklich verpasst wird nur dann 
etwas, wenn eine Sperre lange genug anhält, um ZWEI Ereignisse einer 
Kategorie zu verpassen. Nur ein Ereignis während der Sperre ist ein 
kleineres Problem. Das wird nicht verpaßt, sondern nur verspätet (nach 
Ende der Sperre) bearbeitet.

von holger (Gast)


Lesenswert?

>OK, also wenn ich nur eine Variable vergleiche und auf 0/1 setze sind
>das zusammen mit abschließendem sei() ca. 8 Taktzyklen, ich denke mal
>das ist schnell genug.

Das geht schneller. Kopiere im ATOMIC_BLOCK einfach die gewünschte
Variable in eine temporäre Variable. Vergleichen und irgendwas auf
0/1 setzen und sonstiger Klimbim dann ausserhalb des ATOMIC_BLOCK.

von Carsten R. (kaffeetante)


Lesenswert?

Aus dem handbuch des ATMega16:

"There are basically two types of interrupts. The first type is 
triggered by an event that sets the interrupt flag. For these 
interrupts, the Program Counter is vectored to the actual Interrupt 
Vector in order to execute the interrupt handling routine, and hardware 
clears the corresponding interrupt flag. Interrupt flags can also be 
cleared by writing a logic one to the flag bit position(s) to be 
cleared. If an interrupt condition occurs while the
corresponding interrupt enable bit is cleared, the interrupt flag will 
be set and remembered until the interrupt is enabled, or the flag is 
cleared by software. Similarly, if one or more interrupt conditions 
occur while the Global Interrupt Enable bit is cleared, the 
corresponding interrupt flag(s) will be set and remembered until the 
global interrupt enable bit is set, and will then be executed by order 
of priority.

The second type of interrupts will trigger as long as the interrupt 
condition is present. These interrupts do not necessarily have interrupt 
flags. If the interrupt condition disappears before the interrupt is 
enabled, the interrupt will not be triggered."

Das heißt die erste Gruppe an Interrupts verpaßt du nicht, auch wenn du 
atomare operationen verwendest, da der Chip sich das Flag merkt bis es 
abgearbeitet wird. Du mußt aber dafür sorgen, daß die Verzögerungen bei 
zeitkritischen Ereignissen nicht zu groß werden (beispielsweise 
Stichwort: Pufferüberlauf).

Die zweite Gruppe von Ereignissen könntest Du theoretisch verpassen. Das 
wäre allerdings ein generelles Problem und nicht an die Thematik 
"atomic" gebunden. Nicht nur Atomics deaktivieren kurzfristig 
Interrupts. Sie tun dies wie Du sagst per entsprechender 
Prozessorbefehle im Code. Auch ISR tun dies, aber automatisch in 
Hardware. Solange eine ISR läuft können keine weiteren Interrupts 
ausgelöst werden, es sei denn man implementiert nested Interrupts. Aber 
auch da gibt es eine kurze Blockadezeit.

Wenn das kritisch ist mußt Du dein Konzept anpassen, sei es in Software 
oder in Hardware, so daß kurze "black-outs" der Interrupts tollerierbar 
sind oder anderwertig gespeichert und überbrückt werden. Alternativ kann 
man auch alle konkurrierenden Interrupts maskieren. Aber will man das?

: Bearbeitet durch User
von Carsten R. (kaffeetante)


Lesenswert?

McLovin schrieb:
> Das heißt,
> selbst wenn in den 8 Taktzyklen ein Timer überläuft, wird die Timer-ISR
> direkt nach dem Aufruf von sei() ausgeführt?

Ja, es sei denn es ist noch ein anderer Interrupt mit höherer Priorität 
aktiviert und ausgelöst worden und wartet auf seine Ausfhrung. Dann 
kommt der Timer erst danach. Die Abarbeitung der Interruptflags erfolgt 
nicht chronologisch, sondern nach Prioritäten. Die Prioritäten 
entsprechen beim AVR der Reihenfolge der Vektoren. Reset hat also die 
höchste Priorität. Was darunter steht hat eine niedrigere Priorität. 
Theoretisch könnte so ein Interrupt also lange bis ewig warten.

Ein Grund mehr ISRs genau wie atomics immer möglichst kurz halten. Je 
länger die Routinen sind, um so höher ist die Wahrscheinlichkeit, daß 
sich solche Ereignisse zumindest vorrübergehend Verketten können, was zu 
schwer bis gar nicht nachvollziehbaren Verzögerungen der Ausführung 
führen kann.

von McLovin (Gast)


Lesenswert?

Alles klar, vielen Dank!

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.