【问题标题】:Circular buffer in flash implementation闪存实现中的循环缓冲区
【发布时间】:2019-01-02 09:34:57
【问题描述】:

我一直在为嵌入式设备开发数据记录器。目标是存储 将一组变量的值周期性地存入外部闪存。 我的想法是在 RAM 中创建一个缓冲区。缓冲区的大小将等于 外部闪存中一个扇区中的字节数,即 512 B. 到期后 在规定的时间内,我将用变量的值填充缓冲区,然后 我会将此记录存储到外部闪存中。外部闪光灯包含几个 为数据日志存储保留的块。这些块形成一个循环缓冲区 即,一旦缓冲区已满,最旧的记录就会被覆盖。

我一直在考虑的第一件事是如何识别 我可以用于实际记录存储的循环缓冲区。基于问题Circular Buffer in Flash 我知道我需要在每条记录中附加一个标题。这个标题 应包含一个记录号。

据我了解正确回答问题Circular Buffer in Flash 我的号码 应插入记录头应大于块数 在为数据日志存储保留的外部闪存中。

为了更好地理解包含记录号的标题的想法,我有 决定写一个模拟软件在我的电脑上测试而不是目标MCU。

#define BUFFER_SIZE     8
#define NONE_INDEX      BUFFER_SIZE
#define ERASED_BYTE     0x00


unsigned char buffer[BUFFER_SIZE];

void PrintBuffer(unsigned char *buffer){
    for(unsigned char index = 0; index < BUFFER_SIZE; index++){
        std::cout << std::setw(3);      // 3 digits
        std::cout << showbase << dec;   // in decimal
        std::cout << (unsigned short)*(buffer + index) << ", ";
    }
    std::cout << "\n";
}

void ClearBuffer(unsigned char *buffer, unsigned char length){
    for(unsigned char index = 0; index < length; index++){
        *(buffer + index) = ERASED_BYTE;
    }
}

void Insert2Buffer(unsigned char *buffer, unsigned char elem, unsigned char pos){
    *(buffer + pos) = elem;
}

unsigned char FindPosInBuffer(unsigned char *buffer, unsigned char length){

    unsigned char curr_hdr;
    unsigned char next_hdr;
    unsigned char retval = NONE_INDEX; // non-existent index

    unsigned char index;
    unsigned char next_index;

    // searching for erased byte
    for(index = 0; index < length; index++){
        curr_hdr = *(buffer + index);
        if(curr_hdr == ERASED_BYTE){
            retval = index;
            break;
        }
    } 

    // erased byte does not exist - buffer is full i.e. free position is the
    // position where a discontinuity in record headers numbers occurs
    if(retval == NONE_INDEX){
        for(index = 0; index < length; index++){
           curr_hdr   = *(buffer + index);

           next_index = ((index + 1) & (length - 1)); // indices 0 ... 7
           next_hdr   = *(buffer + next_index);

           if((curr_hdr + 1) != next_hdr){
               retval = next_index;
               break;
           }
        }
    }

    return retval;
}

/*
 * 
 */
int main(int argc, char** argv) {

    unsigned char free_pos;
    unsigned char elem = 1;

    ClearBuffer(buffer, BUFFER_SIZE);
    PrintBuffer(buffer);

    // inserting into buffer
    for(unsigned short insert = 0; insert < 64; insert++){
        free_pos = FindPosInBuffer(buffer, BUFFER_SIZE);
        Insert2Buffer(buffer, elem, free_pos);
        elem++;
        // headers 1 ... 16
        if(elem == 17){
            elem = 1;
        }
        // headers 1 ... 9 - does not work
        //if(elem == 10){
        //    elem = 1;
        //}

        PrintBuffer(buffer);
    }

    return 0;
}

标题 1 ... 16 的输出:

  0,   0,   0,   0,   0,   0,   0,   0, 
  1,   0,   0,   0,   0,   0,   0,   0, 
  1,   2,   0,   0,   0,   0,   0,   0, 
  1,   2,   3,   0,   0,   0,   0,   0, 
  1,   2,   3,   4,   0,   0,   0,   0, 
  1,   2,   3,   4,   5,   0,   0,   0, 
  1,   2,   3,   4,   5,   6,   0,   0, 
  1,   2,   3,   4,   5,   6,   7,   0, 
  1,   2,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,  10,   3,   4,   5,   6,   7,   8, 
  9,  10,  11,   4,   5,   6,   7,   8, 
  9,  10,  11,  12,   5,   6,   7,   8, 
  9,  10,  11,  12,  13,   6,   7,   8, 
  9,  10,  11,  12,  13,  14,   7,   8, 
  9,  10,  11,  12,  13,  14,  15,   8, 
  9,  10,  11,  12,  13,  14,  15,  16, 
  1,  10,  11,  12,  13,  14,  15,  16, 
  1,   2,  11,  12,  13,  14,  15,  16, 
  1,   2,   3,  12,  13,  14,  15,  16, 
  1,   2,   3,   4,  13,  14,  15,  16, 
  1,   2,   3,   4,   5,  14,  15,  16, 
  1,   2,   3,   4,   5,   6,  15,  16, 
  1,   2,   3,   4,   5,   6,   7,  16, 
  1,   2,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,  10,   3,   4,   5,   6,   7,   8, 
  9,  10,  11,   4,   5,   6,   7,   8, 
  9,  10,  11,  12,   5,   6,   7,   8, 
  9,  10,  11,  12,  13,   6,   7,   8, 
  9,  10,  11,  12,  13,  14,   7,   8, 
  9,  10,  11,  12,  13,  14,  15,   8, 
  9,  10,  11,  12,  13,  14,  15,  16, 
  1,  10,  11,  12,  13,  14,  15,  16, 
  1,   2,  11,  12,  13,  14,  15,  16, 
  1,   2,   3,  12,  13,  14,  15,  16, 
  1,   2,   3,   4,  13,  14,  15,  16, 
  1,   2,   3,   4,   5,  14,  15,  16, 
  1,   2,   3,   4,   5,   6,  15,  16, 
  1,   2,   3,   4,   5,   6,   7,  16, 
  1,   2,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,  10,   3,   4,   5,   6,   7,   8, 
  9,  10,  11,   4,   5,   6,   7,   8, 
  9,  10,  11,  12,   5,   6,   7,   8, 
  9,  10,  11,  12,  13,   6,   7,   8, 
  9,  10,  11,  12,  13,  14,   7,   8, 
  9,  10,  11,  12,  13,  14,  15,   8, 
  9,  10,  11,  12,  13,  14,  15,  16, 
  1,  10,  11,  12,  13,  14,  15,  16, 
  1,   2,  11,  12,  13,  14,  15,  16, 
  1,   2,   3,  12,  13,  14,  15,  16, 
  1,   2,   3,   4,  13,  14,  15,  16, 
  1,   2,   3,   4,   5,  14,  15,  16, 
  1,   2,   3,   4,   5,   6,  15,  16, 
  1,   2,   3,   4,   5,   6,   7,  16, 
  1,   2,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,  10,   3,   4,   5,   6,   7,   8, 
  9,  10,  11,   4,   5,   6,   7,   8, 
  9,  10,  11,  12,   5,   6,   7,   8, 
  9,  10,  11,  12,  13,   6,   7,   8, 
  9,  10,  11,  12,  13,  14,   7,   8, 
  9,  10,  11,  12,  13,  14,  15,   8, 
  9,  10,  11,  12,  13,  14,  15,  16,

标题 1 ... 9 的输出:

  0,   0,   0,   0,   0,   0,   0,   0, 
  1,   0,   0,   0,   0,   0,   0,   0, 
  1,   2,   0,   0,   0,   0,   0,   0, 
  1,   2,   3,   0,   0,   0,   0,   0, 
  1,   2,   3,   4,   0,   0,   0,   0, 
  1,   2,   3,   4,   5,   0,   0,   0, 
  1,   2,   3,   4,   5,   6,   0,   0, 
  1,   2,   3,   4,   5,   6,   7,   0, 
  1,   2,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8, 
  9,   2,   3,   4,   5,   6,   7,   8, 
  9,   3,   3,   4,   5,   6,   7,   8, 
  9,   4,   3,   4,   5,   6,   7,   8, 
  9,   5,   3,   4,   5,   6,   7,   8, 
  9,   6,   3,   4,   5,   6,   7,   8, 
  9,   7,   3,   4,   5,   6,   7,   8, 
  9,   8,   3,   4,   5,   6,   7,   8, 
  9,   9,   3,   4,   5,   6,   7,   8, 
  9,   1,   3,   4,   5,   6,   7,   8,

根据Circular Buffer in Flash 问题的答案,我认为最大标头数大于闪存中的总块数就足够了。根据我所做的实验,似乎最大标头数必须至少是闪存中块总数的两倍。请有人能告诉我我的最大标题编号的想法是否正确?提前感谢您的任何建议。

【问题讨论】:

    标签: flash logging circular-buffer


    【解决方案1】:

    鉴于代码中的这一行:

    next_index = ((index + 1) & (length - 1)); // indices 0 ... 7
    

    &amp; (length - 1) 部分仅适用于 2 的幂的 length。它实际上是 % length 的优化,仅当 length 是 2 的幂时才有效。

    因此,如果您将 &amp; (length - 1) 部分替换为 % length,那么它的长度应该为 9(或任何其他不是 2 的幂的数字)。

    (如果您直接使用BUFFER_SIZE 而不是将其作为参数length 传递,那么只要BUFFER_SIZE 是2 的幂,编译器很可能会将% length 优化为等效的&amp; (length - 1)。)

    【讨论】:

    • 感谢您的反应。我认为我刚刚找到了问题的原因。问题在于这个条件语句 if((curr_hdr + 1) != next_hdr)。 curr_hdr 必须以 9 为模递增。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2010-10-24
    • 2012-04-02
    相关资源
    最近更新 更多