Forum: Compiler & IDEs FIFO mit Interruptsperre


von Unwissender (Gast)


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!

von Stefan E. (sternst)


Lesenswert?

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.

von Unwissender (Gast)


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.

von Karl H. (kbuchegg)


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.

von Unwissender (Gast)


Lesenswert?

Mit andren Worten:
Passt das Programm so wie es ist?
Lieber einmal mehr Hinterfragen als einmal zu wenig ;)

von Unwissender (Gast)


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?

von Karl H. (kbuchegg)


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.

von Peter D. (peda)


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

von Karl H. (kbuchegg)


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.

von Adib T. (adib_t)


Lesenswert?

Man könnte speziell für den Fall des Aufrufes aus ISR ein 
interruptoptimierte Routine schreiben.

Adib.

von Peter D. (peda)


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

von Unwissender (Gast)


Lesenswert?

Passt das so wie hier?

http://www.rn-wissen.de/index.php/UART_mit_avr-gcc   (2. Variante)

Hier wird ja, falls das Ausgabe-FIFO voll ist bei
int16_t uart_putc(uint8_t c)
eine 0 ausgegeben, andernfalls eine 1.

Falls man die Daten die man am AVR reinbekommt nicht schneller 
abarbeiten kann als sie reinkommen, kann man ja Handshaken.

Gruß

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.