diff --git a/examples/storage/nvs/nvs_rw_blob/README.md b/examples/storage/nvs/nvs_rw_blob/README.md index 0cadb0e703..22c9f94b3b 100644 --- a/examples/storage/nvs/nvs_rw_blob/README.md +++ b/examples/storage/nvs/nvs_rw_blob/README.md @@ -14,7 +14,7 @@ Example also shows how to implement diagnostics if read / write operation was su Detailed functional description of NVS and API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_flash.html). -If not done already, consider checking simpler example *storage/nvs_rw_value*, that has been used as a starting point for preparing this one. +If not done already, consider checking simpler example *storage/nvs/nvs_rw_value*, that has been used as a starting point for preparing this one. ## How to use example @@ -36,34 +36,27 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -First run: ``` -Restart counter = 0 -Run time: -Nothing saved yet! +... +I (288) main_task: Calling app_main() +I (298) nvs_blob_example: Saving test data blob... +I (308) nvs_blob_example: +Reading updated blob data: +I (308) nvs_blob_example: Reading test data blob: +I (308) nvs_blob_example: ID: 123 +I (308) nvs_blob_example: Name: Test Sample +I (308) nvs_blob_example: Values: 3.140, 2.718, -0.000, 0.000 +I (318) nvs_blob_example: Flags: 0xABCD1234 +I (318) nvs_blob_example: Counts: -100, 100 +I (328) nvs_blob_example: Active: true +I (328) nvs_blob_example: +Reading array data blob: +I (338) nvs_blob_example: Array[0] = 30 +I (338) nvs_blob_example: Array[1] = 20 +I (338) nvs_blob_example: +Blob operations completed. Monitoring GPIO for reset... +I (348) gpio: GPIO[0]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +... ``` -At this point, press "Boot" button and hold it for a second. The board will perform software restart, printing: - -``` -Restarting... -``` - -After booting again, restart counter and run time array will be printed: - -``` -Restart counter = 1 -Run time: -1: 5110 -``` - -After pressing "Boot" once more: - -``` -Restart counter = 2 -Run time: -1: 5110 -2: 5860 -``` - -To reset the counter and run time array, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above. +To reset nvs data, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above. diff --git a/examples/storage/nvs/nvs_rw_blob/main/nvs_blob_example_main.c b/examples/storage/nvs/nvs_rw_blob/main/nvs_blob_example_main.c index ce0ea2bfff..37827fcfcd 100644 --- a/examples/storage/nvs/nvs_rw_blob/main/nvs_blob_example_main.c +++ b/examples/storage/nvs/nvs_rw_blob/main/nvs_blob_example_main.c @@ -19,11 +19,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" +#include "esp_log.h" #include "nvs_flash.h" #include "nvs.h" #include "driver/gpio.h" #define STORAGE_NAMESPACE "storage" +#define BLOB_EXAMPLE_DATA_SIZE 256 + +static const char *TAG = "nvs_blob_example"; #if CONFIG_IDF_TARGET_ESP32C3 #define BOOT_MODE_PIN GPIO_NUM_9 @@ -31,96 +35,60 @@ #define BOOT_MODE_PIN GPIO_NUM_0 #endif //CONFIG_IDF_TARGET_ESP32C3 -/* Save the number of module restarts in NVS - by first reading and then incrementing - the number that has been saved previously. - Return an error if anything goes wrong - during this process. - */ -esp_err_t save_restart_counter(void) +/* Test data structure to demonstrate different data types in blob */ +typedef struct { + uint8_t id; + char name[32]; + float values[2]; + uint32_t flags; + int16_t counts[2]; + bool active; +} test_data_t; + +/* Save test data as a blob in NVS */ +esp_err_t save_test_data(void) { nvs_handle_t my_handle; esp_err_t err; - // Open + // Create sample test data + test_data_t test_data = { + .id = 123, + .name = "Test Sample", + .values = {3.14f, 2.718f}, + .flags = 0xABCD1234, + .counts = {-100, 100}, + .active = true + }; + + // Open NVS handle err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); - if (err != ESP_OK) return err; - - // Read - int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS - err = nvs_get_i32(my_handle, "restart_conter", &restart_counter); - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; - - // Write - restart_counter++; - err = nvs_set_i32(my_handle, "restart_conter", restart_counter); - if (err != ESP_OK) return err; - - // Commit written value. - // After setting any values, nvs_commit() must be called to ensure changes are written - // to flash storage. Implementations may write to storage at other times, - // but this is not guaranteed. - err = nvs_commit(my_handle); - if (err != ESP_OK) return err; - - // Close - nvs_close(my_handle); - return ESP_OK; -} - -/* Save new run time value in NVS - by first reading a table of previously saved values - and then adding the new value at the end of the table. - Return an error if anything goes wrong - during this process. - */ -esp_err_t save_run_time(void) -{ - nvs_handle_t my_handle; - esp_err_t err; - - // Open - err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); - if (err != ESP_OK) return err; - - // Read the size of memory space required for blob - size_t required_size = 0; // value will default to 0, if not set yet in NVS - err = nvs_get_blob(my_handle, "run_time", NULL, &required_size); - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; - - // Read previously saved blob if available - uint32_t* run_time = malloc(required_size + sizeof(uint32_t)); - if (required_size > 0) { - err = nvs_get_blob(my_handle, "run_time", run_time, &required_size); - if (err != ESP_OK) { - free(run_time); - return err; - } + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) opening NVS handle!", esp_err_to_name(err)); + return err; } - // Write value including previously saved blob if available - required_size += sizeof(uint32_t); - run_time[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS; - err = nvs_set_blob(my_handle, "run_time", run_time, required_size); - free(run_time); - - if (err != ESP_OK) return err; + // Write blob + ESP_LOGI(TAG, "Saving test data blob..."); + err = nvs_set_blob(my_handle, "test_data", &test_data, sizeof(test_data_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write test data blob!"); + nvs_close(my_handle); + return err; + } // Commit err = nvs_commit(my_handle); - if (err != ESP_OK) return err; + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit data"); + } - // Close nvs_close(my_handle); - return ESP_OK; + return err; } -/* Read from NVS and print restart counter - and the table with run times. - Return an error if anything goes wrong - during this process. - */ -esp_err_t print_what_saved(void) +/* Example of storing and appending array data as a blob */ +esp_err_t save_array_data(void) { nvs_handle_t my_handle; esp_err_t err; @@ -129,70 +97,137 @@ esp_err_t print_what_saved(void) err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle); if (err != ESP_OK) return err; - // Read restart counter - int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS - err = nvs_get_i32(my_handle, "restart_conter", &restart_counter); - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; - printf("Restart counter = %" PRIu32 "\n", restart_counter); - - // Read run time blob - size_t required_size = 0; // value will default to 0, if not set yet in NVS - // obtain required memory space to store blob being read from NVS - err = nvs_get_blob(my_handle, "run_time", NULL, &required_size); - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err; - printf("Run time:\n"); - if (required_size == 0) { - printf("Nothing saved yet!\n"); - } else { - uint32_t* run_time = malloc(required_size); - err = nvs_get_blob(my_handle, "run_time", run_time, &required_size); - if (err != ESP_OK) { - free(run_time); - return err; - } - for (int i = 0; i < required_size / sizeof(uint32_t); i++) { - printf("%d: %" PRIu32 "\n", i + 1, run_time[i]); - } - free(run_time); + // First, get the size of existing data (if any) + size_t required_size = 0; + err = nvs_get_blob(my_handle, "array_data", NULL, &required_size); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGE(TAG, "Error (%s) reading array size!", esp_err_to_name(err)); + nvs_close(my_handle); + return err; + } + + // Allocate memory and read existing data + uint32_t* array_data = malloc(required_size + sizeof(uint32_t)); + if (required_size > 0) { + err = nvs_get_blob(my_handle, "array_data", array_data, &required_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) reading array data!", esp_err_to_name(err)); + free(array_data); + nvs_close(my_handle); + return err; + } + } + + // Append new value + required_size += sizeof(uint32_t); + array_data[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS; + + // Save updated array + err = nvs_set_blob(my_handle, "array_data", array_data, required_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) saving array data!", esp_err_to_name(err)); + } + + free(array_data); + + // Commit + err = nvs_commit(my_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) committing data!", esp_err_to_name(err)); + } + + nvs_close(my_handle); + return err; +} + +/* Read and display all saved blobs */ +esp_err_t read_stored_blobs(void) +{ + nvs_handle_t my_handle; + esp_err_t err; + + err = nvs_open(STORAGE_NAMESPACE, NVS_READONLY, &my_handle); + if (err != ESP_OK) return err; + + // 1. Read test data blob + ESP_LOGI(TAG, "Reading test data blob:"); + test_data_t test_data; + size_t test_data_size = sizeof(test_data_t); + err = nvs_get_blob(my_handle, "test_data", &test_data, &test_data_size); + if (err == ESP_OK) { + ESP_LOGI(TAG, "ID: %d", test_data.id); + ESP_LOGI(TAG, "Name: %s", test_data.name); + ESP_LOGI(TAG, "Values: %.3f, %.3f, %.3f, %.3f", + test_data.values[0], test_data.values[1], + test_data.values[2], test_data.values[3]); + ESP_LOGI(TAG, "Flags: 0x%08" PRIX32, test_data.flags); + ESP_LOGI(TAG, "Counts: %d, %d", test_data.counts[0], test_data.counts[1]); + ESP_LOGI(TAG, "Active: %s", test_data.active ? "true" : "false"); + } else if (err == ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGW(TAG, "Test data not found!"); + } + + // 2. Read array data blob + ESP_LOGI(TAG, "\nReading array data blob:"); + size_t required_size = 0; + err = nvs_get_blob(my_handle, "array_data", NULL, &required_size); + if (err == ESP_OK) { + uint32_t* array_data = malloc(required_size); + err = nvs_get_blob(my_handle, "array_data", array_data, &required_size); + if (err == ESP_OK) { + for (int i = 0; i < required_size / sizeof(uint32_t); i++) { + ESP_LOGI(TAG, "Array[%d] = %" PRIu32, i, array_data[i]); + } + } + free(array_data); + } else if (err == ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGW(TAG, "Array data not found!"); } - // Close nvs_close(my_handle); return ESP_OK; } - 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 ); + ESP_ERROR_CHECK(err); - err = print_what_saved(); - if (err != ESP_OK) printf("Error (%s) reading data from NVS!\n", esp_err_to_name(err)); + // Save new test data + err = save_test_data(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) saving test data!", esp_err_to_name(err)); + } - err = save_restart_counter(); - if (err != ESP_OK) printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err)); + // Save new array data + err = save_array_data(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) saving array data!", esp_err_to_name(err)); + } + // Read updated data + ESP_LOGI(TAG, "\nReading updated blob data:"); + err = read_stored_blobs(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (%s) reading updated data!", esp_err_to_name(err)); + } + + ESP_LOGI(TAG, "\nBlob operations completed. Monitoring GPIO for reset..."); + + // Setup GPIO for reset monitoring gpio_reset_pin(BOOT_MODE_PIN); gpio_set_direction(BOOT_MODE_PIN, GPIO_MODE_INPUT); - /* Read the status of GPIO0. If GPIO0 is LOW for longer than 1000 ms, - then save module's run time and restart it - */ while (1) { if (gpio_get_level(BOOT_MODE_PIN) == 0) { vTaskDelay(1000 / portTICK_PERIOD_MS); if(gpio_get_level(BOOT_MODE_PIN) == 0) { - err = save_run_time(); - if (err != ESP_OK) printf("Error (%s) saving run time blob to NVS!\n", esp_err_to_name(err)); - printf("Restarting...\n"); - fflush(stdout); + ESP_LOGI(TAG, "Reset button pressed, restarting..."); esp_restart(); } } diff --git a/examples/storage/nvs/nvs_rw_blob/pytest_nvs_rw_blob.py b/examples/storage/nvs/nvs_rw_blob/pytest_nvs_rw_blob.py index d1da1bad64..16973ede92 100644 --- a/examples/storage/nvs/nvs_rw_blob/pytest_nvs_rw_blob.py +++ b/examples/storage/nvs/nvs_rw_blob/pytest_nvs_rw_blob.py @@ -1,11 +1,5 @@ # SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 -import logging -import random -import re -import time -from typing import List - import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize @@ -14,28 +8,12 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic @idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_examples_nvs_rw_blob(dut: Dut) -> None: - def expect_start_msg(index: int) -> None: - dut.expect('Restart counter = {}'.format(index), timeout=10) - dut.expect('Run time:', timeout=10) - - expect_start_msg(0) - dut.expect('Nothing saved yet!', timeout=5) - nvs_store: List[str] = [] - for i in range(1, 10): - time.sleep(random.uniform(0.1, 2)) # in order to randomize the runtimes stored in NVS - try: - # Pulling pin low using DTR - dut.serial.proc.setDTR(True) - dut.expect('Restarting...', timeout=5) # the application waits for a second - finally: - dut.serial.proc.setDTR(False) - - expect_start_msg(i) - - for store_item in nvs_store: - dut.expect(store_item.encode(), timeout=10) - - logging.info('Received: {}'.format(', '.join(nvs_store))) - new_runtime = (dut.expect(re.compile(str.encode('{}: (\\d+)'.format(i))), timeout=10)[0]).decode() - nvs_store.append(new_runtime) - logging.info('loop {} has finished with runtime {}'.format(i, new_runtime)) + # Save and read test data + dut.expect('Saving test data blob...', timeout=20) + # Save array data + # Read updated data + dut.expect('Reading updated blob data:', timeout=20) + dut.expect('Reading test data blob:', timeout=20) + # Verify array data reading + dut.expect('Reading array data blob:', timeout=20) + dut.expect('Blob operations completed. Monitoring GPIO for reset...', timeout=20) diff --git a/examples/storage/nvs/nvs_rw_value/README.md b/examples/storage/nvs/nvs_rw_value/README.md index 0b1d390304..013123825f 100644 --- a/examples/storage/nvs/nvs_rw_value/README.md +++ b/examples/storage/nvs/nvs_rw_value/README.md @@ -13,7 +13,7 @@ Example also shows how to check if read / write operation was successful, or cer Detailed functional description of NVS and API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/nvs_flash.html). -Check another example *storage/nvs_rw_blob*, which shows how to read and write variable length binary data (blob). +Check another example *storage/nvs/nvs_rw_blob*, which shows how to read and write variable length binary data (blob). ## How to use example @@ -35,50 +35,32 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -First run: ``` -Opening Non-Volatile Storage (NVS) handle... Done -Reading restart counter from NVS ... The value is not initialized yet! -Updating restart counter in NVS ... Done -Committing updates in NVS ... Done - -Restarting in 10 seconds... -Restarting in 9 seconds... -Restarting in 8 seconds... -Restarting in 7 seconds... -Restarting in 6 seconds... -Restarting in 5 seconds... -Restarting in 4 seconds... -Restarting in 3 seconds... -Restarting in 2 seconds... -Restarting in 1 seconds... -Restarting in 0 seconds... -Restarting now. +... +I (296) nvs_example: +Opening Non-Volatile Storage (NVS) handle... +I (296) nvs_example: +Writing counter to NVS... +I (306) nvs_example: +Reading counter from NVS... +I (306) nvs_example: Read counter = 42 +I (306) nvs_example: +Writing string to NVS... +I (306) nvs_example: +Reading string from NVS... +I (306) nvs_example: Read string: Hello from NVS! +I (316) nvs_example: +Finding keys in NVS... +I (316) nvs_example: Key: 'message', Type: str +I (316) nvs_example: Key: 'counter', Type: i32 +I (326) nvs_example: +Deleting key from NVS... +I (336) nvs_example: +Committing updates in NVS... +I (336) nvs_example: NVS handle closed. +I (336) nvs_example: Returned to app_main +I (346) main_task: Returned from app_main() +... ``` -Subsequent runs: - -``` -Opening Non-Volatile Storage (NVS) handle... Done -Reading restart counter from NVS ... Done -Restart counter = 1 -Updating restart counter in NVS ... Done -Committing updates in NVS ... Done - -Restarting in 10 seconds... -Restarting in 9 seconds... -Restarting in 8 seconds... -Restarting in 7 seconds... -Restarting in 6 seconds... -Restarting in 5 seconds... -Restarting in 4 seconds... -Restarting in 3 seconds... -Restarting in 2 seconds... -Restarting in 1 seconds... -Restarting in 0 seconds... -Restarting now. -``` - -Restart counter will increment on each run. - -To reset the counter, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above. +To reset nvs data, erase the contents of flash memory using `idf.py erase-flash`, then upload the program again as described above. diff --git a/examples/storage/nvs/nvs_rw_value/main/nvs_value_example_main.c b/examples/storage/nvs/nvs_rw_value/main/nvs_value_example_main.c index b68016afea..1e04f4fb45 100644 --- a/examples/storage/nvs/nvs_rw_value/main/nvs_value_example_main.c +++ b/examples/storage/nvs/nvs_rw_value/main/nvs_value_example_main.c @@ -19,9 +19,45 @@ #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 = "nvs_example"; + +typedef struct { + nvs_type_t type; + const char *str; +} type_str_pair_t; + +static const type_str_pair_t type_str_pair[] = { + { NVS_TYPE_I8, "i8" }, + { NVS_TYPE_U8, "u8" }, + { NVS_TYPE_U16, "u16" }, + { NVS_TYPE_I16, "i16" }, + { NVS_TYPE_U32, "u32" }, + { NVS_TYPE_I32, "i32" }, + { NVS_TYPE_U64, "u64" }, + { NVS_TYPE_I64, "i64" }, + { NVS_TYPE_STR, "str" }, + { NVS_TYPE_BLOB, "blob" }, + { NVS_TYPE_ANY, "any" }, +}; + +static const size_t TYPE_STR_PAIR_SIZE = sizeof(type_str_pair) / sizeof(type_str_pair[0]); + +static const char *type_to_str(nvs_type_t type) +{ + for (int i = 0; i < TYPE_STR_PAIR_SIZE; i++) { + const type_str_pair_t *p = &type_str_pair[i]; + if (p->type == type) { + return p->str; + } + } + + return "Unknown"; +} + void app_main(void) { // Initialize NVS @@ -32,60 +68,94 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(err); - // Open - printf("\n"); - printf("Opening Non-Volatile Storage (NVS) handle... "); + // Open NVS handle + ESP_LOGI(TAG, "\nOpening Non-Volatile Storage (NVS) handle..."); nvs_handle_t my_handle; err = nvs_open("storage", NVS_READWRITE, &my_handle); if (err != ESP_OK) { - printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err)); - } else { - printf("Done\n"); + ESP_LOGE(TAG, "Error (%s) opening NVS handle!", esp_err_to_name(err)); + return; + } - // Read - printf("Reading restart counter from NVS ... "); - int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS - err = nvs_get_i32(my_handle, "restart_counter", &restart_counter); - switch (err) { - case ESP_OK: - printf("Done\n"); - printf("Restart counter = %" PRIu32 "\n", restart_counter); - break; - case ESP_ERR_NVS_NOT_FOUND: - printf("The value is not initialized yet!\n"); - break; - default : - printf("Error (%s) reading!\n", esp_err_to_name(err)); + // Store and read an integer value + int32_t counter = 42; + ESP_LOGI(TAG, "\nWriting counter to NVS..."); + err = nvs_set_i32(my_handle, "counter", counter); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write counter!"); + } + + // Read back the value + int32_t read_counter = 0; + ESP_LOGI(TAG, "\nReading counter from NVS..."); + err = nvs_get_i32(my_handle, "counter", &read_counter); + switch (err) { + case ESP_OK: + ESP_LOGI(TAG, "Read counter = %" PRIu32, read_counter); + break; + case ESP_ERR_NVS_NOT_FOUND: + ESP_LOGW(TAG, "The value is not initialized yet!"); + break; + default: + ESP_LOGE(TAG, "Error (%s) reading!", esp_err_to_name(err)); + } + + // Store and read a string + ESP_LOGI(TAG, "\nWriting string to NVS..."); + err = nvs_set_str(my_handle, "message", "Hello from NVS!"); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write string!"); + } + + // Read back the string + size_t required_size = 0; + ESP_LOGI(TAG, "\nReading string from NVS..."); + err = nvs_get_str(my_handle, "message", NULL, &required_size); + if (err == ESP_OK) { + char* message = malloc(required_size); + err = nvs_get_str(my_handle, "message", message, &required_size); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Read string: %s", message); } - - // Write - printf("Updating restart counter in NVS ... "); - restart_counter++; - err = nvs_set_i32(my_handle, "restart_counter", restart_counter); - printf((err != ESP_OK) ? "Failed!\n" : "Done\n"); - - // Commit written value. - // After setting any values, nvs_commit() must be called to ensure changes are written - // to flash storage. Implementations may write to storage at other times, - // but this is not guaranteed. - printf("Committing updates in NVS ... "); - err = nvs_commit(my_handle); - printf((err != ESP_OK) ? "Failed!\n" : "Done\n"); - - // Close - nvs_close(my_handle); + free(message); } - printf("\n"); - - // Restart module - for (int i = 10; i >= 0; i--) { - printf("Restarting in %d seconds...\n", i); - vTaskDelay(1000 / portTICK_PERIOD_MS); + // Find keys in NVS + ESP_LOGI(TAG, "\nFinding keys in NVS..."); + nvs_iterator_t it = NULL; + esp_err_t res = nvs_entry_find("nvs", "storage", NVS_TYPE_ANY, &it); + while(res == ESP_OK) { + nvs_entry_info_t info; + nvs_entry_info(it, &info); + const char *type_str = type_to_str(info.type); + ESP_LOGI(TAG, "Key: '%s', Type: %s", info.key, type_str); + res = nvs_entry_next(&it); } - printf("Restarting now.\n"); - fflush(stdout); - esp_restart(); + nvs_release_iterator(it); + + // Delete a key from NVS + ESP_LOGI(TAG, "\nDeleting key from NVS..."); + err = nvs_erase_key(my_handle, "counter"); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to erase key!"); + } + + // Commit changes + // After setting any values, nvs_commit() must be called to ensure changes are written + // to flash storage. Implementations may write to storage at other times, + // but this is not guaranteed. + ESP_LOGI(TAG, "\nCommitting updates in NVS..."); + err = nvs_commit(my_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit NVS changes!"); + } + + // Close + nvs_close(my_handle); + ESP_LOGI(TAG, "NVS handle closed."); + + ESP_LOGI(TAG, "Returned to app_main"); + } diff --git a/examples/storage/nvs/nvs_rw_value/pytest_nvs_rw_value.py b/examples/storage/nvs/nvs_rw_value/pytest_nvs_rw_value.py index 657f8c60a1..8bf6b6cac9 100644 --- a/examples/storage/nvs/nvs_rw_value/pytest_nvs_rw_value.py +++ b/examples/storage/nvs/nvs_rw_value/pytest_nvs_rw_value.py @@ -1,8 +1,5 @@ # SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 -import logging -from itertools import zip_longest - import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize @@ -13,11 +10,14 @@ from pytest_embedded_idf.utils import idf_parametrize def test_examples_nvs_rw_value(dut: Dut) -> None: dut.serial.erase_flash() dut.serial.flash() - for i, counter_state in zip_longest(range(4), ('The value is not initialized yet!',), fillvalue='Done'): - dut.expect('Opening Non-Volatile Storage \\(NVS\\) handle... Done', timeout=20) - dut.expect('Reading restart counter from NVS ... {}'.format(counter_state), timeout=20) - dut.expect('Restart counter = {}'.format(i) if int(i) > 0 else '', timeout=20) - dut.expect('Updating restart counter in NVS ... Done', timeout=20) - dut.expect('Committing updates in NVS ... Done', timeout=20) - dut.expect('Restarting in 10 seconds...', timeout=20) - logging.info('loop {} has finished'.format(i)) + + dut.expect('Opening Non-Volatile Storage \\(NVS\\) handle...', timeout=20) + dut.expect('Writing counter to NVS...', timeout=20) + dut.expect('Reading counter from NVS...', timeout=20) + dut.expect('Writing string to NVS...', timeout=20) + dut.expect('Reading string from NVS...', timeout=20) + dut.expect('Finding keys in NVS...', timeout=20) + dut.expect('Deleting key from NVS...', timeout=20) + dut.expect('Committing updates in NVS...', timeout=20) + dut.expect('NVS handle closed.', timeout=20) + dut.expect('Returned to app_main', timeout=20)