[C] fifofast - eine schnelle, macro-basierte, generische FIFO (MIT Lizenz)

OP #5568290
Lesenswert?

Inspiriert von dem einfachen 2ⁿ-FIFO Beispiel aus unserem wiki habe ich 
schnelle FIFO mit erweitertem Funktionsumfang erstellt.

Funktionen:
- basiert auf Macros
- generisch: jede FIFO kann einen beliebigen Datentyp speichern
- flexible Größe: jede FIFO kann eine beliebige 2ⁿ Länge haben (n < 
2^16)
- minimaler RAM benötigt
- einfach: alle FIFO-typischen Funktionen sind verfügbar, Beispielcode 
ist vorhanden
- MIT-lizensiert

Der Code und eine etwas ausführlichere Beschreibung ist auf 
https://github.com/nqtronix/fifofast gehosted.
 
 
Alle marcos der aktuellen Version 0.2.0 sind getestet und funktionieren 
wie erwartet. Vorherige Versionen (bevor ich git genutzt habe) sind 
bereits seit etwa einem Jahr problemlos in Verwendung. Ich plane noch 
einige Features und Performanceoptimierungen, wollte aber diese 
vorläufige Version schon mal mit euch teilen, da sie imho einige 
Vorteile zu der Variante aus dem wiki besitzt.

Falls ihr Verbesserungsvorschläge oder generelles Feedback habt könnt 
ihr das gerne hier posten, für Bugs macht bitte ein Issue auf github 
auf.

Grüße
Dennis

Edit: Titel bearbeitet
OP #5616021
Lesenswert?

Hab in den letzten Tagen an fifofast weiter gearbeitet und um folgende 
Features ergänzt:

- Readme komplett überarbeitet (mit vielen Beispielen!)
- automatisiertes Testen des Quellcodes
- inline Funktionen, um auf Fifos per pointer zugreifen zu können
- fifo arrays, falls man mehr als 1 Fifo von der gleichen Art braucht

Wie gehabt ist der Code auf https://github.com/nqtronix/fifofast 
gehostet.
#7862446
Lesenswert?

Ich habe hierbei den seltsamen Fall, dass bei 2 FIFOs gleichen Datentyps und Länge es zu seltsamen Effekten kommt. Der zweite FIFO scheint in einen anderen Rambereich zu schreiben und es kommt zu Problemen woanders im Programm.

So siehts bei mir aus:

_fff_declare(uint16_t, fifo_uint16_1, 128); _fff_declare(uint16_t, fifo_uint16_2, 128);

_fff_init(fifo_uint16_1); _fff_init(fifo_uint16_2);

Im Code nutze ich die Funktion _fff_write zum Schreiben und _fff_read zu Lesen der Daten.

Habe ich hier etwas nicht verstanden?

Viele Grüße

OP #7862515
Lesenswert?

Die declare/init Makros deklarieren und initialisieren die anonyme structs mit den von dir gewählten Namen (fifo_unit16_1/2). Die anderen Makros greifen auf diese structs mit Namen zu. Die structs nutzen natürlich unterschiedliche RAM Adressen, und sollten sich gegenseitig nicht beeinflussen.

Falls du auf eine fifo auf verschiedenen .c Dateien zugreifst: Die "declare" muss in einen .h Header Datei, die von allen relevanten .c Dateien inkludiert wird. Die init nur 1x in einer .c Datei aufrufen. Ansonsten erzeugt du mehrere structs mit gleichem Namen.

Falls du auf eine fifo aus Interrupt UND regulären Funktionen zugreifst: Entweder im Interrupt befüllen und im normalen code auslesen, oder umgekehrt. Niemals von beiden Stellen gleich zugreifen.

#7862557
Lesenswert?

Hi,

Danke für deinen Kommentar.

Beide Declare und Init Makros sind in einer .c Datei global angelegt. Das befüllen der FIFOs mit write geschieht nicht im Interruptkontext, werden aber durch das deaktivieren und aktivieren der Interrupts geschützt.

Das Lesen passiert auch in der gleichen Datei, gekapselt durch eine Get-Funktion, sodass ich die Daten von woanders über die Get-Funktion auslesen kann. Zuerst wird aber durch _fff_mem_level überprüft, ob überhaupt Daten vorhanden sind. Danach werden sie durch read ausgelesen.

Ich kann jetzt nicht den echten Code präsentieren, aber das prinzipielle. Das ganze läuft auf einem STM32 ARM M3 Core. [CODE] _fff_declare(uint16_t, fifo_uint16_1, 128); _fff_declare(uint16_t, fifo_uint16_2, 128);

_fff_init(fifo_uint16_1); _fff_init(fifo_uint16_2);

void WriteFifo(uint16_t data_1, uint16_t data_2) { __disable_irq(); //fff_write(fifo_uint16_1, 0); //fff_write(fifo_uint16_2, 0); __enable_irq(); }

uint16_t GetFifoData(uint8_t* pData, uint8_t fifo) { uint16_t tmp = 0; uint16_t i = 0; uint16_t mem_level = 0;

if(fifo == 1) { mem_level = _fff_mem_level(fifo_uint16_1); } else { mem_level = _fff_mem_level(fifo_uint16_2); }

for(i = 0; i < mem_level*2; i+=2) { if(ka == 1) { tmp = _fff_read (fifo_uint16_1); } else { tmp = _fff_read (fifo_uint16_2); } memcpy(&pData[i], &tmp, 2); }

1
return i;

}

[/CODE]

-> Sollte doch alles so in Ordnung sein?

Edit: Ich überlege gerade, ob ich durch memcpy einen Bock verbaue? Hm...

Ansonsten probiere ich mal mit Arrays aus _fff_declare_a

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