📄 avrxfifo_documentation.txt
字号:
Sept, 14, 2005
AvrXFifo requires AvrX 2.6f or newer.
AvrX 2.6f contains some significant changes to support AvrXFifos. The changes
should be 100% backward compatible to previous 2.6 versions. The change
primarily allows interrupt handler to directly call AvrXSetSemaphore(). Older
versions of AvrX probably will work, but an extra context will be temporarily
pushed onto the kernel stack during the Set Semaphore processing.
Files:
AvrXFifo.h
AvrXFifo.c
Notes on declaration & usage of AvrXFifo's:
Maximum fifo size is 256 bytes. Most practical systems only need a few
bytes to buffer interrupt handlers or protocols (e.g. large enough for
the biggest outgoing packet, for example). If this limit is too small,
see "Future Expansion" below.
The user can declare and initialize Fifo's explicitly, in code, or use
some handy #define MACROs to do the job. To do this manually follow
this template:
Outside of your code (e.g. global data memory)
uint8_t SomeBuffer[sizeof(AvrXFifo) + DesiredBufferSize];
static const pAvrXFifo FifoName = (pAvrXFifo)SomeBuffer;
Or use the macro
AVRX_DECL_FIFO(FifoName, FifoSize);
or if external
extern uint8_t SomeBuffer[];
static const pAvrXFifo FifoName = (pAvrXFifo)SomeBuffer;
Or use the macro
AVRX_EXT_FIFO(FifoName);
In your code, initialize the fifo:
FifoName->size = DesiredBufferSize;
AvrXFlushFifo(FifoName);
Or use the macro
AVRX_INIT_FIFO(FifoName);
To use the fifo:
int retc = AvrXPutFifo(FifoName, data); // Place data in fifo
int foo = AvrXPullFifo(FifoName); // Get data from fifo
AvrXWaitPutFifo(FifoName, data); // Place data in fifo, blocks if full
int foo = AvrXWaitPullFifo(FifoName); // Get data from fifo, blocks if empty
int size = AvrXPeekFifo(FifoName); // Check size of fifo
AvrXFlushFifo(FifoName); // Flush fifo & release producer.
int foo = AvrXDelFifo(FifoName); // Remove last item placed in fifo
Return Values:
FIFO_ERR (-1) fifo full or empty and operation can't be completed
FIFO_OK (0) operation successful
unsigned int Char data, zero extended for successful removal
GCC produces poor code when comparing to literal 0 (there are reasons
why this is correct). GCC generates good AVR code when testing results
for < 0. e.g.
if ((c = AvrXPullFifo(FifoName)) < FIFO_OK) // rather than ==
// empty...
else
// Do something with c which is unsigned char data.
Because the pointer to the Fifo is declared as a static const value, no
actual storage is used. The compiler is smart enough to just use the
address of the byte buffer when referencing the fifo. Optimal code is
generated.
Macros:
Macros hide the need to record the size for initialization, otherwise
are identical to the explicit C code. The only caveat is that the init
macro needs to be in the same file as the declaration macro. This is
also good programming practice to keep declarations and initialization
in one file.
Synchronization:
AvrXFifo's have built in synchronization between producers (put) and
consumers (pull). Producers and consumers can be either tasks or
interrupt handlers. Interrupt handlers, of course, cannot use the
blocking Fifo API.
When blocked, the producer/consumer will be come unblocked when the
opposite side either removes or adds a data item (respectively). There
is no mechanism to notify an interrupt handler that something has been
added or removed from a fifo. See the example of the buffered serial
I/O to see how that is handled. In short, it is up to the task end of
the fifo to manage coordination with the interrupt handler.
Future expansion possibilities:
By using the fifo code as a starting point some interesting things could
be added:
1. Fifos could be defined as word or even arbitrary data size buffers.
The size could be declared as multiples of the data and new get/put
routines defined that remove the data item. This could be made generic
by adding the element size to the fifo data structure, at the expense of
more code for the simple case.
2. Routine addresses could be added to the fifo structure as call-backs
for interrupt handlers when the fifo fills or empties. This would allow
a fifo to be put between two interrupt handlers. Say a serial to serial
buffer. Simple tasks between handlers could be written as entirely
kernel context code avoiding the overhead of task switching.
3. Fifo size could be expanded beyond 254 by changing the internal size,
in and out from uint8_t to uint16_t and modifying the fifo code
appropriately (internal temporary values). Also, race conditions in
loading pointers must be taken into account. With byte pointers CPU
reads are atomic and no critical sections are needed.
The current byte size data was chosen as a compromise between small
system code and decent sized buffers.
CAVEATS:
The fifo code has not been tested with a buffer size of 256. It should work.
AvrXPeekFifo() has not been tested.
There might be race conditions
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -