Как предотвратить "частичную запись" повреждения данных при отключении питания?
Во встроенной среде (с использованием MSP430) я видел некоторое повреждение данных, вызванное частичной записью в энергонезависимую память. Кажется, это вызвано потерей мощности во время записи (в FRAM или в информационные сегменты).
Я проверяю данные, хранящиеся в этих местах, с помощью CRC.
Мой вопрос: как правильно предотвратить эту "частичную запись"? В настоящее время я изменил свой код для записи в два отдельных места FRAM. Таким образом, если одна запись прервана из-за неправильного CRC, другое местоположение должно остаться в силе. Это обычная практика? Нужно ли реализовать это поведение двойной записи для любой энергонезависимой памяти?
4 ответа
Простым решением является поддержка двух версий данных (на отдельных страницах для флэш-памяти), текущей версии и предыдущей версии. Каждая версия имеет заголовок, состоящий из порядкового номера и слова, которое проверяет порядковый номер - просто дополнение 1 к порядковому номеру, например:
---------
| seq |
---------
| ~seq |
---------
| |
| data |
| |
---------
Критическим моментом является то, что при записи данных seq
а также ~seq
слова написаны последними.
При запуске вы читаете данные, которые имеют наибольший действительный порядковый номер (возможно, с учетом переноса - особенно для коротких последовательных слов). Когда вы пишете данные, вы перезаписываете и проверяете самый старый блок.
Решение, которое вы уже используете, действует до тех пор, пока CRC написан последним, но ему не хватает простоты и накладываются накладные расходы на вычисление CRC, которые могут быть необязательными или нежелательными.
На FRAM вы не заботитесь о выносливости, но это проблема флэш-памяти и EEPROM. В этом случае я использую метод кэширования с обратной записью, где данные хранятся в ОЗУ, и при изменении таймер запускается или перезапускается, если он уже работает - когда истекает таймер, данные записываются - это предотвращает пакетную запись от перегрузки памяти, и это полезно даже на FRAM, так как это минимизирует программные издержки записи данных.
Наша команда инженеров использует два подхода к решению этой проблемы: решите это с помощью аппаратного и программного обеспечения!
Первый - это диодно-конденсаторное устройство, обеспечивающее несколько миллисекунд питания во время отключения. Если мы заметим, что потеряли внешнее питание, мы не дадим коду ввести любые записи без нарушения.
Во-вторых, наши данные особенно важны для работы, они часто обновляются, и мы не хотим изнашивать наше постоянное флэш-хранилище (оно поддерживает только столько операций записи), поэтому мы фактически храним данные 16 раз во флэш-памяти и защищаем каждый из них. запись с кодом CRC. При загрузке мы находим самую новую действительную запись и затем запускаем наши циклы стирания / записи.
Мы никогда не видели искажения данных с момента внедрения нашей откровенно параноидальной системы.
Обновить:
Я должен отметить, что наша флэш-память является внешней по отношению к нашему ЦП, поэтому CRC помогает проверять данные, если существует сбой связи между ЦП и флэш-чипом. Кроме того, если мы сталкиваемся с несколькими сбоями подряд, множественные записи защищают от потери данных.
Мы использовали нечто похожее на ответ Клиффорда, но написанное в одной операции записи. Вам нужно две копии данных и чередовать их. Используйте увеличивающийся порядковый номер, чтобы фактически одно местоположение имело четные порядковые номера, а другое - нечетное.
Запишите данные, как это (в одной команде записи, если вы можете):
---------
| seq |
---------
| |
| data |
| |
---------
| seq |
---------
Когда вы читаете его обратно, убедитесь, что оба порядковых номера совпадают - если они не совпадают, то данные являются недействительными. При запуске прочитайте оба местоположения и определите, какое из них является более поздним (с учетом смены порядкового номера).
Всегда храните данные в каком-то протоколе, например START_BYTE, Всего байтов для записи, данные, END BYTE. Перед записью во внешнюю / внутреннюю память всегда проверяйте регистры POWER Moniter / ADC. если вы каким-либо образом повредите данные, байт END также будет поврежден. Таким образом, эта запись не будет аннулирована после проверки всего протокола. Контрольная сумма не очень хорошая идея, вы можете выбрать CRC16 вместо этого, если хотите включить CRC в свой протокол.