Comments 15
Следующим шагом будет расширение подобного простого NVS до полноценной NVRAM, для чего понадобятся:
wear-out leveling, т.е. выравнивание нагрузки на страницы флеша, чтобы многократная запись в переменную Х использовала не только страницу, куда Х была записан изначально, но все доступные по очереди.
fault-tolerant write, т.е. такой алгоритм записи в переменную, который гарантирует, что "настоящей" эта запись станет исключительно после того, как все данные и все критические для правильной работы метаданные уже записаны, а все остальное можно однозначно восстановить после перезагрузки.
transparent storage backup, т.е. такой алгоритм управления хранилищем, который гарантирует, что при его разрушении у нас есть копия большинства переменных, пусть даже и не самая свежая.
Понятно, что нужно вот это все только там, где софт много пишет в свою же NVRAM по разным причинам. Именно так делают большинство современных систем вычислительных систем разных архитектур, в том числе ПК на х86 (использующие UEFI NVRAM), вся техника Apple (iBoot NVRAM), и т.п.
transparent storage backup, т.е. такой алгоритм управления хранилищем, который гарантирует, что при его разрушении у нас есть копия большинства переменных, пусть даже и не самая свежая.
Можно организовать RAID5. Тогда можно будет сломать 1 чип из трех.
А потом подцепим littlefs
NVRAM еще окажется полезной, если на SPI-NOR Flash придется запускать FаtFS.
А в чем сложность использования SPI nor и fatfs?
А в чем сложность использования SPI nor и fatfs?
FatFs может писать только в один блок, а остальные 99,99% NOR Flash не использовать. Далее через 10k..100k записей следует невосстанавливаемый отказ NOR Flash памяти.
Между SPI-NOR Flash и FatFs должен работать отдельный умный программный компонент: NVRAM
Можно, конечно, использовать FatFs в режиме ReadOnly, но кто-то должен прописать изначальный образ файловой системы.
Программирование МК это трудная работа
Вот вам яркий пример. Нельзя просто взять и записать в память...
В программировании MK все задачи решается с огромным поездом из если. Вот к примеру список ограничений на запись массива во flash память микроконтроллера fc7300f8mdt.
1—можно записывать массив начиная с длины 8 байт
2—можно записывать за раз не более 128 байт
3—адрес записи должен быть выровненным по 128 байт (начиная с нуля)
5—перед записью надо разлочить память
6—активировать прерывание по окончанию записи
7—после записи проверить регистры состояния записи
8—после записи надо залочить память
9—Нельзя до-записать страницу. Если в странице хоть один бит из 1024 бит в нуле, то страница полностью использована. Повторная запись страницы приведет к непредсказуемому результату. Проще говоря писать можно только в те страницы, которые полностью покрыты 0xFF.
10—стирать можно только сектора по 8kByte
4—стирать сектора можно только по выровненным адресам с периодом 8kByte
Нормально как препонов наставлено, правда? При этом надо как то написать драйвер, который будет видеть эту память как обычную RAM (NVRAM).
Достаточно просто портировать LittleFS и wear-out leveling + fault-tolerant write появятся сами собой.
https://habr.com/ru/articles/925372/
Предложенный алгоритм работы с сохраненными настройками (читай переменными ) нашей программы имеет недостаток по скорости работы программы с этими самыми настройками.
Для МК более практична следующая схема организации хранения данных. И мы в данном случае говорим о достаточно навороченной системе, которая оперирует больше сотни разных настроек.
Переменные которые меняются очень редко , один два раза в сутки , и которые должны быть всегда легко доступны командами непосредственного чтения памяти по адресу или указателю - размещаем во FLASH памяти на кристалле.
Большие объемы данных, а так же длинные структуры (строковые данные настройки длиной более 32 символов, ВЕБ страницы) - размещаем во внешней SPI памяти
Часто меняющиеся значения, например счетчики , размещаем в относительно энергонезависимой памяти микросхемы часов (пока батарейка не помрет).
Таким образом достигается возможность хранения больших объемов информации , быстрый доступ к часто используемым переменным , и бережем ресурсы памяти.
Nvram по-русски.
Неоднократно я был свидетелем как в России выкручиваются от неспособности запрограммировать полноценный NVRAM.
Выглядит этот так.
Схемотехники в плату закладывают три или 6 GPIO пинов и джамперами выставлять бинарный код на GPIO, чтобы при старте дать прошивке какую-то команду.
Получается 1х3х6=18 кубических миллиметров на бит.
Например в STM32 первые 4 сектора вообще по 16kByte, остальные больше по 128kByte. Это сделано специально, с расчетом на то, чтобы запускать на маленьких сесекторах по 16kByte FlashFS(cы)
Всегда думал, что они для того чтобы туда записывать свой бутлоадер (т.н. second bootloader). Куда его тогда предлагаете записывать если эти сектора будут заняты под storage?
В самом первом секторе Flash стоит разместить крохотный первичный загрузчик master boot record (MBR). Его можно уместить и в 16kByte, а если писать на ASM то и в 1кByte можно.
Который просто прыгнет на вторичный загрузчик на Custom(ном) отступе (последний сектор Flash).
В моих проектах на STM32 карта памяти обычно такая:

как показывает практика - чем сложнее система тем больше вероятность накосячить.
в тоже время простой ионистор и уход в сон по снижению питания помогут сохранить переменные в памяти с минимальными накладными расходами.
КМК — это разные темы, хранение пользовательских данных вообще и обеспечение их целостности при авариях.
Да и ионистор — отнюдь не так прост. Сам не пользовался, но наслышан о заменах ионисторов в palmtop'ах лет 18 назад.
как показывает практика - чем сложнее система тем больше вероятность накосячить.
Надо просто модульные тесты в код добавлять и прогонять их периодически. Тогда можно масштабировать сложность хоть до Луны.
NVRAM для микроконтроллеров