我一直在为嵌入式设备开发数据记录器。目标是存储 定期将一组变量的值存储到外部闪存中。 我的想法是在RAM中创建一个缓冲区。缓冲区的大小将等于 外部闪存的一个扇区中的字节数,即512B。 在规定的时间内,我将用变量的值填充缓冲区,然后 我将此记录存储到外部闪存中。外接闪光灯包含几个 为数据日志存储保留的块。这些块形成循环缓冲区 即,一旦缓冲区已满,最早的记录将被覆盖。
我一直在考虑的第一件事是如何识别 我可以将循环缓冲区用于实际记录存储。根据问题Circular Buffer in Flash 我知道我需要在每个记录中附加一个标题。这个头 应该包含一个记录号。
据我所知,正确回答问题Circular Buffer in Flash的号码是 插入记录头应大于块数 在为数据日志存储保留的外部闪存中。
为了更好地理解带有包含记录号的标题的想法, 决定编写用于在我的PC而非目标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: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的回答,我认为最大报头数大于闪存中的块总数就足够了。根据我所做的实验,似乎最大报头数必须至少是闪存中块总数的两倍。请任何人告诉我我的最大标题数的想法是否正确?预先感谢您的任何建议。
答案 0 :(得分:1)
在代码中给出这一行:
next_index = ((index + 1) & (length - 1)); // indices 0 ... 7
部分& (length - 1)
仅对2的幂的length
有效。它是对% length
的优化,只有在length
是幂的情况下有效之2。
因此,如果将& (length - 1)
部分替换为% length
,则它的长度应为9(或其他不是2的幂的数字)。
(如果您直接使用BUFFER_SIZE
而不是将其作为参数length
传递,那么编译器很可能会在{{1}时将% length
优化为等效的& (length - 1)
}是2的幂。)