轉載:espressif
NVS 介紹
NVS: Non-volatile storage
, 即將數據存儲到 flash 中, 掉電或重啓後數據仍然存在, flash 類似於 PC 上磁盤.
ESP8266 和 ESP32 上提供 nvs 接口給用戶, 來保存和讀取用戶數據. 具體參考 nvs.h
nvs
更詳細的說明請參考: NVS 文檔
NVS 優勢
-
接口更加安全
相比較於
spi_flash_read
和spi_flash_write
等接口,NVS
不直接操作address
. 對於終端用戶而已, 更加安全.
例如: 應用複雜一點, 容易spi_flash_write(address, src, size)
不小心寫到同一個地址, 或地址寫覆蓋, 而導致長時間 debug -
接口使用接近用戶習慣
NVS
接口類似於電腦上操作文件一樣:
打開文件(nvs_open
), 寫文件(nvs_set_xxx
), 保存文件(nvs_commit
), 關閉文件(nvs_close
)
打開文件(nvs_open
), 讀取文件(nvs_get_xxx
), 關閉文件(nvs_close
) -
擦寫均衡, 使 flash 壽命更長
NVS
在操作少量數據上,NVS
分區更大時, 擦寫均衡表現的更爲明顯.例如: flash 一個
sector
爲4KB, NVS
分配大小爲一個sector
, 寫同一個64 Bytes
數據到flash
, 分別比較spi_flash_xxx
和nvs
寫 64 次 -
spi_flash_write
: 每次寫flash
前, 需擦除flash
. 對應: 64 次擦除flash
, 64 次寫flash
-
nvs: nvs
內部有擦寫均衡, 有標誌位記錄當前有效存儲. 如第一次擦除sector
, 再寫sector 0-63 Byte
, 第二次寫sector 64-127 Bytes
, 第 64 次(4KB/64Bytes)
寫完sector
最後一個64 Byte
. 對應: 1 次擦除flash
,64
次寫flash
這樣NVS
減少64
倍擦除操作, 對flash
壽命有較大提升.
在NVS
分區更大, 存儲信息少時, 表現的更爲明顯.
NVS 寫
void nvs_write_data_to_flash(void)
{
nvs_handle handle;
static const char *NVS_CUSTOMER = "customer data";
static const char *DATA1 = "param 1";
static const char *DATA2 = "param 2";
static const char *DATA3 = "param 3";
int32_t value_for_store = 666;
wifi_config_t wifi_config_to_store = {
.sta = {
.ssid = "store_ssid:hello_kitty",
.password = "store_password:1234567890",
},
};
printf("set size:%u\r\n", sizeof(wifi_config_to_store));
ESP_ERROR_CHECK( nvs_open( NVS_CUSTOMER, NVS_READWRITE, &handle) );
ESP_ERROR_CHECK( nvs_set_str( handle, DATA1, "i am a string.") );
ESP_ERROR_CHECK( nvs_set_i32( handle, DATA2, value_for_store) );
ESP_ERROR_CHECK( nvs_set_blob( handle, DATA3, &wifi_config_to_store, sizeof(wifi_config_to_store)) );
ESP_ERROR_CHECK( nvs_commit(handle) );
nvs_close(handle);
}
NVS 讀
void nvs_read_data_from_flash(void)
{
nvs_handle handle;
static const char *NVS_CUSTOMER = "customer data";
static const char *DATA1 = "param 1";
static const char *DATA2 = "param 2";
static const char *DATA3 = "param 3";
uint32_t str_length = 32;
char str_data[32] = {0};
int32_t value = 0;
wifi_config_t wifi_config_stored;
memset(&wifi_config_stored, 0x0, sizeof(wifi_config_stored));
uint32_t len = sizeof(wifi_config_stored);
ESP_ERROR_CHECK( nvs_open(NVS_CUSTOMER, NVS_READWRITE, &handle) );
ESP_ERROR_CHECK ( nvs_get_str(handle, DATA1, str_data, &str_length) );
ESP_ERROR_CHECK ( nvs_get_i32(handle, DATA2, &value) );
ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA3, &wifi_config_stored, &len) );
printf("[data1]: %s len:%u\r\n", str_data, str_length);
printf("[data2]: %d\r\n", value);
printf("[data3]: ssid:%s passwd:%s\r\n", wifi_config_stored.sta.ssid, wifi_config_stored.sta.password);
nvs_close(handle);
}
其他說明
- 不限於上面功能,
nvs.h
中提供更多接口給用戶使用 - 可參考
esp-idf
nvs blob demo來測試相關接口和使用 - NVS說明文檔