以下内容主要说明环形FIFO 的在多线程环境下的使用注意事项。
FIFO 读取操作与FIFO写入操作
FIFO读取操作或FIFO 写入操作过程中,当达到分配的内存空间尾部时需要进行跳转操作。
如果代码段1所示,如果在write_index++ 后 且write_index = FIFO_SIZE。 此时产生中断并调用write_index 将产生严重的错误。
代码段2 采用先放入局部变量中进行操作,然后再将结果放入wr_idx 中,这种做法理论上是没有问题的。但是一旦编译自作聪明,将局部变量优化掉,肯能会导致一样的结果。所以有必要采用代码段 3的操作方法。
代码段 1
write_index++;
if(write_index >= FIFO_SIZE)
{
write_index = 0;
}
代码段 2
wr_idx = write_index;
wr_idx++;
if(wr_idx >= FIFO_SIZE)
{
wr_idx = 0;
}
write_index = wr_idx;
代码段 3
CRITICAL_REGION_ENTER();
write_index++;
if(write_index >= FIFO_SIZE)
{
write_index = 0;
}
CRITICAL_REGION_EXIT();
环形FIFO多线程操作
当前环形FIFO 的读操作只能有一个线程,写操作也只能有一个线程。如果读操作或者写操作需要多个线程时,将读写操作函数放入整个临界区。
关于8位机或16位机 32位机
8位单片机,当环形FIFO 的write_index 与 read_index 的变量长度大于8 BIT 时 读写操作都是非原子操作。当write_index 与 read_index 的变量长度等于8 BIT 则读操作为原子操作,写操作不是原子操作。
因此在对write_index 和read_index 读写操作时必须执行原子操作,C51的原子操作可以参考:
https://mp.csdn.net/console/editor/html/105036340
因此在8位机或者16位机上需要注意这个问题,在32位机上write_index 与 read_index 为 变量长度大于32时也需要注意。
注意在C51单片机中有局部变量的函数不可以重入,计算长度的函数中存在局部变量,因此整个函数需要在临界区中执行。