diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 5fbeeb7c88..e1b22d6a99 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -118,7 +118,7 @@ const esp_phy_init_data_t* esp_phy_get_init_data() } esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length); if (err != ESP_OK) { - ESP_LOGE(TAG, "failed to read PHY data partition (%d)", err); + ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err); return NULL; } if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 || @@ -167,10 +167,15 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data) { - nvs_handle handle; - esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); + esp_err_t err = nvs_flash_init(); if (err != ESP_OK) { - ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err); + ESP_LOGW(TAG, "%s: failed to initialize NVS (0x%x)", __func__, err); + return err; + } + nvs_handle handle; + err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err); return err; } else { @@ -185,7 +190,7 @@ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_da nvs_handle handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle); if (err != ESP_OK) { - ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err); + ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err); return err; } else { @@ -202,7 +207,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, uint32_t cal_data_version; err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version); if (err != ESP_OK) { - ESP_LOGD(TAG, "%s: failed to get cal_version (%d)", __func__, err); + ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err); return err; } uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); @@ -216,7 +221,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, size_t length = sizeof(cal_data_mac); err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length); if (err != ESP_OK) { - ESP_LOGD(TAG, "%s: failed to get cal_mac (%d)", __func__, err); + ESP_LOGD(TAG, "%s: failed to get cal_mac (0x%x)", __func__, err); return err; } if (length != sizeof(cal_data_mac)) { @@ -234,7 +239,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, length = sizeof(*out_cal_data); err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length); if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: failed to get cal_data(%d)", __func__, err); + ESP_LOGE(TAG, "%s: failed to get cal_data(0x%x)", __func__, err); return err; } if (length != sizeof(*out_cal_data)) { @@ -267,7 +272,6 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, void esp_phy_load_cal_and_init(void) { #ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE - nvs_flash_init(); esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL; if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) { calibration_mode = PHY_RF_CAL_NONE; @@ -285,7 +289,7 @@ void esp_phy_load_cal_and_init(void) } esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data); if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration"); + ESP_LOGW(TAG, "failed to load RF calibration data (0x%x), falling back to full calibration", err); calibration_mode = PHY_RF_CAL_FULL; } diff --git a/components/nvs_flash/README.rst b/components/nvs_flash/README.rst index ade5518aa5..f9602fc8bf 100644 --- a/components/nvs_flash/README.rst +++ b/components/nvs_flash/README.rst @@ -9,10 +9,12 @@ Non-volatile storage (NVS) library is designed to store key-value pairs in flash Underlying storage ^^^^^^^^^^^^^^^^^^ -Currently NVS uses a portion of main flash memory through ``spi_flash_{read|write|erase}`` APIs. The range of flash sectors to be used by the library is provided to ``nvs_flash_init`` function. +Currently NVS uses a portion of main flash memory through ``spi_flash_{read|write|erase}`` APIs. The library uses the first partition with ``data`` type and ``nvs`` subtype. Future versions of this library may add other storage backends to keep data in another flash chip (SPI or I2C), RTC, FRAM, etc. +.. note:: if an NVS partition is truncated (for example, when the partition table layout is changed), its contents should be erased. ESP-IDF build system provides a ``make erase_flash`` target to erase all contents of the flash chip. + Keys and values ^^^^^^^^^^^^^^^ diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h index 5f7a93a7b0..6e5af231ab 100644 --- a/components/nvs_flash/include/nvs.h +++ b/components/nvs_flash/include/nvs.h @@ -31,16 +31,17 @@ typedef uint32_t nvs_handle; #define ESP_ERR_NVS_BASE 0x1100 /*!< Starting number of error codes */ #define ESP_ERR_NVS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x01) /*!< The storage driver is not initialized */ #define ESP_ERR_NVS_NOT_FOUND (ESP_ERR_NVS_BASE + 0x02) /*!< Id namespace doesn’t exist yet and mode is NVS_READONLY */ -#define ESP_ERR_NVS_TYPE_MISMATCH (ESP_ERR_NVS_BASE + 0x03) /*!< TBA */ +#define ESP_ERR_NVS_TYPE_MISMATCH (ESP_ERR_NVS_BASE + 0x03) /*!< The type of set or get operation doesn't match the type of value stored in NVS */ #define ESP_ERR_NVS_READ_ONLY (ESP_ERR_NVS_BASE + 0x04) /*!< Storage handle was opened as read only */ #define ESP_ERR_NVS_NOT_ENOUGH_SPACE (ESP_ERR_NVS_BASE + 0x05) /*!< There is not enough space in the underlying storage to save the value */ #define ESP_ERR_NVS_INVALID_NAME (ESP_ERR_NVS_BASE + 0x06) /*!< Namespace name doesn’t satisfy constraints */ #define ESP_ERR_NVS_INVALID_HANDLE (ESP_ERR_NVS_BASE + 0x07) /*!< Handle has been closed or is NULL */ #define ESP_ERR_NVS_REMOVE_FAILED (ESP_ERR_NVS_BASE + 0x08) /*!< The value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again. */ -#define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) /*!< TBA */ -#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< TBA */ -#define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) /*!< TBA */ -#define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) /*!< TBA */ +#define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) /*!< Key name is too long */ +#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs_ API functions */ +#define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) /*!< NVS is in an inconsistent state due to a previous error. Call nvs_flash_init and nvs_open again, then retry. */ +#define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) /*!< String or blob length is not sufficient to store data */ +#define ESP_ERR_NVS_NO_FREE_PAGES (ESP_ERR_NVS_BASE + 0x0d) /*!< NVS partition doesn't contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again. */ /** * @brief Mode of opening the non-volatile storage diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index 0162a8f8ac..8307fe3521 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -21,7 +21,11 @@ extern "C" { /** * @brief Initialize NVS flash storage with layout given in the partition table. * - * @return ESP_OK if storage was successfully initialized. + * @return + * - ESP_OK if storage was successfully initialized. + * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages + * (which may happen if NVS partition was truncated) + * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_init(void); diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 80ccb1f6d0..a24c7214bb 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -811,10 +811,37 @@ void Page::invalidateCache() { mFindInfo = CachedFindInfo(); } + +const char* Page::pageStateToName(PageState ps) +{ + switch (ps) { + case PageState::CORRUPT: + return "CORRUPT"; + + case PageState::ACTIVE: + return "ACTIVE"; + + case PageState::FREEING: + return "FREEING"; + + case PageState::FULL: + return "FULL"; + + case PageState::INVALID: + return "INVALID"; + + case PageState::UNINITIALIZED: + return "UNINITIALIZED"; + + default: + assert(0 && "invalid state value"); + return ""; + } +} void Page::debugDump() const { - printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", (int) mState, mBaseAddress, mSeqNumber, static_cast(mFirstUsedEntry), static_cast(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); + printf("state=%x (%s) addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", (uint32_t) mState, pageStateToName(mState), mBaseAddress, mSeqNumber, static_cast(mFirstUsedEntry), static_cast(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount); size_t skip = 0; for (size_t i = 0; i < ENTRY_COUNT; ++i) { printf("%3d: ", static_cast(i)); diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index c1f430cae5..66b6e847c8 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -220,6 +220,8 @@ protected: assert(entry < ENTRY_COUNT); return mBaseAddress + ENTRY_DATA_OFFSET + static_cast(entry) * ENTRY_SIZE; } + + static const char* pageStateToName(PageState ps); protected: diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index 768b30667a..943f54f2f8 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -105,6 +105,11 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) } } + // partition should have at least one free page + if (mFreePageList.size() == 0) { + return ESP_ERR_NVS_NO_FREE_PAGES; + } + return ESP_OK; } diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index db97879bc2..07d01db468 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -6,14 +6,26 @@ #include "unity.h" #include "nvs.h" #include "nvs_flash.h" -#include "esp_spi_flash.h" +#include "esp_partition.h" +#include "esp_log.h" #include +static const char* TAG = "test_nvs"; TEST_CASE("various nvs tests", "[nvs]") { nvs_handle handle_1; - TEST_ESP_OK(nvs_flash_init()); + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); + TEST_ESP_ERR(nvs_open("test_namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_INVALID_HANDLE); diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index 282d4de48e..ff35a84d11 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -1108,6 +1108,23 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]") } } +TEST_CASE("nvs_flash_init checks for an empty page", "[nvs]") +{ + const size_t blob_size = 2048; // big enough so that only one can fit into a page + uint8_t blob[blob_size] = {0}; + SpiFlashEmulator emu(5); + TEST_ESP_OK( nvs_flash_init_custom(0, 5) ); + nvs_handle handle; + TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + TEST_ESP_OK( nvs_set_blob(handle, "1", blob, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "2", blob, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "3", blob, blob_size) ); + TEST_ESP_OK( nvs_commit(handle) ); + nvs_close(handle); + // first two pages are now full, third one is writable, last two are empty + // init should fail + TEST_ESP_ERR( nvs_flash_init_custom(0, 3), ESP_ERR_NVS_NO_FREE_PAGES ); +} TEST_CASE("dump all performance data", "[nvs]") { diff --git a/docs/api/storage/nvs_flash.rst b/docs/api/storage/nvs_flash.rst index ce1af94546..b6cf6f2210 100644 --- a/docs/api/storage/nvs_flash.rst +++ b/docs/api/storage/nvs_flash.rst @@ -48,6 +48,7 @@ Macros .. doxygendefine:: ESP_ERR_NVS_PAGE_FULL .. doxygendefine:: ESP_ERR_NVS_INVALID_STATE .. doxygendefine:: ESP_ERR_NVS_INVALID_LENGTH +.. doxygendefine:: ESP_ERR_NVS_NO_FREE_PAGES Type Definitions ^^^^^^^^^^^^^^^^ @@ -61,6 +62,7 @@ Enumerations Functions ^^^^^^^^^ +.. doxygenfunction:: nvs_flash_init .. doxygenfunction:: nvs_open .. doxygenfunction:: nvs_set_i8 .. doxygenfunction:: nvs_set_u8 @@ -86,5 +88,5 @@ Functions .. doxygenfunction:: nvs_erase_all .. doxygenfunction:: nvs_commit .. doxygenfunction:: nvs_close -.. doxygenfunction:: nvs_flash_init + diff --git a/examples/bluetooth/blufi/main/blufi_main.c b/examples/bluetooth/blufi/main/blufi_main.c index b46ffb4648..d35ab71214 100644 --- a/examples/bluetooth/blufi/main/blufi_main.c +++ b/examples/bluetooth/blufi/main/blufi_main.c @@ -312,7 +312,7 @@ void app_main() { esp_err_t ret; - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); esp_bt_controller_init(); diff --git a/examples/get-started/blink/main/blink.c b/examples/get-started/blink/main/blink.c index f97572ac21..698bad218a 100644 --- a/examples/get-started/blink/main/blink.c +++ b/examples/get-started/blink/main/blink.c @@ -9,8 +9,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "nvs_flash.h" #include "driver/gpio.h" #include "sdkconfig.h" @@ -42,6 +40,5 @@ void blink_task(void *pvParameter) void app_main() { - nvs_flash_init(); xTaskCreate(&blink_task, "blink_task", 512, NULL, 5, NULL); } diff --git a/examples/get-started/hello_world/main/hello_world_main.c b/examples/get-started/hello_world/main/hello_world_main.c index c8b9f5f0c9..e1955d8755 100644 --- a/examples/get-started/hello_world/main/hello_world_main.c +++ b/examples/get-started/hello_world/main/hello_world_main.c @@ -10,7 +10,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" -#include "nvs_flash.h" void hello_task(void *pvParameter) { @@ -26,6 +25,5 @@ void hello_task(void *pvParameter) void app_main() { - nvs_flash_init(); xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL); } diff --git a/examples/peripherals/i2s/main/app_main.c b/examples/peripherals/i2s/main/app_main.c index 9c8f80fd56..8072cff6ac 100644 --- a/examples/peripherals/i2s/main/app_main.c +++ b/examples/peripherals/i2s/main/app_main.c @@ -11,8 +11,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "nvs_flash.h" #include "driver/i2s.h" #include @@ -48,7 +46,6 @@ void app_main() .data_in_num = -1 //Not used }; - nvs_flash_init(); i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM, &pin_config); diff --git a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c index fd4fe5b276..90f94f65f7 100644 --- a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c +++ b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c @@ -9,8 +9,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "nvs_flash.h" #include "esp_log.h" #include "driver/touch_pad.h" @@ -95,9 +93,6 @@ static void touch_pad_rtc_intr(void * arg) void app_main() { - ESP_LOGI(TAG, "Starting"); - nvs_flash_init(); - // Initialize touch pad peripheral ESP_LOGI(TAG, "Initializing touch pad"); touch_pad_init(); diff --git a/examples/peripherals/touch_pad_read/main/tp_read_main.c b/examples/peripherals/touch_pad_read/main/tp_read_main.c index accfe5027a..69bb87d17e 100644 --- a/examples/peripherals/touch_pad_read/main/tp_read_main.c +++ b/examples/peripherals/touch_pad_read/main/tp_read_main.c @@ -9,8 +9,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "nvs_flash.h" #include "driver/touch_pad.h" @@ -34,8 +32,6 @@ void touch_pad_read_task(void *pvParameter) void app_main() { - nvs_flash_init(); - // Initialize touch pad peripheral touch_pad_init(); diff --git a/examples/protocols/coap_client/main/coap_client.c b/examples/protocols/coap_client/main/coap_client.c index 7c0df1afec..a45f748d4a 100644 --- a/examples/protocols/coap_client/main/coap_client.c +++ b/examples/protocols/coap_client/main/coap_client.c @@ -199,7 +199,7 @@ static void wifi_conn_init(void) void app_main(void) { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); wifi_conn_init(); xTaskCreate(coap_demo_thread, "coap", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/coap_server/main/coap_server.c b/examples/protocols/coap_server/main/coap_server.c index 75e3296f79..f232853889 100644 --- a/examples/protocols/coap_server/main/coap_server.c +++ b/examples/protocols/coap_server/main/coap_server.c @@ -185,7 +185,7 @@ static void wifi_conn_init(void) void app_main(void) { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); wifi_conn_init(); xTaskCreate(coap_demo_thread, "coap", 2048, NULL, 5, NULL); diff --git a/examples/protocols/http_request/main/http_request_main.c b/examples/protocols/http_request/main/http_request_main.c index 3831ae65b9..130729f06f 100644 --- a/examples/protocols/http_request/main/http_request_main.c +++ b/examples/protocols/http_request/main/http_request_main.c @@ -174,7 +174,7 @@ static void http_get_task(void *pvParameters) void app_main() { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xTaskCreate(&http_get_task, "http_get_task", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/https_request/main/https_request_main.c b/examples/protocols/https_request/main/https_request_main.c index b953252aac..305b562205 100644 --- a/examples/protocols/https_request/main/https_request_main.c +++ b/examples/protocols/https_request/main/https_request_main.c @@ -325,7 +325,7 @@ static void https_get_task(void *pvParameters) void app_main() { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xTaskCreate(&https_get_task, "https_get_task", 8192, NULL, 5, NULL); } diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index d19fd1ae68..50b74e08ca 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -178,7 +178,7 @@ static void mdns_task(void *pvParameters) void app_main() { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xTaskCreate(&mdns_task, "mdns_task", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/openssl_client/main/openssl_client.c b/examples/protocols/openssl_client/main/openssl_client.c index 69e16141be..16c9a0efa6 100644 --- a/examples/protocols/openssl_client/main/openssl_client.c +++ b/examples/protocols/openssl_client/main/openssl_client.c @@ -220,6 +220,6 @@ static void wifi_conn_init(void) void app_main(void) { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); wifi_conn_init(); } diff --git a/examples/protocols/openssl_server/main/openssl_server.c b/examples/protocols/openssl_server/main/openssl_server.c index c74bb0e41f..e1d0619d29 100755 --- a/examples/protocols/openssl_server/main/openssl_server.c +++ b/examples/protocols/openssl_server/main/openssl_server.c @@ -255,6 +255,6 @@ static void wifi_conn_init(void) void app_main(void) { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); wifi_conn_init(); } diff --git a/examples/protocols/sntp/main/sntp_main.c b/examples/protocols/sntp/main/sntp_main.c index 438505d7b6..5a29fcac87 100644 --- a/examples/protocols/sntp/main/sntp_main.c +++ b/examples/protocols/sntp/main/sntp_main.c @@ -93,7 +93,7 @@ void app_main() static void obtain_time(void) { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); diff --git a/examples/storage/nvs_rw_blob/main/nvs_rw_blob.c b/examples/storage/nvs_rw_blob/main/nvs_rw_blob.c index c0a865eb6a..6232984f44 100644 --- a/examples/storage/nvs_rw_blob/main/nvs_rw_blob.c +++ b/examples/storage/nvs_rw_blob/main/nvs_rw_blob.c @@ -13,6 +13,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" +#include "esp_partition.h" #include "nvs_flash.h" #include "nvs.h" #include "driver/gpio.h" @@ -146,9 +147,17 @@ esp_err_t print_what_saved(void) void app_main() { - nvs_flash_init(); - - esp_err_t err; + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // NVS partition was truncated and needs to be erased + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + // Retry nvs_flash_init + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); err = print_what_saved(); if (err != ESP_OK) printf("Error (%d) reading data from NVS!\n", err); diff --git a/examples/storage/nvs_rw_value/main/nvs_rw_value.c b/examples/storage/nvs_rw_value/main/nvs_rw_value.c index 1b3e06b859..db01a6afc4 100644 --- a/examples/storage/nvs_rw_value/main/nvs_rw_value.c +++ b/examples/storage/nvs_rw_value/main/nvs_rw_value.c @@ -13,23 +13,32 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" +#include "esp_partition.h" #include "nvs_flash.h" #include "nvs.h" void app_main() { - nvs_flash_init(); - - nvs_handle my_handle; - esp_err_t err; - - printf("\n"); + // Initialize NVS + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // NVS partition was truncated and needs to be erased + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + // Retry nvs_flash_init + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); // Open - printf("Opening Non-Volatile Storage (NVS) ... "); + printf("\n"); + printf("Opening Non-Volatile Storage (NVS) handle... "); + nvs_handle my_handle; err = nvs_open("storage", NVS_READWRITE, &my_handle); if (err != ESP_OK) { - printf("Error (%d) opening NVS!\n", err); + printf("Error (%d) opening NVS handle!\n", err); } else { printf("Done\n"); diff --git a/examples/system/ota/main/ota_example.c b/examples/system/ota/main/ota_example.c index 06ed81e638..bc910f70c5 100644 --- a/examples/system/ota/main/ota_example.c +++ b/examples/system/ota/main/ota_example.c @@ -21,6 +21,7 @@ #include "esp_ota_ops.h" #include "esp_partition.h" +#include "nvs.h" #include "nvs_flash.h" #define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID @@ -279,7 +280,20 @@ void main_task(void *pvParameter) void app_main() { - nvs_flash_init(); + // Initialize NVS. + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // OTA app partition table has a smaller NVS partition size than the non-OTA + // partition table. This size mismatch may cause NVS initialization to fail. + // If this happens, we erase NVS partition and initialize NVS again. + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); + initialise_wifi(); xTaskCreate(&main_task, "main_task", 8192, NULL, 5, NULL); } diff --git a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c index 7d325c76a0..0932aec931 100644 --- a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c +++ b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c @@ -148,7 +148,7 @@ static void wpa2_enterprise_task(void *pvParameters) void app_main() { - nvs_flash_init(); + ESP_ERROR_CHECK( nvs_flash_init() ); initialise_wifi(); xTaskCreate(&wpa2_enterprise_task, "wpa2_enterprise_task", 4096, NULL, 5, NULL); }