radio_esp32::nvs
nvs_* — the blob’s key/value store, over lib/kvstore.
Twelve table entries. The Wi-Fi driver keeps small things here: the country
code, the stored AP record, a handful of flags. It is not where the
calibration blob goes — that has its own module, because it is 1904 bytes
and needs a commit point (see [crate::calibration]).
Namespaces, which kvstore has not got
Section titled “Namespaces, which kvstore has not got”esp-idf’s NVS is namespaced: nvs_open("wifi", ..) gives a handle, and
every key is scoped to it. kvstore is one flat keyspace, so the namespace
is folded into the key as <namespace>:<key>.
That is not free, and the arithmetic is the reason the limits below exist:
kvstore’s [MAX_KEY_LEN] is 32, and IDF allows 15 characters each of
namespace and key, which is 15 + 1 + 15 = 31. It fits, with a byte spare,
and [MAX_NAME_LEN] enforces the halves rather than letting a long name
silently collide with a different one after truncation.
Types are checked, because IDF checks them
Section titled “Types are checked, because IDF checks them”Every value carries a one-byte tag. nvs_get_u8 on something stored by
nvs_set_u16 returns ESP_ERR_NVS_TYPE_MISMATCH, as it does in IDF —
without the tag it would return the first byte of the u16 and look like
a working read. The tag costs one byte per record and removes a whole
class of silent wrong answers.
What is deliberately not implemented
Section titled “What is deliberately not implemented”nvs_commit is a no-op. kvstore writes through — a set has reached
flash by the time it returns — so there is nothing to flush, and returning
ESP_OK is the truthful answer rather than a stub’s shrug. nvs_close
releases the handle and nothing else, since there is no cached state to
write back.
Error values are esp-idf v4.4’s, read from components/nvs_flash/include/ nvs.h at the tag tools/fetch-blobs.sh pins.
Structs
Section titled “Structs”struct Probe { pub set_full: u32, pub no_heap: u32, pub compacted: u32, pub reclaimed: u32, pub compact_err: u32, pub retry_ok: u32, pub retry_err: u32,}What the compaction path did, counted rather than logged.
The previous hardware run was read as “compaction ran and the retry failed” on the strength of a log line that was missing, which is not evidence of anything: a line can be lost to a level filter, to a serial drop, or to the reset that the run ended in. A counter the application reads back afterwards distinguishes the three ways the retry can fail – the arm never runs, the heap refuses, the store refuses – and cannot go missing.
Implements: Clone, Copy, Debug, Default, Eq, PartialEq, StructuralPartialEq
Functions
Section titled “Functions”fn probe() -> ProbeThe compaction counters so far this boot.
References: Probe
Constants
Section titled “Constants”ESP_ERR_NVS_INVALID_HANDLE
Section titled “ESP_ERR_NVS_INVALID_HANDLE”const ESP_ERR_NVS_INVALID_HANDLE: i32;ESP_ERR_NVS_INVALID_LENGTH
Section titled “ESP_ERR_NVS_INVALID_LENGTH”const ESP_ERR_NVS_INVALID_LENGTH: i32;ESP_ERR_NVS_INVALID_NAME
Section titled “ESP_ERR_NVS_INVALID_NAME”const ESP_ERR_NVS_INVALID_NAME: i32;ESP_ERR_NVS_NOT_ENOUGH_SPACE
Section titled “ESP_ERR_NVS_NOT_ENOUGH_SPACE”const ESP_ERR_NVS_NOT_ENOUGH_SPACE: i32;ESP_ERR_NVS_NOT_FOUND
Section titled “ESP_ERR_NVS_NOT_FOUND”const ESP_ERR_NVS_NOT_FOUND: i32;ESP_ERR_NVS_READ_ONLY
Section titled “ESP_ERR_NVS_READ_ONLY”const ESP_ERR_NVS_READ_ONLY: i32;ESP_ERR_NVS_TYPE_MISMATCH
Section titled “ESP_ERR_NVS_TYPE_MISMATCH”const ESP_ERR_NVS_TYPE_MISMATCH: i32;ESP_ERR_NVS_VALUE_TOO_LONG
Section titled “ESP_ERR_NVS_VALUE_TOO_LONG”const ESP_ERR_NVS_VALUE_TOO_LONG: i32;ESP_OK
Section titled “ESP_OK”const ESP_OK: i32;MAX_BLOB_LEN
Section titled “MAX_BLOB_LEN”const MAX_BLOB_LEN: usize;Largest blob, after the tag byte.
MAX_NAME_LEN
Section titled “MAX_NAME_LEN”const MAX_NAME_LEN: usize;Longest namespace or key, each. IDF’s own limit, and what makes the
composite key fit kvstore’s.