so I'm reading a textbook on RTOS and there's a section that talks about FIFO queue's. I want to implement the code provided in the book for a UART device. I looked through the code and saw that the counters in the code don't reset. The counters are 32 bits, so they can go up to 2^32, but what if they were to be implemented in a device that goes past that value? If the counters overflow, will they wrap around and continue working normally as counters?
#include <stdint.h>
#define Size 32 //temporary value. It can be any value 2^n
uint32_t volatile TxPutI;//Counter 1
uint32_t volatile TxGetI;//Counter 2
static char TxFifo[size];
void TxFifo_Init(void)
{
TxPutI = TxGetI = 0;
}
int TxFifo_Put(char data)
{
if( (TxPutI - TxGetI)&~(Size-1) )
return 0;
TxFifo[TxPutI&(Size-1)] = data;
TxPutI++; //it can overflow
return 1;
}
int TxFifo_Get(char *datapt)
{
if( TxPutI == TxGetI )
return 0;
*datapt = TxFifo[TxGetI & (Size-1)];
TxGetI++; //it can overflow
return 1;
}
uint16_t TxFifo_Size(void) //If someone can explain how this work, that'd be awesome!
{
return( (uint16_t)(TxPutI - TxGetI) );
}
A special condition in the book is that the value Size must be 2^n. Does this condition keep the counters from causing an incorrect index? Thank you
It doesn't matter if these counters overflow. The arithmetic "just works" due to the properties of unsigned arithmetic. When a difference is taken, the operation does a "borrow" from the unrepresented upper bits, and the low bits of the result are correct. Since the difference must be much smaller than the max value of the type uint32_t
the upper bits of the difference are always zero.
Here's an example using uint8_t
to avoid large numbers. We'll use uint8_t
getI
and putI
variables, and a FIFO with size 16. getI
and putI
start out at 0. After 263 insertions and 254 removals, getI
is 254 and putI
is 7 (263 - 256 due to overflow). In unsigned arithmetic, 7 - 254 is 9. Work through some examples!
In the implementation given, the size of the FIFOs must also be a power of two because bitwise is used for modulo operations, and the cute trick for testing to see if the FIFO is full.