Улучшить срок службы EEPROM, не меняя биты?

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

Записанные значения и их порядок всегда будут следующими:

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 0 -> ....

Если я напишу это в EEPROM за полный цикл 0-> 0, последний бит изменится 7 раз, а остальные биты в значительной степени простаивают. Вот почему я подумал о более равномерном распределении изменений, используя вместо этого последовательность

0 -> 1 -> 3 -> 7 -> 15 -> 31 -> 63 -> 0 -> ....

Это изменило бы каждый бит только один раз в течение полного цикла 0-> 0. Улучшает ли это ожидаемый срок службы EEPROM или ожидаемый срок службы связан с обновлением полных байтов, а не отдельных битов?

редактировать: Поскольку вопрос был закрыт из-за того, что он был не по теме, я немного изменил введение. Я сожалею, если некоторые комментарии больше не являются полностью достоверными. Поскольку я не совсем понимаю, почему вопрос был закрыт (тем более, что есть EEPROM-tag), я был бы благодарен за подсказку, где на stackexchange лучше всего подойдет вопрос.

, 👍5

Обсуждение

Хороший вопрос! Вы можете рассмотреть возможность добавления нулей вместо единиц (255 → 254 → 252 → 248 → 240 → 224 → 192 → 255), что касается EEPROM, чистая операция “записи” только превращает единицы в нули. В AVR вы также можете попробовать использовать режим “только запись” EEPROM (см. Таблицу данных) вместо режима “Стирание и запись за одну операцию”, который используется библиотекой Arduino EEPROM., @Edgar Bonet

Спасибо вам за ваш комментарий. Если я правильно понимаю, если я перейду от 00000001 к 00000011, то на самом деле произойдет 00000001-> 11111111-> 00000011. Итак, для того, чтобы моя стратегия имела хоть какую-то надежду иметь смысл, мне нужно работать с нулями вместо единиц?, @maxmilgram

Это мое понимание, но я далек от того, чтобы быть экспертом в EPPROM. Мне не терпится увидеть ответы, которые вы получите. ;-), @Edgar Bonet

Чем более [практичен solution](https://arduinoprosto.ru/q/72365/newbie-using-brown-out-detector-on-arduino-due-for-saving-variables-to-eeprom/72370#72370 ) заключается в том, чтобы сохранять данные в EEPROM только тогда, когда они вам действительно нужны - при отключении питания., @gbg

Если это надуманный вопрос (например, домашняя работа), то вам просто нужно найти умный ответ, как вы с Эдгаром нашли. Кстати, 1 МБ EEPROM, если вы переворачиваете 1 бит из 8 каждую секунду для каждого байта, должно хватить вам более 90 дней. Если это реальная жизнь, не забывайте о более широкой (практической) картине. Как указывает gbg. У меня был друг в ... много лет назад, работавший над чипом. Вы записываете данные в оперативную память, и до того, как питание полностью отключится, чип сбросит оперативную память в EEPROM. Проблема решена (если этот чип существует)., @st2000

Спасибо за дополнительные комментарии. Вопрос относится к реальному проекту, поэтому все решения находятся на столе. Лично я бы предпочел решение без дополнительного оборудования. Если действительно возможно свести старение к переворачиванию отдельных битов, чип должен прослужить более 50 лет, что более чем достаточно. Однако для меня пока не совсем ясно, действительно ли переворачивание отдельных битов является чем-то особенным, особенно в отношении старения., @maxmilgram

Предполагаю, что разница заключается в количестве изменений. Реальная история: мы случайно записали время в EEPROM и обнаружили это только тогда, когда платы начали выходить из строя в полевых условиях... и все это почти в одно и то же время. Естественно, нам пришлось отозвать и отремонтировать платы. Итак, если у вас действительно нулевая толерантность, я бы посоветовал вам добавить способ проверки того, продолжает ли EEPROM работать должным образом. Возможно, с чем-то более умным, чем голосование большинством голосов, когда вы повторяете описанный выше подход 3 раза, сокращая срок службы EEPROM на 1/3, но получая способ убедиться, что он все еще работает., @st2000

Это трюк, который мы используем для эмуляции EEPROM ядра chipKIT для PIC32. Однако в этой ситуации, поскольку он эмулирует EEPROM с флэш-памятью, вам необходимо вручную выполнить стирание сектора, поэтому запись байта поверх существующего байта только в том случае, если разница между двумя байтами заключается в том, что некоторые биты очищаются (удаляются 0xFF), работают хорошо., @Majenko

Поскольку EEPROM (всегда) записываются по байтам, я очень сомневаюсь, что это что-то изменит в ожидаемой продолжительности жизни., @tofro


2 ответа


2

При следующем проектировании рассмотрите возможность использования FRAM, он энергонезависим и поддерживает практически неограниченное количество (10-14-е) циклов чтения-записи. Библиотека, которую я использую или EEPROM, поддерживает функцию обновления, при которой она сначала считывает память и не записывает в нее, если она должна оставаться неизменной.

,

1

Можно выполнить запись в адрес ATmega EEPROM без очистки его предыдущего значения. Режим записи устанавливается с помощью битов EEPMx в регистре EECR.

Функции записи avr-libc eeprom.h используют только режим стирания и записи, а библиотека Arduino EEPROM использует только функцию записи avr-libc eeprom.h.

Я изменил пример функции EEPROM_write из таблицы данных для записи без стирания.

#include <EEPROM.h>

void setup() {

  Serial.begin(115200);

  int address = 0;

  EEPROM.write(address, 0b11111111);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11111110);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11111101);
  Serial.println(EEPROM.read(address), BIN);

  EEPROM_write_no_erase(address, 0b11101111);
  Serial.println(EEPROM.read(address), BIN);

}

void loop() {

}

void EEPROM_write_no_erase(unsigned int uiAddress, unsigned char ucData) {
  /* Дождитесь завершения предыдущей записи */
  while (EECR & (1 << EEPE))
    ;
  /* Настройка регистров адресов и данных */
  EEAR = uiAddress;
  EEDR = ucData;
  /* Write only */
  EECR |= (1 << EEPM1);
  EECR &= ~(1 << EEPM0);
  /* Write logical one to EEMPE */
  EECR |= (1 << EEMPE);
  /* Start eeprom write by setting EEPE */
  EECR |= (1 << EEPE);
}

результат такой, как и ожидалось:

11111111
11111110
11111100
11101100

Я не знаю, увеличивает ли использование этой функции срок службы ATmega EEPROM.

,

Было бы безопаснее установить "EEMPE" и "EEPE" с отключенными прерываниями, как рекомендовано в техническом описании., @Edgar Bonet

@EdgarBonet этот код взят из таблицы данных. Я предполагаю, что он ожидает, что функция будет вызвана с отключенными прерываниями, если возможен конфликт, @Juraj