ESP32原生开发——SPIFFS食用指南 2SPIFFS介绍

SPIFFS(Serial Peripheral Interface Flash File System)是 ESP32-S3 的内存管理系统。更具体地说,它是一种在你的 ESP32 关机后不会擦除的内存存储。你可以使用它进行数据记录,保存访问代码,存储文件,以及记住用户输入的设置。

SPIFFS有以下特性和用处

在指定的地址保存的数据不会因为重新更新而删除(如用户配置好的用户设置)

不用外置的SD卡,节约硬件资源

保存HTML和CSS文件以及建立Web服务器

SPIFFS 是一个用于 SPI NOR flash 设备的嵌入式文件系统,支持磨损均衡、文件系统一致性检查等功能。

目前,SPIFFS 尚不支持目录,但可以生成扁平结构。如果 SPIFFS 挂载在 /spiffs 下,
在 /spiffs/tmp/myfile.txt 路径下创建一个文件则会在 SPIFFS 中生成一个名为 /tmp/myfile.txt 的文件,而不是在 /spiffs/tmp 下生成名为 myfile.txt 的文件;
SPIFFS 与 NVS 的区别
SPIFFS(Serial Peripheral Interface Flash File System)和 NVS(Non-Volatile Storage)都是 ESP32-S3 的存储系统,但它们有一些关键的区别。

NVS 在 SPI NOR flash 上实现了一个有容错性,和磨损均衡功能的键值对存储。
NVS 可以存储一些 PHY 初始化数据,也可以存储其他数据,一些断电存储的数据建议放在这里。
总的来说,SPIFFS 更适合用于存储文件,而 NVS 更适合用于存储键值对数据。具体使用哪种存储系统,取决于应用需求。

NVS一般储存分区表信息 尽量不要抹除

SPIFS的开辟

在前文已经制定了partition table的前提下

这个分区的label是storage,不要搞混

 分区表

 

spiffsgen.py

SPIFFS 提供了一个 Python 工具 spiffsgen.py,用于从主机文件夹内容生成文件系统镜像。使用方法就两步。

制作SPIFFS镜像

python spiffsgen.py <image_size> <base_dir> <output_file>

参数(必选)说明如下:

  • image_size:分区大小,用于烧录生成的 SPIFFS 镜像;
  • base_dir:创建 SPIFFS 镜像的目录;
  • output_file:SPIFFS 镜像输出文件(也就是生成的bin文件的文件名)。

然后是获取文件位置,我的是这里

C:\Espressif\frameworks\esp-idf-v5.3.1\components\spiffs

然后组合成一个贼他妈麻烦的命令

然后cd到项目目录

 

举个例子
首先我在项目中创建一个新文件夹,用来存放需要上传给开发板的内容 ,我就起名叫 Hello_spiffs,之后我又在这个文件夹中创建了一个文件 hello.txt,这是一个文本文件,分区大小我想要256 KB(也就是0x40000)

我这里是data,然后是2M(大小是0x110000)

这里是命令行全貌,非常长长长长长长长长长长长长长

C:\Users\smart\workspace\LVGL1>python C:\Espressif\frameworks\esp-idf-v5.3.1\components\spiffs\spiffsgen.py 0x110000 data data.bin

然后得到bin文件在项目目录中

 

2烧写spiffs文件系统镜像
生成二进制文件后,我们可以使用 esptool.py 工具将生成的二进制文件烧录到 ESP32-S3 的 Flash 存储器中。以下是一个示例命令:

也是长长长长长的没话说

python esptool.py --chip esp32-s3 --port COM16 --baud 115200 write_flash -z 0x110000 hello.bin

esptool的目录

C:\Espressif\frameworks\esp-idf-v5.3.1\components\esptool_py\esptool

老规矩cd到项目目录

总的来说

C:\Users\smart\workspace\LVGL1> 
python C:\Espressif\frameworks\esp-idf-v5.3.1\components\esptool_py\esptool\esptool.py --chip esp32-s3 --port COM3 --baud 115200 write_flash -z 0x110000 data.bin

 就代表了划分的成功

🚨注意事项

如果 ESP32-S3 在文件系统操作期间断电,可能会导致 SPIFFS 损坏。但是仍可通过 esp_spiffs_check 函数恢复文件系统。
当文件系统空间不足时,垃圾收集器会尝试多次扫描文件系统来寻找可用空间。

 

在CMAKE中执行

spiffs_create_partition_image 命令

 添加的位置

 创建文件

 将工程下../data 目录中的文件打包成 SPIFFS 镜像。

这个前两个参数一个是分区label的名称 后面是镜像的目录所在

 

在代码中挂载 SPIFFS 分区并使用

