forked from espressif/esp-idf
feat(examples): Add storage/nvsgen example
Showcases the use of `nvs_create_partition_image` CMake function Remove mentions of NVS multipage blob version 1 so it's not encouraged
This commit is contained in:
@@ -94,7 +94,7 @@ This utility helps generate NVS partition binary files which can be flashed sepa
|
|||||||
|
|
||||||
Instead of calling the ``nvs_partition_gen.py`` tool manually, the creation of the partition binary files can also be done directly from CMake using the function ``nvs_create_partition_image``::
|
Instead of calling the ``nvs_partition_gen.py`` tool manually, the creation of the partition binary files can also be done directly from CMake using the function ``nvs_create_partition_image``::
|
||||||
|
|
||||||
nvs_create_partition_image(<partition> <csv> [FLASH_IN_PROJECT] [VERSION 1 | 2] [DEPENDS dep dep dep ...])
|
nvs_create_partition_image(<partition> <csv> [FLASH_IN_PROJECT] [DEPENDS dep dep dep ...])
|
||||||
|
|
||||||
**Positional Arguments**:
|
**Positional Arguments**:
|
||||||
|
|
||||||
@@ -118,12 +118,6 @@ Instead of calling the ``nvs_partition_gen.py`` tool manually, the creation of t
|
|||||||
- Description
|
- Description
|
||||||
* - ``FLASH_IN_PROJECT``
|
* - ``FLASH_IN_PROJECT``
|
||||||
- Name of the NVS parition
|
- Name of the NVS parition
|
||||||
* - ``VERSION {1,2}``
|
|
||||||
- Set multipage blob version (Default: Version 2)
|
|
||||||
|
|
||||||
Version 1 = support disabled
|
|
||||||
|
|
||||||
Version 2 = support enabled
|
|
||||||
* - ``DEPENDS``
|
* - ``DEPENDS``
|
||||||
- Specify files on which the command depends
|
- Specify files on which the command depends
|
||||||
|
|
||||||
|
@@ -61,6 +61,16 @@ examples/storage/nvs_rw_value_cxx:
|
|||||||
temporary: true
|
temporary: true
|
||||||
reason: lack of runners
|
reason: lack of runners
|
||||||
|
|
||||||
|
examples/storage/nvsgen:
|
||||||
|
disable:
|
||||||
|
- if: IDF_TARGET == "esp32c2"
|
||||||
|
temporary: true
|
||||||
|
reason: target esp32c2 is not supported yet
|
||||||
|
disable_test:
|
||||||
|
- if: IDF_TARGET in ["esp32s2", "esp32s3", "esp32c3", "esp32c6", "esp32h2"]
|
||||||
|
temporary: true
|
||||||
|
reason: lack of runners, should be same for every target
|
||||||
|
|
||||||
examples/storage/partition_api/partition_find:
|
examples/storage/partition_api/partition_find:
|
||||||
disable:
|
disable:
|
||||||
- if: IDF_TARGET == "esp32c2"
|
- if: IDF_TARGET == "esp32c2"
|
||||||
|
6
examples/storage/nvsgen/CMakeLists.txt
Normal file
6
examples/storage/nvsgen/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(nvsgen)
|
54
examples/storage/nvsgen/README.md
Normal file
54
examples/storage/nvsgen/README.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||||
|
|
||||||
|
# NVS Partition Image Generation on Build Example
|
||||||
|
|
||||||
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
|
This example demonstrates how to use the NVS image generation tool [nvs_partition_gen.py](../../../components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py) to automatically create a NVS partition image from the contents of a CSV file during build, with an option of automatically flashing the created image on invocation of `idf.py -p PORT flash`. For more information, see description of `nvs_partition_gen.py` on the ESP-IDF Programming Guide under API Reference > Storage API > NVS Partition Generator Utility.
|
||||||
|
|
||||||
|
The following gives an overview of the example:
|
||||||
|
|
||||||
|
1. There is a file `nvs_data.csv` from which the NVS partition image will be created.
|
||||||
|
|
||||||
|
2. The function `nvs_create_partition_image` is used to specify that a NVS image should be created during build for the `nvs` partition. It is called from [the main component's CMakeLists.txt](./main/CMakeLists.txt). `FLASH_IN_PROJECT` specifies that the created image should be flashed on invocation of `idf.py -p PORT flash` together with app, bootloader, partition table, etc. For both build systems, the image is created on the example's build directory with the output filename `nvs.bin`.
|
||||||
|
|
||||||
|
3. Upon invocation of `idf.py -p PORT flash monitor`, application loads and finds there is already a valid and pre-filled NVS partition in the `nvs` partition with values same as those in `nvs_data.csv` file. The application is then able to read those values.
|
||||||
|
|
||||||
|
## How to use example
|
||||||
|
|
||||||
|
### Build and flash
|
||||||
|
|
||||||
|
To run the example, type the following command:
|
||||||
|
|
||||||
|
```CMake
|
||||||
|
idf.py -p PORT flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||||
|
|
||||||
|
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||||
|
|
||||||
|
## Example output
|
||||||
|
|
||||||
|
Here is the example's console output:
|
||||||
|
|
||||||
|
```
|
||||||
|
...
|
||||||
|
I (357) example: Opening Non-Volatile Storage (NVS) handle
|
||||||
|
I (357) example: Done
|
||||||
|
I (357) example: Reading values from NVS
|
||||||
|
255
|
||||||
|
-128
|
||||||
|
65535
|
||||||
|
4294967295
|
||||||
|
-2147483648
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
Fusce quis risus justo.
|
||||||
|
Suspendisse egestas in nisi sit amet auctor.
|
||||||
|
Pellentesque rhoncus dictum sodales.
|
||||||
|
In justo erat, viverra at interdum eget, interdum vel dui.
|
||||||
|
I (387) example: Reading values from NVS done - all OK
|
||||||
|
```
|
||||||
|
|
||||||
|
The logic of the example is contained in a [single source file](./main/nvsgen_example_main.c), and it should be relatively simple to match points in its execution with the log outputs above.
|
8
examples/storage/nvsgen/main/CMakeLists.txt
Normal file
8
examples/storage/nvsgen/main/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
idf_component_register(SRCS "nvsgen_example_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
||||||
|
|
||||||
|
# Create a NVS image from the contents of the `nvs_data` CSV file
|
||||||
|
# that fits the partition named 'nvs'. FLASH_IN_PROJECT indicates that
|
||||||
|
# the generated image should be flashed when the entire project is flashed to
|
||||||
|
# the target with 'idf.py -p PORT flash'.
|
||||||
|
nvs_create_partition_image(nvs ../nvs_data.csv FLASH_IN_PROJECT)
|
89
examples/storage/nvsgen/main/nvsgen_example_main.c
Normal file
89
examples/storage/nvsgen/main/nvsgen_example_main.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/* Non-Volatile Storage (NVS) Image Generation on Build Example
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
|
||||||
|
static const char *TAG = "example";
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
// Initialize NVS
|
||||||
|
esp_err_t err = nvs_flash_init();
|
||||||
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
// NVS partition was truncated and needs to be erased
|
||||||
|
// Retry nvs_flash_init
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
err = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
|
// Open the pre-filled NVS partition called "nvs"
|
||||||
|
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle");
|
||||||
|
nvs_handle_t my_handle;
|
||||||
|
err = nvs_open_from_partition("nvs", "storage", NVS_READONLY, &my_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "The NVS handle successfully opened");
|
||||||
|
|
||||||
|
// Read values
|
||||||
|
ESP_LOGI(TAG, "Reading values from NVS");
|
||||||
|
|
||||||
|
uint8_t u8_val = 0;
|
||||||
|
err = nvs_get_u8(my_handle, "u8_key", &u8_val);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%"PRIu8"\n", u8_val);
|
||||||
|
assert(u8_val == 255);
|
||||||
|
|
||||||
|
int8_t i8_val = 0;
|
||||||
|
err = nvs_get_i8(my_handle, "i8_key", &i8_val);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%"PRIi8"\n", i8_val);
|
||||||
|
assert(i8_val == -128);
|
||||||
|
|
||||||
|
uint16_t u16_val = 0;
|
||||||
|
err = nvs_get_u16(my_handle, "u16_key", &u16_val);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%"PRIu16"\n", u16_val);
|
||||||
|
assert(u16_val == 65535);
|
||||||
|
|
||||||
|
uint32_t u32_val = 0;
|
||||||
|
err = nvs_get_u32(my_handle, "u32_key", &u32_val);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%"PRIu32"\n", u32_val);
|
||||||
|
assert(u32_val == 4294967295);
|
||||||
|
|
||||||
|
int32_t i32_val = 0;
|
||||||
|
err = nvs_get_i32(my_handle, "i32_key", &i32_val);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%"PRIi32"\n", i32_val);
|
||||||
|
assert(i32_val == -2147483648);
|
||||||
|
|
||||||
|
size_t str_len = 0;
|
||||||
|
err = nvs_get_str(my_handle, "str_key", NULL, &str_len);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
assert(str_len == 222);
|
||||||
|
|
||||||
|
char* str_val = (char*) malloc(str_len);
|
||||||
|
err = nvs_get_str(my_handle, "str_key", str_val, &str_len);
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
printf("%s\n", str_val);
|
||||||
|
assert(str_val[0] == 'L');
|
||||||
|
free(str_val);
|
||||||
|
|
||||||
|
// Close
|
||||||
|
nvs_close(my_handle);
|
||||||
|
ESP_LOGI(TAG, "Reading values from NVS done - all OK");
|
||||||
|
}
|
13
examples/storage/nvsgen/nvs_data.csv
Normal file
13
examples/storage/nvsgen/nvs_data.csv
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Sample csv file
|
||||||
|
key,type,encoding,value
|
||||||
|
storage,namespace,,
|
||||||
|
u8_key,data,u8,255
|
||||||
|
i8_key,data,i8,-128
|
||||||
|
u16_key,data,u16,65535
|
||||||
|
u32_key,data,u32,4294967295
|
||||||
|
i32_key,data,i32,-2147483648
|
||||||
|
str_key,data,string,"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
Fusce quis risus justo.
|
||||||
|
Suspendisse egestas in nisi sit amet auctor.
|
||||||
|
Pellentesque rhoncus dictum sodales.
|
||||||
|
In justo erat, viverra at interdum eget, interdum vel dui."
|
Can't render this file because it has a wrong number of fields in line 2.
|
6
examples/storage/nvsgen/partitions_example.csv
Normal file
6
examples/storage/nvsgen/partitions_example.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
|
factory, app, factory, 0x10000, 1M,
|
|
11
examples/storage/nvsgen/pytest_nvsgen_example.py
Normal file
11
examples/storage/nvsgen/pytest_nvsgen_example.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32
|
||||||
|
def test_nvsgen_example(dut: Dut) -> None:
|
||||||
|
dut.expect('Reading values from NVS', timeout=10)
|
||||||
|
dut.expect('Reading values from NVS done - all OK', timeout=10)
|
3
examples/storage/nvsgen/sdkconfig.defaults
Normal file
3
examples/storage/nvsgen/sdkconfig.defaults
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||||
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
Reference in New Issue
Block a user