Выравнивание износа на EEPROM микроконтроллера


15

Например: Таблица данных для ATtiny2313 (как и большинство таблиц данных Atmel AVR) гласит:

Внутрисистемное программируемое EEPROM 128 байт Выносливость: 100 000 циклов записи / стирания

Представьте, что программе требуется только два байта для хранения какой-либо конфигурации, остальные 126 байтов фактически теряются. Меня беспокоит то, что регулярные обновления двух байтов конфигурации могут изнашивать EEPROM устройства и делать его бесполезным. Все устройство станет ненадежным, потому что в определенный момент вы просто не сможете отследить, какие байты в EEPROM ненадежны.

Существует ли разумный способ выравнивания износа в EEPROM микроконтроллера, когда вы эффективно используете только один или два байта из имеющихся 128?


1
Если бы ограничение записи 100 тыс. Было бы ограничением, имеет ли смысл вместо этого использовать какую-то другую технологию? Или механизм, который включает внутреннее выравнивание, или что-то с порядком величины или большей выносливостью?
Аниндо Гош

1
@AnindoGhosh Я просто не хочу тратить свой небольшой запас микроконтроллеров только из-за изнашивания EEPROM из-за того, что я проверил проверку концепции. Я не хочу беспокоиться о том, какой байт я использовал в предыдущем проекте при повторном использовании контроллера. И мне приятно знать, что я оптимально использую доступное оборудование.
Джиппи


1
Может быть, посмотрите на мой ответ на stackoverflow .
JimmyB

Взгляните на серию TAM MSP430 FRAM ... 10 ^ 13 пишет !!!
геометрикал

Ответы:


19

Техника, которую я обычно использую, заключается в добавлении к данным 4-байтового порядкового номера, где наибольшее число представляет собой последнее / текущее значение. В случае хранения 2 байтов фактических данных, которые дадут всего 6 байтов, а затем я сформируюсь в круговую очередь, так что для 128 байтов EEPROM он будет содержать 21 запись и увеличит выносливость в 21 раз.

Затем при загрузке можно использовать наибольший порядковый номер для определения как следующего порядкового номера, который будет использоваться, так и текущего хвоста очереди. Следующий псевдокод C демонстрирует, что это предполагает, что при начальном программировании область EEPROM была стерта до значений 0xFF, поэтому я игнорирую порядковый номер 0xFFFF:

struct
{
  uint32_t sequence_no;
  uint16_t my_data;
} QUEUE_ENTRY;

#define EEPROM_SIZE 128
#define QUEUE_ENTRIES (EEPROM_SIZE / sizeof(QUEUE_ENTRY))

uint32_t last_sequence_no;
uint8_t queue_tail;
uint16_t current_value;

