I have been working on data logger for an embedded device. The goal is to store values of a set of variables in periodic manner into the external flash memory. My idea is to create a buffer in RAM. Size of the buffer will be equal to the number of bytes in one sector in the external flash i.e. 512 B. After expiration of prescribed time I will fill the buffer with values of the variables and then I will store this record into the external flash. External flash contains several blocks reserved for the data logs storage. These blocks form a circular buffer i.e. as soon as the buffer is full the oldest records will be overwritten.
First thing I have been thinking about is how to recognize what block in the circular buffer I can use for actual record storage. Based on the question Circular Buffer in Flash I have understood that I need to append a header into each record. This header shall contain a record number.
As far as I understand correctly answer to the question Circular Buffer in Flash the number which I shall insert into the record header should be greater than the number of blocks in the external flash which are reserved for the data logs storage.
For better understanding the idea with headers containing record numbers I have decided to write a simulation software for testing on my pc instead of the target 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;
}
Output for headers 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,
Output for headers 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,
Based on the answer to the question Circular Buffer in Flash I thought that it is suficient to have the maximal header number greater than total number of blocks in flash. Based on the experiments I have done it seems that the maximal header number has to be at least double of total number of blocks in flash. Please can anybody tell me whether my idea with maximal header number is correct? Thanks in advance for any suggestions.