Хотя ESP-IDF (а так же Arduino Core) содержат функции для работы с NVS (библиотеки EEPROM и Preferences в Arduino), как таковой EEPROM в SoC от Espressif не предусмотрено: вместо этого EEPROM эмулируется на FLASH памяти и для этого на флеше есть специальный раздел, который по умолчанию называется "nvs".
NVS в ESP устроена в виде линейной базы данных, с одним уровнем иерархии: помимо обычных "ключ=значение" в NVS так же сохраняется т.н. namespace. Ключи могут иметь одинаковые имена если он относятся к разым неймспейсам. Здесь и далее по тексту: термины пространство имен, неймспейс, namespace и каталог означают одно и то же.
ESPShell позволяет перемещаться по NVS образом, похожим на работу с фаловой системой: есть знакомые ls, cd, rm. Для создания новых и изменения существующих значений есть команды new и set, а для экспорта и импорта есть команды import и export, сохраняющие NVS в виде текстового файла, что позволяет переносить NVS между разными устройствами и версиями NVS. Текстовый файл содержит команды ESPShell которые можно выполнить командой "exec" или "import" (на самом деле коанда "import" - это алиас команды "exec")
Для запуска NVS редактора нужно выполнить команду nvs:
esp32#>nvs esp32-nvs(/)>Появившееся приглашение говорит нам о том, что редактор запустился и мы находимся в корневом каталоге. В этом каталоге находятся пространства имен или namespaces, которые можно пролистать командой "ls" или активировать командой "cd": лучше всего думать о пространствах имен как о каталогах в фаловой системе. Чтобы выйти из режима редактирования NVS нужно выполнить команду "exit" или нажать Ctrl+z
Рис. 1: Пример работы и вывод команд cd и ls
Для просмотра информации из NVS используется три команды: cd, ls и dump. Последняя используется лишь в тех случаях, когда команды "ls" недостаточно: например, если данные это текстовая строка, то команда ls покажет лишь первые 42 символа, а если тип данных - бинарный blob, то ls покажет лишь длину блока данных и первые 16 байт. Команда ls имеет один необязательный параметр: пространство имен. Если параметр опущен, то используется то значение, которое было установлено командой cd. Команда ls, будучи выполненной в корневом каталоге пространства имен выведет список пространства имен:
esp32-nvs(/)>ls % NVS has 3 namespaces: % Namespace "espshell" : 2 keys % Namespace "phy" : 4 keys % Namespace "nvs.net80211" : 25 keys esp32-nvs(/)>Если же зайти, скажем, в пространство имен phy (это WiFi драйвер) командой "cd /phy", то выполнив там команду ls без параметров, получим табличку-список ключей и их значений:
esp32-nvs(/)>cd phy esp32-nvs(/phy)ls % # | Key name | Type | Value (strings may be truncated. use "dump") % --+------------------+--------+----------------------------------------------- % 1| cal_address | char[] | <A binary blob, not displayed>, 1 bytes % 2| cal_data | char[] | <A binary blob, not displayed>, 1904 bytes % 3| cal_mac | char[] | <A binary blob, not displayed>, 6 bytes % 4| cal_version | uint32 | 701 % --+------------------+--------+----------------------------------------------- % Total: 4 recordsА можно - указать пространство имен непосредственно команде, ее первым аргументом:
esp32-nvs(/phy)>ls ../espshell % # | Key name | Type | Value (strings may be truncated. use "dump") % --+------------------+--------+----------------------------------------------- % 1| tz | char* | UTC-07:00 % 2| hostid | char* | <empty> % --+------------------+--------+----------------------------------------------- % Total: 2 records esp32-nvs(/phy)>ПРИМЕЧАНИЕ: Для команды "cd" существование пространства имен не обязательно: если выполнить "cd sdfgsdfg" то никакой ошибки не произойдет и namespace будет установлено именно таким. При создании первого ключа в данном пространстве имен, оно появится в списке команды "ls /". Если же namespace будет пустым, то после выхода из него (например, командой cd /) пространство имен будет удалено.
Как уже было указано, команда ls выводит содержимое NVS в виде таблицы: в ней указаны названия и типы ключей, а так же их значения, если эти значения являются числами. Строки отображаются целиком,только если они короче 42 символов, а бинарные данные (blob) не отображаются вовсе. Для отображения строк целиком, а так же бинарных данных существует команда dump KEY.
esp32-nvs(/phy)>dump cal_address 10 11 22 33 44 55 esp32-nvs(/phy)>Для данных небольшого размера (т.е. до 16 байт. лимит можно изменить с помощью команды "var tbl_min_len") отображение осуществляется в виде строчки. Для данных больщего размера включается форматированный табличный вывод:
Рис. 2: Пример работы и вывод команды dump sta.apinfo
Команда "dump" так же позволяет выводить длинные строчки, которые могут быть обрезаны командой "ls", целиком. Фомат вывода, впрочем, отличается от формата вывода бинарных данных:
mars@esp32-nvs(/espshell)>dump hostid % "hostid" = "mars" mars@esp32-nvs(/espshell)>Команда cd позволяет заходить в пространства имен. Выбранное пространство имен будет отображаться в строке-приглашении:
esp32-nvs(/)>cd espshell esp32-nvs(/espshell)>Как и при работе с файловой системой, команда "cd" редактора NVS может работать с относительными путями:
esp32-nvs(/espshell)>cd ../phyКаталог / (корневой каталог NVS) не содержит ни ключей ни их значений - в корневом каталоге расположены пространства имен. Как уже было сказано выше, NVS имеет лишь один уровень иерархии, поэтому "каталог в каталоге" создать нельзя.
| Команда | Описание и примеры |
|---|---|
| ls [PATH] |
Получить листинг каталога (пространства имен) или список пространств имен esp32-nvs(/)>ls %% NVS namespaces: % Namespace "espshell" : 2 keys % Namespace "phy" : 4 keys esp32-nvs(/)> esp32-nvs(/)>ls espshell % # | Key name | Type | Value (strings may be truncated. use "dump") % --+------------------+--------+----------------------------------------------- % 1| hostid | char* |Если PATH не указан, то использется путь, который был задан до этого командой "cd" |
| cd PATH |
Сменить текущий каталог (пространство имен) на PATH. В качестве PATH может быть указано существующее ролстранство имен (и тогда команда "ls" что-то покажет) а может - несуществующее. В случае, когда PATH не существует, он будет создан. Это поведение используется для создания новых записей: если вам захотелось создать неймспейс "my_prefs" а в нем - записи, то нужно сменить каталог командой cd а затем создать записи командой new. Если никаких записей не создать и выйти, то такой пустой неймспейс будет тут же удален. esp32-nvs(/)>cd my_prefs esp32-nvs(/my_prefs)>ls % Namespace "my_prefs" (partition: "nvs") is empty or does not exist esp32-nvs(/my_prefs)>new TestKey char % Key created. Use "set TestKey ..." to set its value esp32-nvs(/my_prefs)> |
| cd PATH |
Сменить текущий каталог (пространство имен) на PATH. В качестве PATH может быть указано существующее ролстранство имен (и тогда команда "ls" что-то покажет) а может - несуществующее. В случае, когда PATH не существует, он будет создан. Это поведение используется для создания новых записей: если вам захотелось создать неймспейс "my_prefs" а в нем - записи, то нужно сменить каталог командой cd а затем создать записи командой new. Если никаких записей не создать и выйти, то такой пустой неймспейс будет тут же удален. esp32-nvs(/)>cd my_prefs esp32-nvs(/my_prefs)>ls % Namespace "my_prefs" (partition: "nvs") is empty or does not exist esp32-nvs(/my_prefs)>new TestKey char % Key created. Use "set TestKey ..." to set its value esp32-nvs(/my_prefs)> |
| dump KEY_NAME |
Выводит на экран значение ключа KEY_NAME в текущем пространстве имен. Эта команда работает только
со строками и бинарными данными.
esp32-nvs(/)>cd phy esp32-nvs(/phy)>dump cal_address % f0 9e 9e 22 7b 2c |
Чтобы создать новый элемент в NVS (т.е. создать новый ключ) следует выполнить команду "new", которая создаст новую запись и установит ее значение в 0 (для скалярных типов) или в однобайтовый буфер, внутри которого, опять же ноль.
esp32-nvs(/)>cd phy esp32-nvs(/phy)>new Key unsigned char % Key created. Use "set Key ..." to set its value esp32-nvs(/phy)>В данном примере мы создали запись с именем "Key", в пространстве имен "phy". Тип данных, который будет хранится в этой записи - unsigned char, т.е. беззнаковый байт. Для указания типа данных используется синтаксис принятый в Си\Си++; поддерживаются следующие типы:
Для удаления записей из NVS используется команда rm: она имеет один обязательный параметр. То, как работает эта команда станет понятнее из примеров. Предположим, что мы находимся в каталоге (namespace) "espshell":
esp32-nvs(/)>cd espshell esp32-nvs(/espshell)>Если мы выполним команду rm tz, то ключ tz из пространства имен espshell будет удален. Чтобы удалить ВСЕ ключи в данном пространстве имен, вместо имени ключа следует указать звездочку ("*")
esp32-nvs(/)>cd espshell esp32-nvs(/espshell)> esp32-nvs(/espshell)>rm * % All keys in the namespace "espshell" were removed esp32-nvs(/espshell)>Для удаления пространства имен целиком так же можно задать его первым аргументом команды rm:
esp32-nvs(/phy)>rm ../espshellДля удаления всех записей вообще, следует выполнить команду rm * непосредственно в корневом каталоге (в "/") или выполнить команду "rm /" в любом каталоге. Удаление записей NVS происходит без подтверждения (espshell не будет спрашивать у вас, уверены ли вы в том, что хотите удалить то или это)
Для установки значения существующего ключа (существующего или созданного командой "new") можно воспользоваться командой "set". У команды всего два параметра: название ключа и новое значение. Например, установим ключ "tz" в пространстве имен "espshell" в значение "Hello World!":
esp32-nvs(/espshell)>set tz Hello World! esp32-nvs(/espshell)>ls % # | Key name | Type | Value (strings may be truncated. use "dump") % --+------------------+--------+----------------------------------------------- % 1| hostid | char* |Для установки бинарных данных (char[]) используется Си-подобный синтаксис: символы, за исключением специальных (начинающихся с "\", например "\n" или "\22") сохраняются "как есть". Символы \r\n\t\v преобразуются в соответствии с правилами Си\Си++, символы вида \AB (где A и B - шеснадцатиричные цифры) преобразуются в байт со значением 0xAB. Пример: установить значение cal_data равным 0x10, 0x20, Hello, 0x20, 0x10% 2| tz | char* | Hello World! % --+------------------+--------+----------------------------------------------- % Total: 2 records esp32-nvs(/espshell)>
esp32->nvs(/phy)set cal_data \10\20Hello\20\10
| Команда | Описание и примеры |
|---|---|
| new KEY_NAME KEY_TYPE |
Создать ключ типа KEY_TYPE с именем KEY_NAME. В качестве KEY_TYPE может быть указан один из скалярных типов языка Си (т.е. char, short, int, long, unsigned/signed, long long, char *, char []) Пример: создать запись cal_address, задать значение cal_address таким - 0011:2233:4455 esp32-nvs(/)>cd phy esp32-nvs(/phy)>new cal_address char[] % Key created. Use "set cal_address ..." to set its valueЕсли ключ уже существует, то он будет обнулен (строки превратятся в строчки нулевой длины а массивы - в массивы состоящие из одного байта, нуля) |
| set KEY_NAME KEY_VALUE |
Задать новое значение для ключа KEY_NAME. Аргумент KEY_VALUE это либо число (в случае со скалярными типами) либо строка\массив. Массив и строка задаются одним и тем же способом. Пример: Изменить запись cal_address, задать значение 0011:2233:4455 esp32-nvs(/phy)>set cal_address \00\11\22\33\44\55 |
| rm PATH | Удалить ключи\пространства имен. В качестве аргумента указывается или название ключа или пространство имен. Если в качестве PATH указать "/" (корневой каталог) до будут удалены вообще все данные NVS Если в качестве PATH указать название пространства имен, то будут удалены все ключи в данном пространстве имен. Ну а если команде передать название ключа, то команда удалит только указанный ключ. |
Для того, чтобы сохранить содержимое NVS в файл существует команда "export":
esp32-nvs(/nvs.net80211)>export nvs_backup.txt % Exporting namespace "nvs.net80211".. esp32-nvs(/nvs.net80211)>Команда может использоваться для экспорта отдельных каталогов (пространств имен) а может - для экспорта всего содержиого NVS целиком. Последний аргумент команды это всегда имя файла, в который требуется сохранить данные из NVS. Пространство имен можно указать, а можно - не указывать. В таком случае в качестве пространства имен для экспорта будет использовано текущее пространство имен. Синтаксис команды станет понятнее из примеров:
esp32-nvs(/phy)#>export /ffat/data.txt ← экспортировать текущее пространство имен (т.е. "phy") esp32-nvs(/phy)#>export ../espshell /ffat/data.txt ← экспортировать настройки espshell esp32-nvs(/phy)#>export / /ffat/data.txt ← экспортировать все содержимое NVS esp32#>
Сохраненный файл с данными NVS можно будет загрузить командой "import":
esp32-nvs(/phy)#>import /ffat/data.txt ← импортировать данные из файла в NVS.При импорте совершенно не важно, в каком каталоге вы находитесь - можно выполнять импорт находясь в корневом каталоге или в каталоге, скажем, "phy", на результат это не повлияет никак. При экспорте то, в каком каталоге вы находитесь имеет значение лишь в случае, когда команда "export" запускается с одним аргументом - именем файла.
| Команда | Описание и примеры |
|---|---|
| export [NVS_PATH] FILE_PATH | Экспорт содержимого NVS в текстовый файл (файловая система должна быть смонтирована, см. "mount") Если в качестве NVS_PATH указать "/" (корневой каталог) до будут экспортированы все данные NVS (все пространства имен).
esp32-nvs(/espshell)>export / file.txt ← экспортировать все содержимое NVS в файл
Если в качестве NVS_PATH указать название пространства имен, то будет экспортировано указанное пространство имен.
esp32-nvs(/espshell)>export /phy file.txt ← экспортировать содержимое пространства имен "phy"
Если же параметр NVS_PATH опустить, то будет экспортировано текущее пространство имен:
esp32-nvs(/espshell)>export file.txt ← экспортировать пространство имен "espshell"
|
| import FILE_PATH | Импорт содержимого текстового файла (файловая система должна быть смонтирована, см. "mount")
esp32-nvs(/espshell)>import file.txt
|