The latest development version of this page may be more current than this released 0.4.3 version.

NVS

Overview

Non-Volatile Storage (NVS) is a module that uses flash memory to store key-value pairs. This document will introduce some basic concepts of NVS.

Basic Principle

The NVS library uses part of the main flash memory by calling the wm_nvs API API, specifically using the partition named “nvs” in the flash partition table to store data.

Note

NVS is best suited for storing smaller data. For larger data storage, consider using a file system.

Key-Value Pairs

NVS operates on key-value pairs, where the key is an ASCII string with a maximum length of 15 characters. The stored values can be of the following types:

  • Integers: uint8_t , int8_t , uint16_t , int16_t , uint32_t , int32_t , uint64_t and int64_t ;

  • Strings: Null-terminated strings

  • Binary data: Variable length binary data (BLOB)

  • Floating point: double type floating point numbers

Warning

When storing string data, the trailing \0 character is also stored, so the actual stored length is the length obtained by the strlen function plus 1. When retrieving a string, the buffer length should be one more than the actual number of characters, otherwise an invalid parameter error will be returned.

Note

Each flash sector is currently 4096 bytes. NVS storage cannot span sectors. By default, each sector has 20 bytes of header to mark the sector’s usage status, and each data item has a 24-byte header. Therefore, whether storing strings or binary data, their size cannot exceed 4052 bytes.

Note

Although NVS provides read and write for integers and floating points, it’s also possible to convert integers and floating points to strings for storage in the project.

Keys must be unique. Writing a new value to an existing key will replace the old value and its data type.

When reading a value, a data type check is performed. If the expected data type for the read operation does not match the data type of the corresponding key, an error is returned.

Grouping

NVS does not support grouping. If users need to group key-values, it’s suggested to add a group prefix to a set of keys, such as wifi.ssid. The iterator traversal interface supports prefix traversal, and specifying a prefix will retrieve all key-value pairs with that prefix.

NVS Iterator

Iterators allow traversing data in NVS. You can specify a key-value to retrieve or specify a prefix to retrieve a set of key-values. If not specified, all key-values will be traversed.

Use the following functions for related operations:

  • wm_nvs_entry_find: Creates an opaque iterator handle and points the iterator to the first record, for subsequent calls to wm_nvs_entry_next , wm_nvs_entry_info , and wm_nvs_entry_data .

  • wm_nvs_entry_next: Points the iterator to the next key-value pair.

  • wm_nvs_entry_info: Returns information about the current key-value pair.

  • wm_nvs_entry_data: Returns the data of the current key-value pair.

  • wm_nvs_release_iterator: Releases the iterator handle.

In summary, all iterators obtained through wm_nvs_entry_find() (including NULL iterators) must be released using wm_nvs_release_iterator() .

Functional Implementation

To accommodate diverse user needs, we can implement multiple functions:

  • NVS Initialization:

    wm_nvs_init

  • String Write and Read:

    wm_nvs_set_str, wm_nvs_get_str

  • Binary Data Write and Read:

    wm_nvs_set_blob, wm_nvs_get_blob

  • 8-bit, 16-bit, 32-bit, 64-bit Integer Write and Read:

    wm_nvs_set_i8, wm_nvs_get_i8

    wm_nvs_set_i16, wm_nvs_get_i16

    wm_nvs_set_i32, wm_nvs_get_i32

    wm_nvs_set_i64, wm_nvs_get_i64

    wm_nvs_set_u8, wm_nvs_get_u8

    wm_nvs_set_u16, wm_nvs_get_u16

    wm_nvs_set_u32, wm_nvs_get_u32

    wm_nvs_set_u64, wm_nvs_get_u64

  • Floating Point Read and Write:

    wm_nvs_set_floatwm_nvs_get_float

  • Traverse NVS Data Items and Print:

    wm_nvs_print

  • Get Data Item Type and Size:

    wm_nvs_get_info

  • NVS Data Item Deletion:

    wm_nvs_del

  • NVS Reset:

    wm_nvs_reset

  • NVS Iteration Interface:

    wm_nvs_entry_find : Create iterator, point iterator to the first record

    wm_nvs_entry_next : Move to the next record

    wm_nvs_entry_info : Get key, type, and data length of record based on iterator

    wm_nvs_entry_data : Get data of record based on iterator

    wm_nvs_release_iterator : Release iterator

  • Supports Wear Leveling

  • Supports Power Failure Protection

  • Supports Hash Quick Read and Write

Note

After executing wm_nvs_reset , the NVS partition will be formatted, and all stored data will be cleared. Use with caution.

Configuration Method

To adjust the NVS size in the project, adjust the partition named nvs in the partition table. Both the starting address and size can be adjusted. Specific configuration is as follows:

# name,         offset,        size,       flag
nvs,            0x1F0000,      0x8000,     0x0

For detailed configuration, refer to the partition table section.

Note

When the data is full, it needs to recycle deleted data. To prevent data loss due to power failure during the recycling process, a dedicated sector is needed for recycling. Therefore, the actual available space will be 4K less. The size should be configured to at least 2 sectors, i.e., at least 0x2000.

Module Configuration

  • Hash Table Configuration

    The hash table is created to speed up reading and writing. During initialization, the NVS storage partition is scanned, and an address offset table is established in memory. During read and write, the key is converted to an index by hash calculation, and the offset address of the key-value is directly obtained from the table, enabling fast value retrieval. The initial number of hash table entries is 53, which dynamically expands as the number of stored data entries increases. When the number of stored data entries exceeds 75%, the hash table length is dynamically expanded, adding about 50 entries each time. Each entry occupies 3 bytes. Disabling the hash table can save memory space roughly equal to the number of stored entries * 4, but at the cost of traversing each sector during read and write.

    CONFIG_NVS_HASH_ENABLED can configure whether to use the hash table. By default, it is enabled. The hash table greatly improves read and write speed, so it is not recommended to disable it.

  • Key Length Configuration

    The key length is configured using CONFIG_NVS_ITEM_NAME_MAX_SIZE, with a default configuration of 16. Since the trailing 0 needs to be stored, the actual maximum supported string length is 15 characters. If a longer key name is needed in the project, this configuration can be increased.

Note

After modifying this key length configuration, historical stored data will be lost.

Application Examples

For details, refer to the project under /examples/storage/nvs/.