SPIFFS 文件系统
简介
SPIFFS 是一个用于 SPI NOR flash 设备的嵌入式文件系统,支持磨损均衡、文件系统一致性检查等功能。ESP32-C3 支持使用 SPIFFS 文件系统来存储和访问数据。
SPIFFS是一个完整的操作系统,不需要再借助其它的文件系统来实现文件的读写。
使用方法
由于对应的SPI存储芯片是ESP32-C3的内部存储芯片,所以SPIFFS文件系统是直接在ESP32-C3上运行的,不需要额外的硬件支持。所以使用方法也非常简单,只需要在代码中包含SPIFFS的头文件,然后初始化SPIFFS文件系统即可。
1.引入头文件
#include "esp_vfs_fat.h"
#include "esp_spiffs.h"
2.初始化SPIFFS文件系统
esp_err_t init_fs(void)
{
esp_vfs_spiffs_conf_t conf = {
.base_path = CONFIG_EXAMPLE_WEB_MOUNT_POINT,
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = false};
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 ESP_FAIL;
}
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);
}
return ESP_OK;
}
注意:
base_path
是 SPIFFS 文件系统的根目录,可以自定义。在读写文件时,需要从这个根路径开始写起,写出完整的路径才可以。partition_label
是 SPIFFS 文件系统的分区标签,可以自定义。这个分区标签,是与分区表
的名称相对应的。这个名称与base_path
是独立的,没有关联性。分区表的名称,是为了区分不同分区而设置的。这里的分区标签,是为了让fs知道,在哪个分区上挂载SPIFFS文件系统。但如果没有设置分区标签,那么fs会自动在第一个分区上挂载SPIFFS文件系统。 如果在调用 esp_vfs_spiffs_register 函数时,esp_vfs_spiffs_conf_t 结构体里的 partition_label 被设置为 NULL,该函数会使用分区表中第一个子类型(subtype)为 spiffs 的分区。
在 ESP-IDF 里,分区表定义了不同分区的用途、大小和类型。分区表一般是一个 CSV 文件,其中每个分区会指定类型(type)和子类型(subtype)。对于 SPIFFS 文件系统,子类型为 spiffs。
下面是一个简单的分区表示例:Name Type SubType Offset Size Flags nvs data nvs 0x9000 0x5000 otadata data ota 0xe000 0x2000 app0 app ota_0 0x10000 0x140000 app1 app ota_1 0x150000 0x140000 www data spiffs 0x290000 0x170000 在这个分区表中,
www
分区的子类型是spiffs。当 partition_label为NULL时,esp_vfs_spiffs_register 就会使用这个分区。max_files
是 SPIFFS 文件系统的最大文件数,可以自定义。format_if_mount_failed
是是否在挂载失败时格式化文件系统,可以自定义。
3.读写文件
esp_err_t write_file(const char *path, const char *data, size_t size) {
FILE *f = fopen(path, "w");
if (!f)
{
ESP_LOGE(TAG, "Failed to open file for writing");
return ESP_FAIL;
}
size_t written = fwrite(data, 1, size, f);
fclose(f);
if (written != size)
{
ESP_LOGE(TAG, "Failed to write file");
}
return ESP_OK;
}
esp_err_t read_file(const char *path, char *data, size_t size) {
FILE *f = fopen(path, "r");
if (!f)
{
ESP_LOGE(TAG, "Failed to open file for reading");
return ESP_FAIL;
}
size_t read = fread(data, 1, size, f);
fclose(f);
if (read == 0)
{
ESP_LOGE(TAG, "Failed to read file");
return ESP_FAIL;
}
return ESP_OK;
}