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!
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.
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.
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.
Mit andren Worten: Passt das Programm so wie es ist? Lieber einmal mehr Hinterfragen als einmal zu wenig ;)
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?
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.
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
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.
Man könnte speziell für den Fall des Aufrufes aus ISR ein interruptoptimierte Routine schreiben. Adib.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.