FIFO Buffer in C

Gast #810814
Lesenswert?

Du legst ein Array vom Typ der zu speichernden Daten an.
Du definierst zwei Zeiger. Einen für die Stelle, an die du
Daten schreibst, einen für die Stelle, wo du die Daten wieder ausliest.
Nach jeder Schreib- oder Leseoperation erhöhst du den jeweiligen
Zeiger. Wenn ein Zeiger über das Ende des Arrays hinausgeht, setzt
du ihn wieder auf Null.

Soweit das mal ganz grob umrissen.
#810869
Lesenswert?

Source Schnippsel:
////////////////////////////////////
#define CON_OUT_BUF_SIZE           64

/* Buffer masks */
#define CON_OUT_MASK               (CON_OUT_BUF_SIZE-1ul)

/* Buffer read / write macros */
#define CON_BUF_RESET(Fifo)      (Fifo->rd_idx = Fifo->wr_idx = 0)
#define CON_BUF_WR(Fifo, dataIn) (Fifo->data[CON_OUT_MASK & 
Fifo->wr_idx++] = (dataIn))
#define CON_BUF_RD(Fifo)         (Fifo->data[CON_OUT_MASK & 
Fifo->rd_idx++])
#define CON_BUF_EMPTY(Fifo)      ((CON_OUT_MASK & Fifo->rd_idx) == 
(CON_OUT_MASK & Fifo->wr_idx))
#define CON_BUF_FULL(Fifo)       ((CON_OUT_MASK & Fifo->rd_idx) == 
(CON_OUT_MASK & Fifo->wr_idx+1))
#define CON_BUF_COUNT(Fifo)      ((CON_OUT_MASK & Fifo.wr_idx) - 
(CON_OUT_MASK & Fifo.rd_idx))

// Serial output buffer
typedef struct {
  unsigned char data[CON_OUT_BUF_SIZE];
  unsigned int wr_idx;
  unsigned int rd_idx;
} CON_Fifo_t;
Gast #810951
Lesenswert?

Hi

>Du legst ein Array vom Typ der zu speichernden Daten an.
>Du definierst zwei Zeiger. Einen für die Stelle, an die du
>Daten schreibst, einen für die Stelle, wo du die Daten wieder ausliest.
>Nach jeder Schreib- oder Leseoperation erhöhst du den jeweiligen...

Das ist ein Ringpuffer und kein FIFO. Da reicht ein Zeiger, der nach dem 
Schreiben um 1 erhöht und vor dem Lesen um 1 erniedrigt wird.

MfG Spess
#813095
Lesenswert?

Ich hab das mal mit Maske probiert, spart tatsächlich einige Bytes Code.

Blöd ist nur, daß auch der SRAM in 2-er Potenzen organisiert ist.

Wenn ich also nen Puffer beim ATtiny45 einrichte und 18 Byte für Stack 
und Variablen reserviere, kann ich nur 64 Byte Puffer einrichten.

Ich bleibe daher beim Vergleichen und 0 setzen, dann kann ich sogar 110 
Byte Puffer nehmen, also fast das doppelte!


Peter
Gast #827477
Lesenswert?

> #define CON_BUF_COUNT(Fifo)      ((CON_OUT_MASK & Fifo.wr_idx) -
> (CON_OUT_MASK & Fifo.rd_idx))

So funktioniert es auch wenn wr_idx < rd_idx ist:

#define CON_BUF_COUNT(Fifo)  ((Fifo.wr_idx - Fifo.rd_idx) & 
CON_OUT_MASK)
Gast #827525
Lesenswert?

Man könnte ja anstatt

CON_OUT_MASK & Fifo->wr_idx++
auch
(Fifo->wr_idx++) % CON_OUT_BUF_SIZE

verwenden und hätte damit das Problem der auf Zweierpotenzen 
eingeschränkten Puffergröße umgangen. Sollte auch nicht mehr
Platz im .text Segment brauchen und auch nicht langsamer sein.

Viele Grüße,
 Martin L.
Gast #827668
Lesenswert?

Ist ja nur ein 8-Bit Modulo notwendig. Aber stimmt - der Atmel hat 
keinen "mod"-Befehl. (Übrigens brauchen bessere Prozessoren bei 16 oder 
32bit Berechnungen deren höherwertigen Bits null sind nicht länger als 
mit entsprechend kleineren Registern.)

Viele Grüße,
 Martin L.
Gast #827689
Lesenswert?

Nur wenige Controller haben einen div- oder mod Befehl. Mir fällt
da nur der Cortex M3 ein. Das traurige am C Standard ist das
solche Berechnungen immer mit mindestens 16Bit durchgeführt werden.
Vielleicht optimiert der AVR-GCC das in diesem Fall und rechnet
tatsächlich nur mit 8 Bits. Bei einer Multiplikation macht er das
jedenfalls nicht. Da werden 8Bit Operanden auf 16Bit aufgebohrt und
das Ergebnis wieder auf 8Bit zurückgestutzt.

>(Übrigens brauchen bessere Prozessoren bei 16 oder
>32bit Berechnungen deren höherwertigen Bits null sind nicht länger als
>mit entsprechend kleineren Registern.)

Ich nehme an du meinst 16/32 Bit Prozessoren?
Interessanterweise dauert es auf solchen Prozessoren mitunter sogar
länger wenn mit kleinen Datentypen gerechnet werden soll.
Da werden nämlich Ergebnisse die ja in z.B. 32Bit Registern stehen
erst mit Masken verknüpft um die oberen Bits auszublenden.
Deshalb gibt es in der <stdint.h> die 'fast' Typen.
Also z.B. uint_fast8_t der bei einem ARM7 als 'unsigned long'
definiert ist.
Ergo: Die kleinsten Datentypen sind nicht immer die Besten.

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