嵌入式 C 中的 FIFO 队列 - 计数器会溢出吗?
FIFO Queue in Embedded C - Counters will overflow?
所以我正在阅读一本关于 RTOS 的教科书,其中有一节讨论了 FIFO 队列。我想为 UART 设备实现书中提供的代码。我查看了代码,发现代码中的计数器没有重置。计数器是 32 位的,因此它们可以达到 2^32,但是如果它们在超过该值的设备中实现怎么办? 如果计数器溢出,它们会回绕并继续作为计数器正常工作吗?
#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) );
}
书上有一个特殊的条件,就是Size的值必须是2^n。这种情况是否可以防止计数器导致不正确的索引?谢谢
这些计数器是否溢出并不重要。由于无符号算术的性质,算术"just works"。当取差时,操作从未表示的高位执行"borrow",结果的低位是正确的。由于差异必须远小于类型 uint32_t
的最大值,因此差异的高位始终为零。
这是一个使用 uint8_t
来避免大数字的示例。我们将使用 uint8_t
getI
和 putI
变量,以及大小为 16 的 FIFO。getI
和 putI
从 0 开始。经过 263 次插入和 254 次插入后移除,getI
是 254,putI
是 7(263 - 256 由于溢出)。在无符号算术中,7 - 254 是 9。通过一些例子来完成!
在给定的实现中,FIFO 的大小也必须是 2 的幂,因为按位用于模运算,以及测试 FIFO 是否已满的可爱技巧。
所以我正在阅读一本关于 RTOS 的教科书,其中有一节讨论了 FIFO 队列。我想为 UART 设备实现书中提供的代码。我查看了代码,发现代码中的计数器没有重置。计数器是 32 位的,因此它们可以达到 2^32,但是如果它们在超过该值的设备中实现怎么办? 如果计数器溢出,它们会回绕并继续作为计数器正常工作吗?
#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) );
}
书上有一个特殊的条件,就是Size的值必须是2^n。这种情况是否可以防止计数器导致不正确的索引?谢谢
这些计数器是否溢出并不重要。由于无符号算术的性质,算术"just works"。当取差时,操作从未表示的高位执行"borrow",结果的低位是正确的。由于差异必须远小于类型 uint32_t
的最大值,因此差异的高位始终为零。
这是一个使用 uint8_t
来避免大数字的示例。我们将使用 uint8_t
getI
和 putI
变量,以及大小为 16 的 FIFO。getI
和 putI
从 0 开始。经过 263 次插入和 254 次插入后移除,getI
是 254,putI
是 7(263 - 256 由于溢出)。在无符号算术中,7 - 254 是 9。通过一些例子来完成!
在给定的实现中,FIFO 的大小也必须是 2 的幂,因为按位用于模运算,以及测试 FIFO 是否已满的可爱技巧。