赞
踩
存储器类型 | 描述 | 容量 |
---|---|---|
内部存储器 | ||
ROM | 用于存储固定的程序代码和数据 | 384KB |
SRAM | 用于存储运行时的程序数据 | 512KB |
RTC SRAM | 在深度睡眠模式下仍然保持数据 | 16KB |
外部存储器 | ||
PSRAM | 片外用于存储运行时的程序数据 | 最大16MB |
特殊存储器 | ||
RTC FAST memory | 可以作为指令存储器也可以作为数据存储器进行访问 | - |
RTC Slow memory | 从深度睡眠模式唤醒后必须要运行的代码要放在 RTC 存储器中 | - |
SPI Flash | 片外通过 SPI接口外接 | 最大16MB |
对于片外的Flash 它是可读可写的,由于它的容量高达16MB,这意味着我们可以在其中存储大量的配置文件、图像、音频文件,甚至是一些小型的视频文件,可以尝试很多有趣的项目和应用
ESP32-S3 的 Flash 存储器,它被划分为多个分区,每个分区都有特定的用途。
而Flash分区表它定义了 Flash 存储器的布局。Flash 分区表中的每个条目都描述了一个分区的属性,包括其在 Flash 中的位置(偏移量)、大小、类型、以及其他一些属性。
在使用分区表时,最简单的方法就是打开项目配置菜单(idf.py menuconfig
),并在 CONFIG_PARTITION_TABLE_TYPE
下选择一个预定义的分区表:
“Single factory app, no OTA”
“Factory app, two OTA definitions”
如果想要查看当前使用的分区表 只要在终端运行 idf.py partition-table
,即可以打印当前使用分区表的信息摘要。
这里我使用的Single factory app, no OTA
分区表
自定义分区表
关于自定义分区表可以查看我写的另一篇博客
15-partition table (分区表)
以下是 “Factory app, two OTA definitions” 选项的分区表信息摘要:
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
ota_0, app, ota_0, 0x110000, 1M,
ota_1, app, ota_1, 0x210000, 1M,
Factory app, two OTA definitions
相比Single factory app, no OTA
多了otadata
,ota_0
,ota_1
这三个分区
这三个分区在 ESP32-S3 的 OTA(Over-The-Air)更新机制中起着重要的作用。它们三个共同支持 ESP32-S3 的 OTA 更新功能,使设备能够在固件正常运行时根据接收数据(如通过 Wi-Fi 或蓝牙)进行自我更新。
ESP32-S3启动时 启动加载器会查询 “otadata” 分区的数据,以判断该从哪个 OTA 应用程序分区加载程序,如果不存在 “otadata” 分区则会从factory分区启动
前面铺垫了这么多,存储有了,哪怎么使用这些空间呢,这就需要文件管理系统了,在我们的windows电脑里有NTFS文件系统,在安卓手机里有F2FS 文件系统,而对于ESP32有SPIFFS文件系统。
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(Serial Peripheral Interface Flash File System)和 NVS(Non-Volatile Storage)都是 ESP32-S3 的存储系统,但它们有一些关键的区别。
总的来说,SPIFFS 更适合用于存储文件,而 NVS 更适合用于存储键值对数据。具体使用哪种存储系统,取决于应用需求。
该函数使用给定的路径前缀将 SPIFFS 注册并装载到 VFS,其函数原型如下所示:
esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf);
该函数的形参描述,如下表所示:
形参 | 描述 |
---|---|
conf | 指向 esp_vfs_spiffs_conf_t 配置结构的指针 |
需要解释一下,函数名esp_vfs_spiffs_register
中的VFS(虚拟文件系统)是操作系统内核的抽象层,统一了不同文件系统的接口,使应用程序能够通过通用接口访问各种底层文件系统。ESP32 中的 SPIFFS 就是通过 VFS 来提供文件系统支持的。
该函数的使用示例,如下所示:
#include "driver/gpio.h"
void example_fun(void)
{
/* 配置 SPIFFS 文件系统各个参数 */
esp_vfs_spiffs_conf_t conf = {
.base_path = mount_point, // 设置挂载点的路径
.partition_label = partition_label, // 设置SPIFFS的分区标签
.max_files = max_files, // 设置文件系统支持的最大文件数
.format_if_mount_failed = true, // 如果挂载失败,是否尝试格式化分区
};
/* 使用上面定义的设置来初始化和挂载 SPIFFS 文件系统 */
esp_err_t ret_val = esp_vfs_spiffs_register(&conf); // 注册并装载 SPIFFS
}
该函数用于获取 SPIFFS 的信息,其函数原型如下所示:
esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes);
该函数的形参描述,如下表所示:
形参 | 描述 |
---|---|
partition_label | 指向分区标签的指针,分区表名称 |
total_bytes | 存放文件系统的大小 |
used_bytes | 存放文件系统中当前使用的字节数 |
该函数的使用示例,如下所示:
#include "esp_spiffs.h"
void app_main(void)
{
size_t total = 0, used = 0;
esp_spiffs_info(partition_label, &total, &used); //获取信息
printf("Flash chip size: %d\n", total);
printf("Used size: %d\n", used);
}
该函数从 VFS 注销和卸载 SPIFFS,其函数原型如下所示:
esp_err_t esp_vfs_spiffs_unregister(const char* partition_label);
该函数的形参描述,如下表所示:
形参 | 描述 |
---|---|
partition_label | 指向分区表的指针,分区表名称 |
该函数的使用示例,如下所示:
#include "driver/gpio.h"
void example_fun(char *partition_label)
{
esp_vfs_spiffs_unregister(partition_label); // 注销和卸载 SPIFFS
}
除了上面这三个函数外,常常还需要调用到了 C 库的函数,对这块遗忘的博友可以看下 下面这篇博客来复习一下
C语言文件操作
在 flash 指定区域新建 holle.txt 文件,然后对这文件进行读写操作
首先我们需要在分区表中创建一块分区,用以存放holle.txt 文件,具体方法可以查看我写的另一篇文章,这里我就不多赘述了
15-partition table (分区表)
这里是我配置的分区表,可以参考一下
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
SPIFFS, data, spiffs, 0x110000, 1M,
程序如下
#include "esp_spiffs.h" #include "esp_log.h" void app_main(void){ // 初始化 SPIFFS esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", // 指定 SPIFFS 的挂载路径 .partition_label = "SPIFFS", // 分区标签,如果为 NULL,则使用默认的 SPIFFS 分区 .max_files = 5, // SPIFFS 可以打开的最大文件数 .format_if_mount_failed = true // 如果挂载失败,是否格式化 SPIFFS }; // 注册 SPIFFS 到 VFS esp_err_t ret = esp_vfs_spiffs_register(&conf); // 检查 SPIFFS 是否成功初始化 if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE("TAG", "无法挂载或格式化文件系统"); } else if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE("TAG", "未找到 SPIFFS 分区"); } else { ESP_LOGE("TAG", "无法初始化 SPIFFS (%s)", esp_err_to_name(ret)); } return; } // 写入文件 FILE* f = fopen("/spiffs/hello.txt", "w"); // 打开一个文件进行写入 if (f == NULL) { ESP_LOGE("TAG", "无法打开文件进行写入"); return; } fprintf(f, "你好,世界!\n"); // 向文件中写入数据 fclose(f); // 关闭文件 // 读取文件 char line[64]; f = fopen("/spiffs/hello.txt", "r"); // 打开一个文件进行读取 if (f == NULL) { ESP_LOGE("TAG", "无法打开文件进行读取"); return; } fgets(line, sizeof(line), f); // 从文件中读取一行数据 fclose(f); // 关闭文件 // 打印文件内容 printf("从文件中读取:'%s'\n", line); // 卸载 SPIFFS esp_vfs_spiffs_unregister(NULL); // 从 VFS 中注销 SPIFFS }
在这个项目中 首先初始化 SPIFFS,然后在 /spiffs 目录下创建一个名为 hello.txt 的文件,并向其中写入 “Hello World!\n”。然后,它打开这个文件并读取其中的内容,最后打印出读取到的内容。在完成所有操作后,它将卸载 SPIFFS。
编译 下载 打开串口 三步走 效果和我们期望的一样,实验成功
每次通过程序代码去保存和修改文件也太麻烦了,那么有没有一种工具,可以直接向开发板中传文件呢?
SPIFFS 提供了一个 Python 工具 spiffsgen.py
,用于从主机文件夹内容生成文件系统镜像。使用方法就两步。
1️⃣制作spiffs文件系统镜像
打开终端并运行以下命令即可使用 spiffsgen.py
:
python spiffsgen.py <image_size> <base_dir> <output_file>
参数(必选)说明如下:
image_size
:分区大小,用于烧录生成的 SPIFFS 镜像;base_dir
:创建 SPIFFS 镜像的目录;output_file
:SPIFFS 镜像输出文件(也就是生成的bin文件的文件名)。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。