Resolving NVS Flash Corruption on ESP32
What causes this
NVS (Non-Volatile Storage) flash corruption on the ESP32 is often a consequence of improper shutdowns, power failures, or frequent writes leading to wear and tear on the flash memory. The ESP32's flash memory is divided into sectors, each of which has a limited number of write-erase cycles. Overusing these cycles can lead to corruption. Additionally, incomplete writes, often due to interrupts or resets during a write operation, result in corrupted data. Within the ESP-IDF, the NVS implementation uses multiple sectors to ensure data integrity, but it relies on the proper functioning of the underlying flash operations. Corruption manifests in errors like ESP_ERR_NVS_NOT_FOUND or ESP_ERR_NVS_CORRUPT, and can be traced back to the internal flash operation failures via registers such as FLASH_STATUS, FLASH_CMD, and FLASH_WP.
Minimal reproduction
To reproduce NVS flash corruption, you can simulate a power failure during a write operation:
```cpp
#include
#include
void app_main() {
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// NVS partition was truncated and needs to be erased
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Open NVS handle
nvs_handle_t nvs_handle;
ret = nvs_open("storage", NVS_READWRITE, &nvs_handle);
ESP_ERROR_CHECK(ret);
// Simulate power failure during write
for (int i = 0; i < 100; i++) {
ret = nvs_set_i32(nvs_handle, "key", i);
ESP_ERROR_CHECK(ret);
// Simulate abrupt reset/power failure
if (i == 50) {
esp_restart();
}
}
nvs_close(nvs_handle);
}
```
Expected Serial Output/Backtrace:
```
E (100) nvs: write failed at offset xxxxxx
E (100) nvs: NVS item is corrupted
E (100) nvs_flash: flash read error
```
The fix
To fix NVS flash corruption, ensure your application handles power failures gracefully and minimizes write cycles. Implement checks and balances in your code to detect potential corruptions early.
Before:
```cpp
esp_err_t ret = nvs_set_i32(nvs_handle, "key", value);
ESP_ERROR_CHECK(ret);
```
After:
```cpp
esp_err_t ret = nvs_set_i32(nvs_handle, "key", value);
if (ret != ESP_OK) {
// Handle the error
if (ret == ESP_ERR_NVS_CORRUPT) {
// Attempt to recover by erasing the NVS
nvs_flash_erase();
nvs_flash_init();
}
}
```
Additionally, consider using wear leveling mechanisms and battery-backed capacitors to safeguard against power failures.
How SerialDoctor catches this
SerialDoctor connects to your ESP32 via Web Serial, capturing and analyzing the serial output in real-time. When it detects error codes like ESP_ERR_NVS_CORRUPT, SerialDoctor quickly pinpoints NVS flash corruption as the root cause, offering immediate insights and suggestions. Visit [serialdoctor.com](https://serialdoctor.com) to see how it can streamline your debugging process.
Quick checklist
- [ ] Limit the frequency of NVS write operations to extend flash lifespan.
- [ ] Implement power failure detection and graceful shutdown mechanisms.
- [ ] Regularly back up critical data to secondary storage.
- [ ] Use error handling to catch and manage
ESP_ERR_NVS_CORRUPT. - [ ] Monitor flash wear and use wear leveling techniques to prevent sector overuse.
Seeing this crash on your board right now?
Connect it to SerialDoctor and get a root cause + code fix in under 3 seconds.
Try SerialDoctor free →