gpt4 book ai didi

io - 通过无竞争条件的缓冲区将数据写入 SD 卡

转载 作者:行者123 更新时间:2023-12-04 02:05:32 31 4
gpt4 key购买 nike

我正在为数据记录设备编写固件。它以 20 Hz 的频率从传感器读取数据并将数据写入 SD 卡。但是,向SD卡写入数据的时间并不一致(大约200-300 ms)。因此,一种解决方案是以一致的速率将数据写入缓冲区(使用定时器中断),并有第二个线程在缓冲区已满时将数据写入 SD 卡。

这是我天真的实现:

#define N 64
char buffer[N];
int count;

ISR() {
if (count < N) {
char a = analogRead(A0);
buffer[count] = a;
count = count + 1;
}
}

void loop() {
if (count == N) {
myFile.open("data.csv", FILE_WRITE);

int i = 0;
for (i = 0; i < N; i++) {
myFile.print(buffer[i]);
}
myFile.close();
count = 0;
}
}

代码存在以下问题:

  1. 当缓冲区已满时,向 SD 卡写入数据会阻塞读取
  2. 它可能有竞争条件。

解决这个问题的最佳方法是什么?使用循环缓冲区,还是双缓冲?如何确保不会发生竞争条件?

最佳答案

您已经回答了您自己的问题;您应该使用双缓冲或循环缓冲区。双缓冲可能更易于实现,适用于 SD 卡等 block 写入通常更高效的设备。

缓冲区长度的选择可能需要一些考虑;通常,您会使缓冲区与 SD 扇区缓冲区大小(通常为 512 字节)相同,但这可能不切实际,并且采样率低至 20 sps,优化 SD 写入性能可能不是问题。

另一个考虑因素是,您需要通过选择合适的缓冲区大小来使采样率与文件系统延迟相匹配。在这种情况下,64 个样本缓冲区缓冲区将填充三秒多一点,但 block 写入最多只需要 300 毫秒 - 因此如果需要,您可以使用更小的缓冲区 - 8 个样本就足够了 - 尽管要小心,您可能已经观察到 300 毫秒的延迟,但当物理闪存中的特定边界被跨越时,它可能会更大 - 我已经看到一些卡在 1 MB 边界处有明显的延迟 - 此外,卡的性能因尺寸和制造商而异。

下面是对双缓冲实现的改编。我已将缓冲区长度减少到 32 个样本,但使用双缓冲后总数保持不变,仍为 64,但写入延迟减少到 1.6 秒。

// Double buffer and its management data/constants
static volatile char buffer[2][32];
static const int BUFFLEN = sizeof(buffer[0]);
static const unsigned char EMPTY = 0xff;
static volatile unsigned char inbuffer = 0;
static volatile unsigned char outbuffer = EMPTY;

ISR()
{
static int count = 0;

// Write to current buffer
char a = analogRead(A0);
buffer[inbuffer][count] = a;
count++ ;

// If buffer full...
if( count >= BUFFLEN )
{
// Signal to loop() that data available (not EMPTY)
outbuffer = inbuffer;

// Toggle input buffer
inbuffer = inbuffer == 0 ? 1 : 0;
count = 0;
}
}

void loop()
{
// If buffer available...
if( outbuffer != EMPTY )
{
// Write buffer
myFile.open("data.csv", FILE_WRITE);
for( int i = 0; i < BUFFLEN; i++)
{
myFile.print(buffer[outbuffer][i]);
}
myFile.close();

// Set the buffer to empty
outbuffer = EMPTY;
}
}

请注意volatileunsigned char 用于共享数据。重要的是,在并发执行上下文之间共享的数据是显式地和原子地访问的;在基于 8 位 AVR 的 Arduino 上访问 int 需要多条机器指令,并且中断可能会在 loop() 中的读/写过程中发生并导致不正确的值待阅读。

关于io - 通过无竞争条件的缓冲区将数据写入 SD 卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43703778/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com