需要在ESP8266的FLASH中存储一些可变参数,有两种方式,一种是调用SPI Flash API直接指定地址读写FLASH;二是在SPI FLASH上创建一块SPIFFS 分区,以读写文件的形式存取数据。
下面记录第二种方式,使用SPIFFS文件系统存取参数。
查看当前分区情况:
进入编译目录,执行make partition_table编译分区,结果如下:
# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,16K,
otadata,data,ota,0xd000,8K,
phy_init,data,phy,0xf000,4K,
ota_0,app,ota_0,0x10000,960K,
ota_1,app,ota_1,0x110000,960K,
总共占了2M空间,SPI FLASH总尺寸为2M(2048K)。不过ota_0与ota_1之间还有64K没有使用,那么就将spiffs分区设置在此处,尺寸为64K。
重新生成分区表
在工程目录下创建一个partitions_two_ota_spiffs.csv文件,内容如下:
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
ota_0, 0, ota_0, 0x10000, 0xF0000
storage, data, spiffs, 0x100000,0x10000
ota_1, 0, ota_1, 0x110000,0xF0000
其它分区不变,增加spiffs分区,地址:0x100000,大小:0x10000(64K)。
执行make menuconfig,Partition Table选择Custom partition table CSV,Custom partition CSV file 选择partitions_two_ota_spiffs.csv。
保存之后,退出。
执行make partition_table重新编译分区文件,编译之后分区信息如下:
# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,16K,
otadata,data,ota,0xd000,8K,
phy_init,data,phy,0xf000,4K,
ota_0,app,ota_0,0x10000,960K,
storage,data,spiffs,0x100000,64K,
ota_1,app,ota_1,0x110000,960K,
执行make partition_table-flash ESPPORT=COM10 ESPBAUD=115200烧写分区。
测试SPIFFS
参考esp-idf\ESP8266_RTOS_SDK\examples\storage\spiffs\例程,在void app_main(void)()中加入测试代码:
void SPIFFS_Init( void )
{
ESP_LOGI(TAG, "Initializing SPIFFS");
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = true
};
// Use settings defined above to initialize and mount SPIFFS filesystem.
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info(NULL, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
} else {
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
// Use POSIX and C standard library functions to work with files.
// First create a file.
ESP_LOGI(TAG, "Opening file");
FILE* f = fopen("/spiffs/hello.txt", "w");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "Hello World!\n");
fclose(f);
ESP_LOGI(TAG, "File written");
// Check if destination file exists before renaming
struct stat st;
if (stat("/spiffs/foo.txt", &st) == 0) {
// Delete it if it exists
unlink("/spiffs/foo.txt");
}
// Rename original file
ESP_LOGI(TAG, "Renaming file");
if (rename("/spiffs/hello.txt", "/spiffs/foo.txt") != 0) {
ESP_LOGE(TAG, "Rename failed");
return;
}
// Open renamed file for reading
ESP_LOGI(TAG, "Reading file");
f = fopen("/spiffs/foo.txt", "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[64];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char* pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
// All done, unmount partition and disable SPIFFS
esp_vfs_spiffs_unregister(NULL);
ESP_LOGI(TAG, "SPIFFS unmounted");
}
编译应用并烧写到设备,启动日志如下:
[0m[0;32mI (2971) storage: Partition size: total: 52961, used: 0[0m
[0mI (3030) storage: Opening file[0m
[0;32mI (3197) storage: File written[0m
[0;32mI (3229) storage: Renaming file[0m
[0;32mI (3279) storage: Reading file[0m
[0;32mI (3319) storage: Read from file: 'Hello World!'[0m
[0;32mI (3379) storage: SPIFFS unmounted[0m
实际可使用的空间大小为51k。