此文权当学习开发笔记,如有错误,敬请读者指出!如果读者要用于自己的项目,出现bug请责任自负。
用ESP8266来开发项目,需要存储用户信息,看了乐鑫关于NVS操作的说明,发现NVS操作很是方便快捷,而且有读写均衡,自动校验、自动避开坏区、NVS加密等功能,好处很多。
但就是乐鑫IDF3.2目前单纯支持NVS_DEFAULT_PART_NAME的操作,再细看它底层封装是#define NVS_DEFAULT_PART_NAME "nvs"
再看看函数的实现:
extern "C" esp_err_t nvs_flash_erase()
{
return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
}
extern "C" esp_err_t nvs_flash_init(void)
{
return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
}
extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
{
if (s_nvs_storage_list.size() == 0) {
return ESP_ERR_NVS_NOT_INITIALIZED;
}
return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle);
}
都是基于NVS_DEFAULT_PART_NAME来实现的。
好了,要创建自己的NVS分区,首先要把这些函数改了:
先定义自己的分区名字:
#ifndef USER_PARTITION_NAME
#define USER_PARTITION_NAME "user"
#endif
extern "C" esp_err_t my_nvs_flash_erase()
{
return nvs_flash_erase_partition(USER_PARTITION_NAME);
}
extern "C" esp_err_t my_nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
{
if (s_nvs_storage_list.size() == 0) {
return ESP_ERR_NVS_NOT_INITIALIZED;
}
return nvs_open_from_partition(USER_PARTITION_NAME, name, open_mode, out_handle);
}
extern "C" esp_err_t my_nvs_flash_init(void)
{
return nvs_flash_init_partition(USER_PARTITION_NAME);
}
把这几个函数添加到nvs_falsh.h头文件中
再修改partitions_two_ota.csv中的分区表,增加一个名为user的分区
写个小程序测试一下:基于乐鑫的demo改的
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",
},
};
ESP_LOGI(TAG,"set size:%u\r\n", sizeof(wifi_config_to_store));
if( my_nvs_open( NVS_CUSTOMER, NVS_READWRITE, &handle) !=ESP_OK)
{
ESP_LOGI(TAG, "my_nvs_open error ");
return;
}
if( nvs_set_str( handle, DATA1, "i am a string.") !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_set_str error ");
return;
}
if( nvs_set_i32( handle, DATA2, value_for_store) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_set_i32 error ");
return;
}
if( nvs_set_blob( handle, DATA3, &wifi_config_to_store, sizeof(wifi_config_to_store)) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_set_blob error ");
return;
}
if( nvs_commit(handle) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_commit error ");
return;
}
nvs_close(handle);
}
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);
if( my_nvs_open(NVS_CUSTOMER, NVS_READWRITE, &handle) !=ESP_OK)
{
ESP_LOGI(TAG, "my_nvs_open error ");
return;
}
if( nvs_get_str(handle, DATA1, str_data, &str_length) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_get_str error ");
return;
}
if( nvs_get_i32(handle, DATA2, &value) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_get_i32 error ");
return;
}
if( nvs_get_blob(handle, DATA3, &wifi_config_stored, &len) !=ESP_OK)
{
ESP_LOGI(TAG, "nvs_get_blob error ");
return;
}
ESP_LOGI(TAG, "[data1]: %s len:%u ", str_data, str_length);
ESP_LOGI(TAG, "[data2]: %d ", value);
ESP_LOGI(TAG, "[data3]: ssid:%s passwd:%s ", wifi_config_stored.sta.ssid, wifi_config_stored.sta.password);
nvs_close(handle);
}
编译通过,上电测试一下:
[0;32mI (105) boot: compile time 15:10:01[0m
[0;32mI (113) qio_mode: Enabling default flash chip QIO[0m
[0;32mI (117) boot: SPI Speed : 40MHz[0m
[0;32mI (126) boot: SPI Mode : QIO[0m
[0;32mI (134) boot: SPI Flash Size : 2MB[0m
[0;32mI (142) boot: Partition Table:[0m
[0;32mI (149) boot: ## Label Usage Type ST Offset Length[0m
[0;32mI (164) boot: 0 nvs WiFi data 01 02 00009000 00004000[0m
[0;32mI (179) boot: 1 otadata OTA data 01 00 0000d000 00002000[0m
[0;32mI (194) boot: 2 phy_init RF data 01 01 0000f000 00001000[0m
[0;32mI (209) boot: 3 ota_0 OTA app 00 10 00010000 000e0000[0m
[0;32mI (225) boot: 4 ota_1 OTA app 00 11 00100000 000e0000[0m
[0;32mI (240) boot: 5 user WiFi data 01 02 001f0000 00010000[0m
[0;32mI (255) boot: End of partition table[0m
试着读写,再掉电重启,数据依旧保存着,然后擦除nvs分区,user分区的数据还在,试着擦除user分区,nvs的数据还在。2个分区的数据是没有关联性。也就是说创建自己的分区成功了,函数修改也凑效了。
[11:03:35.175]发→◇User_PartW□
[11:03:35.181]收←◆[0;32mI (650231) uart_events: uart[0] event:[0m
[0;32mI (650232) uart_events: [UART DATA]: 10[0m
[0;32mI (650234) uart_events: [DATA EVT]: User_PartW[0m
[0;32mI (650246) app: Got sys_uart0_queue message: User_PartW [0m
[0;32mI (650247) app: Got USER_PART_WRITE order, system write user data to partition [0m
[0;32mI (650250) my_mvs: set size:124
[0m
[11:03:37.409]发→◇User_PartR□
[11:03:37.415]收←◆[0;32mI (652461) uart_events: uart[0] event:[0m
[0;32mI (652462) uart_events: [UART DATA]: 10[0m
[0;32mI (652463) uart_events: [DATA EVT]: User_PartR[0m
[0;32mI (652470) app: Got sys_uart0_queue message: User_PartR [0m
[0;32mI (652471) app: Got USER_PART_READ order, system read user data from partition [0m
[0;32mI (652480) my_mvs: [data1]: i am a string. len:15 [0m
[0;32mI (652484) my_mvs: [data2]: 666 [0m
[0;32mI (652488) my_mvs: [data3]: ssid:store_ssid:hello_kitty passwd:store_password:1234567890 [0m