Forum: Projekte & Code [C] fifofast - eine schnelle, macro-basierte, generische FIFO (MIT Lizenz)


von Dennis  . (nqtronix)


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

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Eine gute Demonstration, warum C++ templates erfunden wurden...
Duck und wech

von Dennis  . (nqtronix)


Lesenswert?

Dr. Sommer schrieb:
> Eine gute Demonstration, warum C++ templates erfunden wurden...

Da stimm ich dir zu, für C++ Code sind templates die bessere Wahl. Für C 
muss man halt kreativ werden schulterzuck

von Dr. Sommer (Gast)


Lesenswert?

Dennis  . schrieb:
> Für C muss man halt kreativ werden schulterzuck

Oder sich überlegen ob man wirklich unbedingt C braucht...

von Dennis  . (nqtronix)


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.

von Oscar K. (sieges)


Lesenswert?

super, Danke !

von Ali K. (teddy50)


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

von Dennis  . (nqtronix)


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.

von Ali K. (teddy50)


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.
1
_fff_declare(uint16_t, fifo_uint16_1, 128);
2
_fff_declare(uint16_t, fifo_uint16_2, 128);
3
4
_fff_init(fifo_uint16_1);
5
_fff_init(fifo_uint16_2);
6
7
void WriteFifo(uint16_t data_1, uint16_t data_2)
8
{
9
  __disable_irq();
10
  //_fff_write_(fifo_uint16_1, 0);
11
  //_fff_write_(fifo_uint16_2, 0);
12
  __enable_irq();
13
}
14
15
uint16_t GetFifoData(uint8_t* pData, uint8_t fifo)
16
{
17
  uint16_t tmp = 0;
18
  uint16_t i = 0;
19
  uint16_t mem_level = 0;
20
21
  if(fifo == 1)
22
  {
23
    mem_level = _fff_mem_level(fifo_uint16_1);
24
  }
25
  else
26
  {
27
    mem_level = _fff_mem_level(fifo_uint16_2);
28
  }
29
30
  for(i = 0; i < mem_level*2; i+=2)
31
  {
32
    if(ka == 1)
33
    {
34
      tmp = _fff_read (fifo_uint16_1);
35
    }
36
    else
37
    {
38
      tmp = _fff_read (fifo_uint16_2);
39
    }
40
    memcpy(&pData[i], &tmp, 2);
41
  }
42
43
    return i;
44
}

-> 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

: Bearbeitet durch User
von Ali K. (teddy50)


Lesenswert?

Hi, das Problem liegt auf meiner Seite, nicht an dem fifo.
Nur als Info.

Viele Grüße

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.