diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index c9e4a72d7..a7ef7f451 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -24,7 +24,7 @@ extern "C" { * @brief Initialize the default NVS partition. * * This API initialises the default NVS partition. The default NVS partition - * is the one that is labelled "nvs" in the partition table. + * is the one that is labeled "nvs" in the partition table. * * @return * - ESP_OK if storage was successfully initialized. @@ -38,7 +38,7 @@ esp_err_t nvs_flash_init(void); /** * @brief Initialize NVS flash storage for the specified partition. * - * @param[in] partition_name Name (label) of the partition. Note that internally a reference to + * @param[in] partition_label Label of the partition. Note that internally a reference to * passed value is kept and it should be accessible for future operations * * @return @@ -48,7 +48,30 @@ esp_err_t nvs_flash_init(void); * - ESP_ERR_NOT_FOUND if specified partition is not found in the partition table * - one of the error codes from the underlying flash storage driver */ -esp_err_t nvs_flash_init_partition(const char *partition_name); +esp_err_t nvs_flash_init_partition(const char *partition_label); + +/** + * @brief Deinitialize NVS storage for the default NVS partition + * + * Default NVS partition is the partition with "nvs" label in the partition table. + * + * @return + * - ESP_OK on success (storage was deinitialized) + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage was not initialized prior to this call + */ +esp_err_t nvs_flash_deinit(void); + +/** + * @brief Deinitialize NVS storage for the given NVS partition + * + * @param[in] partition_label Label of the partition + * + * @return + * - ESP_OK on success + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage for given partition was not + * initialized prior to this call + */ +esp_err_t nvs_flash_deinit_partition(const char* partition_label); /** * @brief Erase the default NVS partition diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index e5c2f5adc..dba8e115a 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -126,6 +126,42 @@ extern "C" esp_err_t nvs_flash_init(void) return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME); } +extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name) +{ + Lock::init(); + Lock lock; + + nvs::Storage* storage = lookup_storage_from_name(partition_name); + if (!storage) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + /* Clean up handles related to the storage being deinitialized */ + auto it = s_nvs_handles.begin(); + auto next = it; + while(it != s_nvs_handles.end()) { + next++; + if (it->mStoragePtr == storage) { + ESP_LOGD(TAG, "Deleting handle %d (ns=%d) related to partition \"%s\" (missing call to nvs_close?)", + it->mHandle, it->mNsIndex, partition_name); + s_nvs_handles.erase(it); + delete static_cast(it); + } + it = next; + } + + /* Finally delete the storage itself */ + s_nvs_storage_list.erase(storage); + delete storage; + + return ESP_OK; +} + +extern "C" esp_err_t nvs_flash_deinit(void) +{ + return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); +} + extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name) { const esp_partition_t* partition = esp_partition_find_first( diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index 07d01db46..ed0884a7d 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -59,5 +59,9 @@ TEST_CASE("various nvs tests", "[nvs]") TEST_ASSERT_EQUAL_INT32(0, strcmp(buf, str)); nvs_close(handle_1); + + // check that deinit does not leak memory if some handles are still open + nvs_flash_deinit(); + nvs_close(handle_2); }