// 初始化SPIFFS
static void spiffs_init(void)
{
    esp_vfs_spiffs_conf_t conf = {
      .base_path = "/storage",
      .partition_label = "storage",
      .max_files = 5,
      .format_if_mount_failed = true
    };
    
    //注册SPIFFS到VFS
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    
    //检测是否成功初始化
    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE("SPIFFS", "Failed to mount or format filesystem");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE("SPIFFS", "Failed to find SPIFFS partition");
        } else {
            ESP_LOGE("SPIFFS", "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("SPIFFS", "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
    } else {
        ESP_LOGI("SPIFFS", "Partition size: total: %d, used: %d", total, used);
    }
}
关键在于这一段
    esp_vfs_spiffs_conf_t conf = {
      .base_path = "/storage", //挂载目录
      .partition_label = "storage", //label名称
      .max_files = 5,
      .format_if_mount_failed = true
    };

使用方式

// 读取并发送音频文件任务
static void audio_send_task(void *arg)
{
    // 打开音频文件
    FILE *file = fopen("/storage/RWR.pcm", "r"); //实际上这个目录和镜像名称没关系,好像和label的名称也没关系
    if (file == NULL) {
        ESP_LOGE("AUDIO", "Failed to open audio file");
        vTaskDelete(NULL); //准备delete掉task
        return;
    }
void app_main() {
    // 配置 SPIFFS
    esp_vfs_spiffs_conf_t conf = {
        .base_path = ""/audio"",      // 挂载点
        .partition_label = "audio",  // 分区名称
        .max_files = 5,              // 最大文件数
        .format_if_mount_failed = true  // 如果挂载失败,则格式化分区
    };

    // 挂载 SPIFFS 分区
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    ESP_ERROR_CHECK(ret);    // 检查是否挂载成功
    
    // 获取分区信息
    size_t total = 0, used = 0;
    ret = esp_spiffs_info(conf.partition_label, &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);
    }

    // 读取文件示例
    FILE* f = fopen("/audio/Canon.mp3", "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file");
        return;
    }
    
    //开始播放音乐 示例
    audio_player_play(f);    //播放音乐
    
    // 卸载 SPIFFS 分区
    esp_vfs_spiffs_unregister(conf.partition_label);
    ESP_LOGI(TAG, "SPIFFS unmounted");
}
其它例子

创建文件并读写

 

 1 #include "esp_spiffs.h"
 2 #include "esp_log.h"
 3 
 4 void app_main(void){
 5 
 6     // 初始化 SPIFFS
 7     esp_vfs_spiffs_conf_t conf = {
 8       .base_path = "/spiffs",  // 指定 SPIFFS 的挂载路径
 9       .partition_label = "SPIFFS",  // 分区标签,如果为 NULL,则使用默认的 SPIFFS 分区
10       .max_files = 5,  // SPIFFS 可以打开的最大文件数
11       .format_if_mount_failed = true  // 如果挂载失败,是否格式化 SPIFFS
12     };
13 
14     // 注册 SPIFFS 到 VFS
15     esp_err_t ret = esp_vfs_spiffs_register(&conf);
16 
17     // 检查 SPIFFS 是否成功初始化
18     if (ret != ESP_OK) {
19         if (ret == ESP_FAIL) {
20             ESP_LOGE("TAG", "无法挂载或格式化文件系统");
21         } else if (ret == ESP_ERR_NOT_FOUND) {
22             ESP_LOGE("TAG", "未找到 SPIFFS 分区");
23         } else {
24             ESP_LOGE("TAG", "无法初始化 SPIFFS (%s)", esp_err_to_name(ret));
25         }
26         return;
27     }
28 
29     // 写入文件
30     FILE* f = fopen("/spiffs/hello.txt", "w");  // 打开一个文件进行写入
31     if (f == NULL) {
32         ESP_LOGE("TAG", "无法打开文件进行写入");
33         return;
34     }
35     fprintf(f, "你好,世界!\n");  // 向文件中写入数据
36     fclose(f);  // 关闭文件
37 
38     // 读取文件
39     char line[64];
40     f = fopen("/spiffs/hello.txt", "r");  // 打开一个文件进行读取
41     if (f == NULL) {
42         ESP_LOGE("TAG", "无法打开文件进行读取");
43         return;
44     }
45     fgets(line, sizeof(line), f);  // 从文件中读取一行数据
46     fclose(f);  // 关闭文件
47 
48     // 打印文件内容
49     printf("从文件中读取:'%s'\n", line);
50 
51     // 卸载 SPIFFS
52     esp_vfs_spiffs_unregister(NULL);  // 从 VFS 中注销 SPIFFS
53 }

 

 

 

 

 




 

posted @ 2025-02-12 01:07  mcwhirr  阅读(703)  评论(0)    收藏  举报