Portál AbcLinuxu, 5. května 2025 08:59
typedef struct { word OfsWR; // Pozice cteni word OfsRD; // Pozice zapisu word Cnt; // Pocet ulozenych bytu byte * Buf; // Buffer word BufSize; // Velikost bufferu } Fifo_t; word FifoGetCount (Fifo_t * Fifo){ return Fifo->Cnt; } word FifoGetFree (Fifo_t * Fifo){ return Fifo->BufSize - Fifo->Cnt; } byte FifoAddByte (Fifo_t * Fifo, byte Src){ if (Fifo->Cnt >= Fifo->BufSize) return 0; Fifo->Buf[Fifo->OfsWR++] = Src; Fifo->Cnt++; if (Fifo->OfsWR >= Fifo->BufSize) Fifo->OfsWR = 0; return 1; } byte FifoGetByte (Fifo_t * Fifo){ byte b; if (!Fifo->Cnt) return 0; b = Fifo->Buf[Fifo->OfsRD++]; Fifo->Cnt--; if (Fifo->OfsRD >= Fifo->BufSize) Fifo->OfsRD = 0; return b; } void FifoInit (Fifo_t * Fifo, byte * Buf, word BufSize){ Fifo->OfsRD = 0; Fifo->OfsWR = 0; Fifo->Cnt = 0; Fifo->BufSize = BufSize; Fifo->Buf = Buf; }
volatile
. Bez toho compilator nerata, ze hodnota sa moze zmenit mimo kontext aktualneho kodu. Kompilator moze optimalizovat kod tak, ze si udaje drzi v registroch a necita udaje z pamate. Tym padom zmena z prerusenia nie je reflektovana v hlavnej slucke kodu.ATOMIC_BLOCK
". Inac povedane, funkcia FifoGetByte by mala docasne vypnut prerusenie a zapnut ho az ked su vsetky zmeny zapisane do pamate. V opacnom pripade moze nastat situacia, ze funkcia "FifoGetByte" a "FifoAddByte" sa bude prelinat a navzajom si prepisu data. Situacia, ked sa napr. nacitaju data pre if a/alebo dekrementaciu. V preruseni dojde k zmene udajov, ale k naslednemu zapisu dojde podla pred tym nacitanych dat a nie realnych .... o tomto by sa dalo dlho hovorit. Ked si pohladas "ATOMIC_BLOCK" v avr-gcc dokumentacii tak najdes hromadu roznych prikladov, preco sa to ma pouzivat.
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.