C Library to transform a physical SPI Flash into a arbitrary number of logical circular buffers. The interface between SFCB and SPI core is realized as shared memory.
-D at compile time| Version | Date | Source | Change log |
|---|---|---|---|
| latest | latest.zip |
git clone --recursive https://github.com/andkae/SPI-Flash-Circular-Buffer.gitThe Makefile builds the repository with unit test:
$ make
gcc -c -O -Wall -Wextra -Wconversion -I . -I ../ -DW25Q16JV ./test/sfcb_test.c -o ./test/sfcb_test.o
gcc -c -O -Wall -Wextra -Wconversion -I . -I ../ -DW25Q16JV -DSFCB_PRINTF_EN ./spi_flash_cb.c -o ./test/sfcb.o
gcc -c -O -Wall -Wextra -Wconversion -I . -I ../ -DW25Q16JV ./test/spi_flash_model/spi_flash_model.c -o ./test/spi_flash_model.o
gcc ./test/sfcb_test.o ./test/sfcb.o ./test/spi_flash_model.o -Wall -Wextra -I. -lm -o ./test/sfcb_testThe library part itself can be built with:
gcc -c -O -Wall -Wextra -Wconversion -I . -DW25Q16JV -Werror ./spi_flash_cb.c -o ./test/sfcb.oThe flash memory W25Q16JV was selected via compile switch -D.
To run the unit test call:
$ ./test/sfcb_testInitializes SFCB common handle and assigns memory.
int sfcb_init (t_sfcb *self, void *cb, uint8_t cbLen, void *spi, uint16_t spiLen);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cb | Circular buffer queue memory |
| cbLen | max. number of cb queues |
| spi | SFCB / SPI core exchange buffer |
| spiLen | spi buffer size in bytes |
Exit codes
Creates a new logical independent circular buffer queue in the SPI Flash.
int sfcb_new_cb (t_sfcb *self, uint32_t magicNum, uint16_t elemSizeByte, uint16_t numElems, uint8_t *cbID);| Arg | Description |
|---|---|
| self | SFCB storage element |
| magicNum | Magic number, needs to be unique for every queue on the same SPI Flash |
| elemSizeByte | Payload size in byte, header/footer causes |
| numElems | minimal number of required elements in queue, rounded up to next full SECTOR |
| cbID | assigned ID to this queue, needed for all further requests |
Exit codes
Checks if SFCB is processing another request.
int sfcb_busy (t_sfcb *self);| Arg | Description |
|---|---|
| self | SFCB storage element |
Exit codes
In last request ended with error.
int sfcb_isero (t_sfcb *self);| Arg | Description |
|---|---|
| self | SFCB storage element |
Exit codes
Acquires all queue information from SPI flash. Needed after calling sfcb_add to update all management information.
int sfcb_mkcb (t_sfcb *self);| Arg | Description |
|---|---|
| self | SFCB storage element |
Exit codes
Append bytes to the current selected circular buffer queue element.
int sfcb_add (t_sfcb *self, uint8_t cbID, void *data, uint16_t len);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cbID | circular buffer queue to interact |
| *data | pointer to write data |
| len | number of bytes in *data |
Exit codes
Force writing the Footer if not all available bytes in the circular buffer queue
element are occupied by Add. The Footer is used to detect an complete writing of an element.
The general recommendation is to call sfcb_add_done every time when you completed the queue element writing.
int sfcb_add_done (t_sfcb *self, uint8_t cbID);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cbID | circular buffer queue to interact |
Exit codes
Acquire the current number of written bytes to queues element. Enables multistage data object writing to circular buffer element.
uint16_t sfcb_get_pl_wrcnt (t_sfcb *self, uint8_t cbID);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cbID | circular buffer queue to interact |
Write byte count of queue element.
Read last written queue element back.
int sfcb_get_last (t_sfcb *self, uint8_t cbID, void *data, uint16_t len, uint32_t *elemID);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cbID | circular buffer queue to interact |
| *data | pointer to read data |
| len | number of bytes in *data |
| *elemID | queue element number |
Exit codes
Raw data read from flash.
int sfcb_flash_read (t_sfcb *self, uint32_t adr, void *data, uint16_t len);| Arg | Description |
|---|---|
| self | SFCB storage element |
| adr | SPI Flash memory address |
| *data | pointer to read data |
| len | number of bytes in *data |
Exit codes
Services circular buffer layer request as well SPI packet processing. This function should called in a time based matter. The SPI data packet transfer should use an ISR based dataflow.
void sfcb_worker (t_sfcb *self);| Arg | Description |
|---|---|
| self | SFCB storage element |
None.
By sfcb_worker created SPI packet size in bytes.
uint16_t sfcb_spi_len (t_sfcb *self);| Arg | Description |
|---|---|
| self | SFCB storage element |
Byte Count of SPI packet.
Get SFCB compiled flash type total size.
uint32_t sfcb_flash_size (void);Size in bytes.
Get highest element number of circular buffer queue cbID.
uint32_t sfcb_idmax (t_sfcb *self, uint8_t cbID);| Arg | Description |
|---|---|
| self | SFCB storage element |
| cbID | circular buffer queue to interact |
Highest element number.
| Value | Description |
|---|---|
| SFCB_OK | Accepted |
| SFCB_E_NO_FLASH | no flash type selected, use -D
|
| SFCB_E_MEM | not enough memory assigned in sfcb_init
|
| SFCB_E_FLASH_FULL | Flash capacity exceeded |
| SFCB_E_WKR_BSY |
sfcb_worker is busy, wait |
| SFCB_E_NO_CB_Q | circular buffer queue cbID not existent |
| SFCB_E_WKR_REQ | circular buffer management data not prepared for request, run sfcb_mkcb
|
| SFCB_E_CB_Q_MTY | no valid entries in queue |
The SFCB supports an arbitrary number of circular buffer queues. Each circular buffer starts at the lowest free SPI Flash address. The Flash architecture requires an dedicated data clear - so called Sector Erase. Through this limitation needs to be at least two sectors allocated. Otherwise would the overwrite of the first written element result in an complete circular buffer queue overwrite without keeping any previous entries. Every new entry is marked with the incremented highest 32bit IdNum and MagicNum. The MagicNum ensures the detection of an occupied circular buffer queue element.
An exemplary memory organization for 240 bytes payload and 32 elements (= two sectors) shows the figure below: