所以我正在阅读一本关于 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。这种情况是否可以防止计数器导致不正确的索引?谢谢
最佳答案
这些计数器是否溢出并不重要。由于无符号算术的特性,算术“有效”。当取差时,该操作从未表示的高位“借”,结果的低位是正确的。由于差异必须远小于类型 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 是否已满的可爱技巧。
关于c - 嵌入式 C 中的 FIFO 队列 - 计数器会溢出吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47404432/