Круговой буфер во флэш-реализации - PullRequest
0 голосов
/ 02 января 2019

Я работал над регистратором данных для встроенного устройства.Цель состоит в том, чтобы периодически хранить значения набора переменных во внешней флэш-памяти.Моя идея - создать буфер в оперативной памяти.Размер буфера будет равен количеству байтов в одном секторе во внешней флэш-памяти, то есть 512 В. После истечения установленного времени я заполню буфер значениями переменных, а затем сохраню эту запись во внешней флэш-памяти.Внешняя флэш-память содержит несколько блоков, зарезервированных для хранения журналов данных.Эти блоки образуют кольцевой буфер, т. Е. Как только буфер заполнится, самые старые записи будут перезаписаны.

Первое, о чем я подумал - как распознать, какой блок в кольцевом буфере я могу использовать для фактической записиместо хранения.Исходя из вопроса Циркулярный буфер во Flash Я понял, что мне нужно добавить заголовок в каждую запись.Этот заголовок должен содержать номер записи.

Насколько я понимаю, правильно ответить на вопрос Круговой буфер во 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,

На основе ответа навопрос Круговой буфер во Flash Я подумал, что достаточно, чтобы максимальный номер заголовка был больше, чем общее количество блоков во флэш-памяти.Основываясь на проведенных мной экспериментах, кажется, что максимальное количество заголовков должно быть как минимум вдвое больше общего количества блоков во флэш-памяти.Кто-нибудь может подсказать, верна ли моя идея с максимальным номером заголовка?Заранее спасибо за любые предложения.

1 Ответ

0 голосов
/ 03 января 2019

Учитывая эту строку в коде:

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

Деталь & (length - 1) работает только для length, который является степенью 2. Это эффективная оптимизация % length, которая действительнатолько если length является степенью 2.

Так что если вы замените деталь & (length - 1) на % length, то она должна работать на длину 9 (или любое другое число, которое не являетсястепень 2).

(Если вы используете BUFFER_SIZE напрямую, а не передаете его в качестве параметра length, то компилятор, скорее всего, оптимизирует % length до эквивалентного & (length - 1) всякий раз, когда BUFFER_SIZEсила 2.)

...