Структура EEPROM в прошивках Unwired Range

Модули Unwired Range для сети LoRa используют встроенную.память EEPROM микроконтроллеров STM32L1 для хранения как настроек радиосети, так и настроек и данных отдельных модулей, динамически подключаемых пользователем.

В зависимости от модели микроконтроллера, объём этой памяти может отличаться — 4 кбайта у STM32L151CB и 8 кбайт у STM32L151CC. Износостойкость памяти составляет 100 тыс. циклов.

Структура EEPROM

На нижней границе EEPROM хранятся базовые настройки модуля — его адрес EUI64, ключи шифрования, радиоканал, скорость сети и так далее. Соответствующие структуры описаны в файле unwired-modules\lora-star-end-device\include — config_eui64_t и nvram_config_t (там же до поры до времени хранится nvram_old_config_t, нужная для безболезненного обновления прошивки с одной из старых версий).

В сумме эти структуры занимают менее 200 байт, с учётом запаса на будущее для них отведены младшие 256 байт EEPROM.

Выше расположены настройки конкретных программных модулей — они заранее зарезервированы для каждого из возможных модулей, и не могут меняться. Каждый модуль располагает 24 байтами для сохранения своей конфигурации (плюс два байта контрольной суммы Fletcher16 добавляются автоматически), чтение и запись конфигурации производится самим модулем функциями unwds_read_nvram_config и unwds_write_nvram_config, структура конфигурации не определена и меняется от модуля к модулю. Если функция чтения конфигурации возвращает false, модуль должен самостоятельно заполнить соответствующую структуру данных значениями по умолчанию.

Всего в прошивке Unwired Range может быть до 126 модулей: номера от 1 до 49 присваиваются модулям стандартной прошивки, от 50 до 99 — коммерческой, от 100 до 125 — модулям из собственных прошивок клиента, 126 — системный модуль. Память EEPROM распределена жёстко, её структура не зависит от количества модулей, включённых в данную прошивку, что гарантирует сохранение настроек модулей даже при смене прошивки (например, если поверх commercial установить lora-star-simple, то модуль umdk-pulse пропадёт, т.к. в lora-star-simple его нет; если вернуть прошивку commercial, модуль umdk-pulse не только вернётся, но и восстановит свои прежние настройки).

Системный модуль umdk-config не имеет собственных настроек, однако зарезервированное для него место используется для хранения таблицы использования пространства nvram_storage — динамически выделяемого объёма энергонезависимой памяти для модулей, которым требуется хранение большего объёма данных.

В зависимости от микроконтроллера, nvram_storage может обслуживать 4 или 16 модулей, с объёмом данных до 128 или 256 байт каждый. К каждому блоку данных добавляется контрольная сумма Fletcher16.

Модуль, которому необходимо это хранилище, при инициализации должен вызвать функцию unwds_read_nvram_storage, описанную в файле unwired-modules\unwds-common\include\unwds-common.h. Если ранее этот модуль уже использовался, и дополнительная память в EEPROM для него выделена, ему будут возвращены данные, хранящиеся в ней. Если модуль запускается впервые, то система найдёт первый свободный (не используемый другими модулями) участок EEPROM в области nvram_storage, обнулит его содержимое и присвоит его данному модулю. Если данная функция возвращает false, модуль должен самостоятельно заполнить соответствующую структуру данных значениями по умолчанию.

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

Таким образом, до некоторого порога включение и выключение пользователем модулей, использующих расширенное хранилище nvram_storage, не будет приводить к потере ими хранимых там данных. Однако если таких модулей много, то при заполнении nvram_storage система начнёт очищать его от данных, относящихся к модулям, в данный момент неактивным.

Запись данных в блок nvram_storage осуществляется функцией unwds_write_nvram_storage. Структура данных не фиксирована и меняется от модуля к модулю.