mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
nvs: check that storage has at least one free page
This change adds a check for the free page count to nvs_flash_init. Under normal operation, NVS keeps at least one free page available, except for transient states such as freeing up new page. Due to external factors (such as NVS partition size reduction) this free page could be lost, making NVS operation impossible. Previously this would cause an error when performing any nvs_set operation or opening a new namespace. With this change, an error is returned from nvs_flash_init to indicate that NVS partition is in such a state.
This commit is contained in:
parent
817bbb4bf9
commit
5a23ec4dc4
@ -9,10 +9,12 @@ Non-volatile storage (NVS) library is designed to store key-value pairs in flash
|
|||||||
Underlying storage
|
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.
|
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
|
Keys and values
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ typedef uint32_t nvs_handle;
|
|||||||
#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs_ API functions */
|
#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_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_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
|
* @brief Mode of opening the non-volatile storage
|
||||||
|
@ -21,7 +21,11 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief Initialize NVS flash storage with layout given in the partition table.
|
* @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);
|
esp_err_t nvs_flash_init(void);
|
||||||
|
|
||||||
|
@ -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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]")
|
TEST_CASE("dump all performance data", "[nvs]")
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@ Macros
|
|||||||
.. doxygendefine:: ESP_ERR_NVS_PAGE_FULL
|
.. doxygendefine:: ESP_ERR_NVS_PAGE_FULL
|
||||||
.. doxygendefine:: ESP_ERR_NVS_INVALID_STATE
|
.. doxygendefine:: ESP_ERR_NVS_INVALID_STATE
|
||||||
.. doxygendefine:: ESP_ERR_NVS_INVALID_LENGTH
|
.. doxygendefine:: ESP_ERR_NVS_INVALID_LENGTH
|
||||||
|
.. doxygendefine:: ESP_ERR_NVS_NO_FREE_PAGES
|
||||||
|
|
||||||
Type Definitions
|
Type Definitions
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
@ -61,6 +62,7 @@ Enumerations
|
|||||||
|
|
||||||
Functions
|
Functions
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
.. doxygenfunction:: nvs_flash_init
|
||||||
.. doxygenfunction:: nvs_open
|
.. doxygenfunction:: nvs_open
|
||||||
.. doxygenfunction:: nvs_set_i8
|
.. doxygenfunction:: nvs_set_i8
|
||||||
.. doxygenfunction:: nvs_set_u8
|
.. doxygenfunction:: nvs_set_u8
|
||||||
@ -86,5 +88,5 @@ Functions
|
|||||||
.. doxygenfunction:: nvs_erase_all
|
.. doxygenfunction:: nvs_erase_all
|
||||||
.. doxygenfunction:: nvs_commit
|
.. doxygenfunction:: nvs_commit
|
||||||
.. doxygenfunction:: nvs_close
|
.. doxygenfunction:: nvs_close
|
||||||
.. doxygenfunction:: nvs_flash_init
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user