// Called at startup
void load_queue()
{
  int i;

  last_sequence_no = 0;
  queue_tail = 0;
  current_value = 0;
  for (i=0; i < QUEUE_ENTRIES; i++)
  {
    // Following assumes you've written a function where the parameters
    // are address, pointer to data, bytes to read
    read_EEPROM(i * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
    if ((QUEUE_ENTRY.sequence_no > last_sequence_no) && (QUEUE_ENTRY.sequence_no != 0xFFFF))
    {
      queue_tail = i;
      last_sequence_no = QUEUE_ENTRY.sequence_no;
      current_value = QUEUE_ENTRY.my_data;
    }
  }
}

void write_value(uint16_t v)
{
  queue_tail++;
  if (queue_tail >= QUEUE_ENTRIES)
    queue_tail = 0;
  last_sequence_no++;
  QUEUE_ENTRY.sequence_no = last_sequence_no;
  QUEUE_ENTRY.my_data = v;
  // Following assumes you've written a function where the parameters
  // are address, pointer to data, bytes to write
  write_EEPROM(queue_tail * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
  current_value = v;
}

Для EEPROM меньшего размера 3-байтовая последовательность была бы более эффективной, хотя вместо использования стандартных типов данных потребовалась бы небольшая разбивка битов.


+1, Хороший подход. Может ли хранилище быть немного оптимизировано с использованием меньшего количества «теговых» байтов, и, возможно, в зависимости от некоторой формы механизма хэш-корзины для обеспечения дополнительного распределения? Гибрид между отсутствием выравнивания и вашим подходом?
Аниндо Гош

@AnindoGhosh, да, я верю, что мог. Я обычно использовал этот подход на небольших микросхемах для простоты кода, плюс лично я использовал его в основном на больших устройствах, таких как DataFLASH. Еще одна простая идея, которая приходит на ум, заключается в том, что порядковые номера можно периодически уменьшать, чтобы они оставались на меньших значениях.
PeterJ

Замечание по применению Atmel, упомянутое @ m.Alin, имеет простое упрощение: после СБРОСА можно просматривать буфер [...], находя последний измененный [...] элемент буфера, находя место, где Разница между элементом буфера и следующим элементом буфера больше 1 .
Джиппи

Не следует ли write_value () поместить запись в queue_tail * sizeof (QUEUE_ENTRY)? я буду прав в первый раз, но разве не должно продолжаться, если есть несколько записей? я не увеличивается вне load_queue ().
Маршал Юбэнкс

2
@ DWORD32: Да, это технически правильно, но на практике не имеет значения. К тому времени, когда это произойдет, предел износа EEPROM будет превышен в 2000 раз!
Дэйв Твид

5

Ниже приведен метод, который использует сегменты и около одного байта служебной информации на блок. Байты ведра и байты заголовка получают примерно одинаковое количество износа. В данном примере при использовании 128 байт EEPROM этот метод выделяет 42 2-байтовых сегмента и 44 байта состояния, увеличивая износостойкость примерно в 42 раза.

Метод:

Разделите адресное пространство EEPROM на k сегментов, где k = ⌊ E / ( n +1) with, где n = размер массива данных настройки = размер сегмента и E = размер EEPROM (или, в более общем случае, количество EEPROM ячейки, которые будут посвящены этой структуре данных).

Инициализируйте каталог, массив из m байтов, установленный в k , с m = En · k . Когда ваше устройство запускается, оно читает каталог, пока не найдет текущую запись, которая является байтом, не равным k . [Если все записи каталога равны k , инициализируйте первую запись каталога 0 и продолжайте с этого момента.]

Когда текущая запись каталога содержит j , сегмент j содержит текущие данные. Когда вам нужно написать новую запись данных настройки, вы сохраняете j +1 в текущей записи каталога; если это делает его равным k , инициализируйте следующую запись каталога 0 и продолжайте оттуда.

Обратите внимание, что байты каталога получают примерно такой же износ, как и байты сегмента, потому что 2 · k > mk .

(Я приспособил выше от моего ответа на Arduino SE вопрос 34189 , Как увеличить срок службы EEPROM? ) .


2

Я использовал для этого порядковый номер (аналогично ответу Питера). Порядковый номер на самом деле может быть всего 1 бит, при условии, что количество элементов в метке является нечетным. Голова и хвост помечаются двумя последовательными 1 или 0

Например, если вы хотите пролистать 5 элементов, порядковые номера будут такими:

{01010} (запись в 0) {11010} (запись в 1) {10010} (запись в 2) {10110} (запись в 3) {10100} (запись в 4) {10101} (запись в 5)


1

Есть несколько вариантов в зависимости от типа вашей EEPROM и размера ваших данных.

  1. Если ваша EEPROM имеет индивидуально стираемые страницы и вы используете 1 страницу (или больше), просто сохраните все страницы, кроме используемых, и повторное использование страниц по кругу.

  2. Если вы используете только часть страницы, которую нужно стереть сразу, разделите эту страницу на записи данных. Используйте чистую запись каждый раз, когда вы пишете, и стирайте, когда у вас заканчиваются чистые записи.

При необходимости используйте «грязный» бит, чтобы различать чистые и грязные записи (обычно у вас есть хотя бы один байт, который гарантированно отличается от 0xFF, который можно использовать для отслеживания грязных записей).

Если ваша библиотека EEPROM не предоставляет функцию стирания (например, Arduino), вот полезный трюк для алгоритма № 2: поскольку ваша первая запись EEPROM всегда используется, вы можете определить значение «грязного» бита, прочитав его. Затем, когда у вас заканчиваются чистые записи, вы просто начинаете снова с первой записи, инвертируя «грязный» бит, и остальные ваши записи автоматически становятся помеченными как «чистые».

Порядковые номера и каталоги - пустая трата места, если вы не хотите иметь возможность отслеживать плохие страницы или обновлять различные части ваших данных EEPROM независимо.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.