Hm. Welcher Anfänger hat den Artikel "FIFO" verbrochen ? uint8_t BufferIn(uint8_t byte) { //if (buffer.write >= BUFFER_SIZE) // buffer.write = 0; // erhöht sicherheit if ( ( buffer.write + 1 == buffer.read ) || ( buffer.read == 0 && buffer.write + 1 == BUFFER_SIZE ) ) return BUFFER_FAIL; // voll Hoffentlich hat noch niemand diesen Unfug gelesen ? Man stelle sich das mal vor, und setze im Geiste BUFFER_SIZE=2 und versuche zwei Elemente einzufügen, dann wirds offensichtlicher.. Setzen. sechs. Und das auskommentierte: Was bitte erhöht da die Sicherheit ? Das kaschiert allerhöchstens einen BUG der woanders gemacht wurde. Oder soll das für den Fall da sein, daß sich die CPU aus versehen mal verrechnet ?
:
Verschoben durch User
Frank schrieb: > Man stelle sich das mal vor, und setze im Geiste BUFFER_SIZE=2 und > versuche zwei Elemente einzufügen, dann wirds offensichtlicher.. Du willst also in einen Ringbuffer der Größe 2 zwei Elemente einfügen. Dann steht der Schreibindex unweigerlich auf dem Leseindex, und das ist die Abfrage-Bedingung für "Buffer ist leer" beim Lesen. Dir ist schon klar, wie ein Ringbuffer überhaupt funktioniert, oder? > Und das auskommentierte: Was bitte erhöht da die Sicherheit ? Das nennt man "defensive Programmierung", obwohl man in dem Fall natürlich besser stattdessen mit einem Fehlercode abbrechen sollte.
Verrate mir mal, warum man in ein Array daß zwei Elementen Platz bietet, keine zwei Elemente schreiben kann...??
...dem sprechen höchstens intellektuelle Schwierigkeiten entgegen, aber gewiss nicht die Logik :-)
Frank schrieb: > Verrate mir mal, warum man in ein Array daß zwei Elementen Platz > bietet, keine zwei Elemente schreiben kann...?? OK, Du weißt also, weas ein Array ist. Das ist schön. Dann befasse Dich auch mal damit, was ein RINGBUFFER ist und wie der funktioniert, bevor Du noch mehr Unsinn erzählst. Deine Frage ist unsinnig gestellt. Die Frage ist, wieso man in einen Ringbuffer der Größe N nicht N Elemente schreiben kann, und den Grund habe ich Dir bereits in meinem Vorposting verraten.
und wenn Du schon von "intellektuellen Schwierigkeiten" schreibst.. ja, die sind auf Deiner Seite. Wegen des Dunning-Kruger-Effektes. Du hast dermaßen keine Ahnung, daß Du nichtmal merkst, daß Du keine hast. Sorry, so sieht es aus.
Bei einem Ringpuffer MUSS man also grundsätzlich ein Element verschwenden, wenn es nach dir geht. Guck, so kann man feststellen ob im Puffer noch Platz ist: (Ich mach mir jetzt nicht die Mühe die Namen des "Beispiels" zu verwenden: int free = (head >= tail) ? (SIZE_OF_BUFFER - 1 - head + tail) : (tail - head - 1); Das habe ich mir übrigens nicht selbst ausgedacht, sondern ist Standard. Wenn free > 0 kannst du einfügen. Und, oh Wunder, plötzlich muss man kein Element mehr verschwenden. Es kommt vor, daß so ein Element mehrere KB groß ist. Aber wenns nach Dir geht, ist man gezwungen die zu verschwenden ?
Frank schrieb: > int free = (head >= tail) Dann gehen wir das mal durch unter der Annahme SIZE_OF_BUFFER==2, und zu Anfang seien head und tail beide auf 0. Der Buffer sei leer. Das erste Einfügen ist trivial, also ist head jetzt 1. Jetzt soll nochmal eingefügt werden. head>=tail 1>=0 ist TRUE, also ist free damit SIZE_OF_BUFFER - 1 - head + tail 2 - 1 - 1 + 0 0 > Wenn free > 0 kannst du einfügen Mithin kannst Du nach dem Einfügen eines Elementes kein zweites einfügen. Du bist am Zug. Da ein Mod beschlossen hat, das zu verschieben, daß Gäste nicht mehr auf den Beitrag antworten können, ist die Diskussion damit für mich leider beendet. Vielen Dank, liebe Moderation.
Nop schrieb: > Da ein Mod beschlossen hat, das zu verschieben, daß Gäste nicht mehr auf > den Beitrag antworten können, ist die Diskussion damit für mich leider > beendet. Vielen Dank, liebe Moderation. War sowieso überflüssig, hätte auch gleich kpl. in den Papierkorb verschoben werden können.
Nop schrieb: > Da ein Mod beschlossen hat, das zu verschieben, daß Gäste nicht mehr auf > den Beitrag antworten können, ist die Diskussion damit für mich leider > beendet. Vielen Dank, liebe Moderation. Es hat mit "Projekte und Code" einfach gar nichts zu tun. Da war es ursprünglich hingerotzt worden.
Wie man das in Software macht weiß ich nicht, aber in Hardware gibt es drei Fälle: - Im gleichen Takt wird aus dem FIFO gelesen und geschrieben. Das ist OK und da kann der FIFO auch gerne voll sein. - Es wird nur gelesen. FIFO darf nicht leer sein. - Es wird nur geschrieben. FIFO darf nicht voll sein. Man muss jedenfalls keinen Speicherplatz verschwenden.
Wenn hier etwas hingerotzt ist, dann der Artikel .) Gustl, danke. Ok, ich gebe zu, das int free... reicht nicht aus. Im Gegensatz zu anderen hier habe ich kein Problem damit Fehler zuzugeben :) Aber so geht es tatsächlich, ohne ein Element zu verschwenden: #define BUFFER_FAIL 0 #define BUFFER_SUCCESS 1 #define BUFFER_SIZE 2 struct Buffer { uint8_t data[BUFFER_SIZE]; uint8_t read; // zeigt auf das Feld mit dem ältesten Inhalt uint8_t write; uint8_t count; // zähler <!--- NEU } buffer = {{}, 0, 0}; // // Gibt an wieviel Platz im Puffer ist // // uint8_t BufferAvailable(void) { return BUFFER_SIZE - buffer.count; } // // Stellt 1 Byte in den Ringbuffer // // Returns: // BUFFER_FAIL der Ringbuffer ist voll. Es kann kein weiteres Byte gespeichert werden // BUFFER_SUCCESS das Byte wurde gespeichert // uint8_t BufferIn(uint8_t byte) { if (BufferAvailable() < 1) return BUFFER_FAIL; //Voll buffer.data[buffer.write] = byte; buffer.write++; if (buffer.write >= BUFFER_SIZE) buffer.write = 0; buffer.count++; return BUFFER_SUCCESS; } // // Holt 1 Byte aus dem Ringbuffer, sofern mindestens eines abholbereit ist // // Returns: // BUFFER_FAIL der Ringbuffer ist leer. Es kann kein Byte geliefert werden. // BUFFER_SUCCESS 1 Byte wurde geliefert // uint8_t BufferOut(uint8_t *pByte) { if (buffer.count == 0) return BUFFER_FAIL; *pByte = buffer.data[buffer.read]; buffer.read++; if (buffer.read >= BUFFER_SIZE) buffer.read = 0; buffer.count--; return BUFFER_SUCCESS; } Und bevor jetzt jemand schreit, daß der Zähler auch Platz braucht: Stimmt! Aber Ringpuffer werden auch für größere Elemente als Bytes verwendet. Bitte tut euch selbst den Gefallen und korrigiert den Artikel, oder fügt zumindest eine Info hinzu. Vor allem dieser oben erwähnte wirklich fürchterliche Kommentar sollte raus.
> Bitte tut euch selbst den Gefallen und korrigiert den Artikel, oder fügt > zumindest eine Info hinzu. Vor allem dieser oben erwähnte wirklich > fürchterliche Kommentar sollte raus. Der steht im Wiki - was hindert Dich daran, das selbst in Ordnung zu bringen? Du hast Deine "Kritik" in "Projekte & Code" abgesetzt, da hat sie schlichtweg nichts verloren. Hättest Du sie in "Smarthome" abgesetzt, oder in "Analoge Elektronik", sähe das nicht anders aus.
"Wiki":War mir nicht bekannt. Ich überlasse das trotzdem lieber euch. Bitte nenne mir eine Rubrik die besser passt, dann poste ich das nächste mal dort. Das "Offtopic" der richtige Ort ist - darauf muss man erstmal kommen.
Frank K. schrieb: > Das "Offtopic" der richtige Ort ist Dass man in diesem Fall dass mit Doppel-s schreibt, hättest du aber durchaus wissen können...
:
Bearbeitet durch User
Frank schrieb: > Welcher Anfänger hat den Artikel "FIFO" verbrochen ? 1. du plenkst. https://de.wikipedia.org/wiki/Plenk Bitte stell das ab. 2. ein Wiki ist ein Wiki ist ein Wiki. Artikel werden nicht dadurch besser, daß jemand (s)einen Rant ins Forum kotzt, sondern dadurch daß sie korrigiert werden. Klick dir einen Account (hast du wohl mittlerweile?) und korrigiere den Artikel. Fertig. Damit ist allen Beteiligten besser gedient. PS: falls es Diskussionsbedarf zu einem Artikel im Wiki gibt: dafür gibt es extra den Link "Diskussion" im linken Menu unter "Dieser Artikel"
:
Bearbeitet durch User
...mich verstört auch die Tatsache, dass die Implementierung mit sperren der Interrupts empfohlen wird. Bei geschickter Programmierung ist das überhaupt nicht notwendig, da man das Update der Pointer atomar mit einer Zuweisung am Ende machen kann. Die Variante mit dem Counter ist dann allerdings nicht möglich, da die "++" Operation nicht zwingend atomar ist.
Markus M. schrieb: > ...mich verstört auch die Tatsache, dass die Implementierung mit sperren > der Interrupts empfohlen wird. > > Bei geschickter Programmierung ist das überhaupt nicht notwendig, da man > das Update der Pointer atomar mit einer Zuweisung am Ende machen kann. Das will ich sehen!
Wer langeweile hat kann ja den Code hier ins wiki packen:
1 | //FIFO Zustandsvariablen
|
2 | static struct fifo_vars fifo1_tx; |
3 | |
4 | //FIFO Speicherbereich
|
5 | static char buf_fifo1_tx[FIFO_SIZE]; |
6 | |
7 | fifo_init(fifo1_tx, buf_fifo1_tx, FIFO_SIZE, uart_nbr, 1); |
Markus M. schrieb: > da man das Update der Pointer atomar mit einer Zuweisung am Ende machen > kann. Atomare 16-Bit-Operationen auf einem 8-Bit-µC? Das ginge allenfalls, wenn nicht mit Pointern, sondern Array-Indices gearbeitet würde, und diese nur 8 Bit groß sind, das Fifo also maximal 256 Einträge enthalten dürfte. Oder der Compiler müsste wissen, daß er die Pointer zwingend in einem 16-Bit-Indexregister des µCs vorzuhalten hat, damit er sie atomar speichern kann. Welcher Compiler aber weiß etwas von atomaren Operationen und den interessanten Auswirkungen von Interrupts?
Frank schrieb: > Verrate mir mal, warum man in ein Array daß zwei Elementen Platz > bietet, > keine zwei Elemente schreiben kann...?? Aus Performancegründen wird lediglich mit Head und Tail Indizes gearbeiten. Dafür nimmt man gerne den einen verschwendeten Spot in Kauf. Siehe bspw. die Implementierung von boost::lockfree::spsc_queue.
Rufus Τ. F. schrieb: > Markus M. schrieb: >> da man das Update der Pointer atomar mit einer Zuweisung am Ende machen >> kann. > > Atomare 16-Bit-Operationen auf einem 8-Bit-µC? > > Das ginge allenfalls, wenn nicht mit Pointern, sondern Array-Indices > gearbeitet würde, und diese nur 8 Bit groß sind, das Fifo also maximal > 256 Einträge enthalten dürfte. Ja, genauso tut es doch der Code hier im Beispiel. Es wird uint8_t verwendet. Ich nahm jetzt mal diese Implementierung als Ausgangspunkt, auch wenn Pointer ggf. effizienter sind. Auf einem 32 Bit Controller sollte das ja kein Problem sein. Wenn man beim Schreiben so vorgeht: - Wert in das aktuell referenzierte Byte im FIFO schreiben - FIFO Schreibpointer updaten (Voraussetzung: atomar) Und beim Lesen so: - Wert aus dem aktuell refrenzierten Byte aus dem FIFO lesen - FIFO Lesepointer updaten (Voraussetzung: atomar) Müssen KEINE Interrupts gesperrt werden.
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.