FIFO mit Interruptsperre

Gast #2630535
Lesenswert?

Hallo Forumsgemeinde!

Ich bin gerade dabei mich mit folgendem Artikel auseinanderzusetzen:

http://www.rn-wissen.de/index.php/FIFO_mit_avr-gcc

In beiden Inline-Funktionen im Header ist mir nicht ganz klar warum 
ausgerechnet über

f->count++;

bzw.

f->count--;

eine Interruptsperre ist.

Besten Dank für eine Antwort!
Gast #2630581
Lesenswert?

Stefan Ernst schrieb:
> Weil das ein RMW-Zugriff ist, der an beiden Enden des FIFOs stattfindet,
> und in der Regel ein Ende des FIFOs per Interrupt bedient wird.

Heißt das soviel, dass die beiden Operationen nicht atomar ausgeführt 
werden?

Müssten eig die kompletten Funktionen in einer Interruptsperre sein?
Da hier ja soweit ich seh sämtliche Zeiger der Reihe nach verändert 
werden, und wenn dazwischen ein Interrupt mit einem FIFO-Zugriff 
ausgelöst wird die neu aufgerufene Funktion falsche Zeigerwerte 
übergeben bekommen würde.
#2630600
Lesenswert?

Unwissender schrieb:

> Müssten eig die kompletten Funktionen in einer Interruptsperre sein?
> Da hier ja soweit ich seh sämtliche Zeiger der Reihe nach verändert
> werden, und wenn dazwischen ein Interrupt mit einem FIFO-Zugriff
> ausgelöst wird die neu aufgerufene Funktion falsche Zeigerwerte
> übergeben bekommen würde.

Es sind aber nicht dieselben Werte in der put und in der get Funktion. 
Erst durch die Manipulation von count wird die Operation, man könnte 
sagen, gültig. Und da darf der jeweilige Gegenpart nicht 
dazwischenkommen.
Gast #2630897
Lesenswert?

Eine Frage hätt ich noch.
Warum wird hier das komplette SREG-Register immer gerettet?
Es wurde hier doch nur das I-Flag verändert und nichts weiter.
Wäre nur ein sei() hier nicht einfacher?
#2630941
Lesenswert?

Unwissender schrieb:
> Eine Frage hätt ich noch.
> Warum wird hier das komplette SREG-Register immer gerettet?
> Es wurde hier doch nur das I-Flag verändert und nichts weiter.
> Wäre nur ein sei() hier nicht einfacher?

Weil du in der Funktion nicht weißt, ob nicht vom Aufrufer die 
Interrupts mittelse sei() bereits gesperrt wurden. Und der hätte was 
dagegen, wenn die Funktion die Interrupts einfach freigeben würde.
Detto, wenn die Funktion aus einer ISR heraus aufgerufen wird.

Daher: Interrupts nicht einfach: sperren und freigeben
sondern   sperren und den vorhergehenden Zustand wieder herstellen.
#2631006
Lesenswert?

Karl Heinz Buchegger schrieb:
> Weil du in der Funktion nicht weißt, ob nicht vom Aufrufer die
> Interrupts mittelse sei() bereits gesperrt wurden.

In der Regel weiß man es aber.
Da in Interrupts kein Atomic nötig ist.
Und da nach dem Init Interrupts immer enabled sind.

Wenn man also nicht irgendwelche ganz speziellen Schweinereien vorhat, 
ist ein cli/sei vollkommen ausreichend.

Im AVR-GCC entspricht das dem:
1
ATOMIC_BLOCK(ATOMIC_FORCEON){
2
// atomic code
3
}


Peter
#2631194
Lesenswert?

Peter Dannegger schrieb:

> In der Regel weiß man es aber.

Peter.
Der verlinkte Code ist eine allgemeine FIFO.
Einsatzort: unbekannt. Kann daher sowohl innerhalb als auch ausserhalb 
einer ISR benutzt werden sowie in Funktionen die selbst aus irgendeinem 
Grund unter Interruptsperre laufen.
Und für diese Fälle hat der Programmierer vorgesorgt. Getreu dem Motto: 
Lieber ein wenig langsamer und dafür richtig als schnell und falsch.
Einer Sichtweise, der ich für allgemein verwendbaren Module, die in 
einem Common-Lib Verzeichnis liegen, durchaus etwas abgewinnen kann.
#2635605
Lesenswert?

Adib T. schrieb:
> Man könnte speziell für den Fall des Aufrufes aus ISR ein
> interruptoptimierte Routine schreiben.

Man könnte nicht nur, man sollte auch.
Man muß ja auch den Sendeinterrupt freigen. Und ist der Sendepuffer 
voll, muß man warten.
Und man hat beim Empfang 3 Byte mehr Puffer, ehe es zu einem Überlauf 
kommt. Dazu muß man nur den Empfangsinterrupt sperren, wenn der 
SW-Puffer voll ist. Einen wirklichen Überlauf kann man dann mit dem 
UART-Flag abtesten.


Peter

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