26-ESP32-S3 的 FLASH分区表以及 SPIFFS 文件系统 和spiffsgen.py工具

ESP32-S3 的 SPIFFS 文件系统

ESP32-S3的ROM,RAM,FLASH

存储器类型描述容量
内部存储器
ROM用于存储固定的程序代码和数据384KB
SRAM用于存储运行时的程序数据512KB
RTC SRAM在深度睡眠模式下仍然保持数据16KB
外部存储器
PSRAM片外用于存储运行时的程序数据最大16MB
特殊存储器
RTC FAST memory可以作为指令存储器也可以作为数据存储器进行访问-
RTC Slow memory从深度睡眠模式唤醒后必须要运行的代码要放在 RTC 存储器中-
SPI Flash片外通过 SPI接口外接最大16MB

对于片外的Flash 它是可读可写的,由于它的容量高达16MB,这意味着我们可以在其中存储大量的配置文件、图像、音频文件,甚至是一些小型的视频文件,可以尝试很多有趣的项目和应用

Flash分区表

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 (分区表)

Flash 分区表的结构

以下是 “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多了otadataota_0ota_1这三个分区

这三个分区在 ESP32-S3 的 OTA(Over-The-Air)更新机制中起着重要的作用。它们三个共同支持 ESP32-S3 的 OTA 更新功能,使设备能够在固件正常运行时根据接收数据(如通过 Wi-Fi 或蓝牙)进行自我更新。

ESP32-S3启动时 启动加载器会查询 “otadata” 分区的数据,以判断该从哪个 OTA 应用程序分区加载程序,如果不存在 “otadata” 分区则会从factory分区启动

SPIFFS介绍

前面铺垫了这么多,存储有了,哪怎么使用这些空间呢,这就需要文件管理系统了,在我们的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 与 NVS 的区别

SPIFFS(Serial Peripheral Interface Flash File System)和 NVS(Non-Volatile Storage)都是 ESP32-S3 的存储系统,但它们有一些关键的区别。

  • NVS 在 SPI NOR flash 上实现了一个有容错性,和磨损均衡功能的键值对存储。
  • NVS 可以存储一些 PHY 初始化数据,也可以存储其他数据,一些断电存储的数据建议放在这里。

总的来说,SPIFFS 更适合用于存储文件,而 NVS 更适合用于存储键值对数据。具体使用哪种存储系统,取决于应用需求。

SPIFFS 的使用

1️⃣注册装载 SPIFFS

该函数使用给定的路径前缀将 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
}

2️⃣获取 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);
}

3️⃣注销和卸载 SPIFFS

该函数从 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){// 初始化 SPIFFSesp_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 到 VFSesp_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);// 卸载 SPIFFSesp_vfs_spiffs_unregister(NULL);  // 从 VFS 中注销 SPIFFS
}

在这个项目中 首先初始化 SPIFFS,然后在 /spiffs 目录下创建一个名为 hello.txt 的文件,并向其中写入 “Hello World!\n”。然后,它打开这个文件并读取其中的内容,最后打印出读取到的内容。在完成所有操作后,它将卸载 SPIFFS。

编译 下载 打开串口 三步走 效果和我们期望的一样,实验成功
在这里插入图片描述

spiffsgen.py

每次通过程序代码去保存和修改文件也太麻烦了,那么有没有一种工具,可以直接向开发板中传文件呢?

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文件的文件名)。

🚨注意(spiffsgen.py)这个空要用spiffsgen.py这个文件的绝对路径
这是我电脑上spiffsgen.py的位置

"D:\Espressif\frameworks\esp-idf-v5.2.1\components\spiffs\spiffsgen.py"

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

这样此时我就应该在控制台输入以下命令即可使用 spiffsgen.py

python D:\Espressif\frameworks\esp-idf-v5.2.1\components\spiffs\spiffsgen.py 0x40000 Hello_spiffs hello.bin

运行后如愿得到hello.bin文件
在这里插入图片描述
2️⃣烧写spiffs文件系统镜像
生成二进制文件后,我们可以使用 esptool.py 工具将生成的二进制文件烧录到 ESP32-S3 的 Flash 存储器中。以下是一个示例命令:

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

其中:

  • 0x110000 是文件系统的偏移量
  • hello.bin 是要烧录的文件。

主要修改这两个部分,关于文件系统的偏移量要写多少,我们可以查看一下当前使用的分区表 (在终端运行 idf.py partition-table )
在这里插入图片描述

以我的为例factory分区划到了0x10000,大小1M(也就是0x100000),所以我们需要偏移0x110000,到我们自己创建的SPIFFS分区

同样我们还需要找到电脑上esptool.py 程序的路径

"D:\Espressif\frameworks\esp-idf-v5.2.1\components\esptool_py\esptool\esptool.py"

修改好命令,复制到终端上,回车运行

python D:\Espressif\frameworks\esp-idf-v5.2.1\components\esptool_py\esptool\esptool.py --chip esp32-s3 --port COM16 --baud 115200 write_flash -z 0x110000 hello.bin

恭喜你如果输出以下信息就表示数据上传成功了
在这里插入图片描述

🚨注意事项

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

结论

SPIFFS 是 ESP32-S3 的一个强大的功能,它提供了一种简单而有效的方式来在设备上存储和检索数据。尽管它有一些限制,但对于大多数应用来说,这些限制并不构成问题。通过学习理解了 SPIFFS 的工作原理和如何在我的项目中使用它,我已经可以充分利用 ESP32-S3 的这一功能。同时,理解了SPIFFS 和 NVS 的区别也同样帮助我能更好地选择适合的存储系统。希望这篇博客对您有所帮助!

参考资料
正点原子DNESP32S3 开发板教程-IDF 版
乐鑫编程指南 分区表
SPIFFS 文件系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3032332.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【生信技能树】数据挖掘全流程

R包的安装&#xff0c;每次做分析的时候先运行这段代码把R包都安装好了&#xff0c;这段代码不需要任何改动&#xff0c;每次分析直接运行。 options("repos""https://mirrors.ustc.edu.cn/CRAN/") if(!require("BiocManager")) install.packag…

vue 点击平滑到指定位置并绑定页面滑动效果

1.html元素 写出对应的数据块&#xff08;注意添加ref) 用于获取元素位置 <template><div class"index-page" ><div class"top-head" ref"index"><img src"logo.png" style"height: 40px;margin-right: 2…

大模型面试常考知识点1

文章目录 1. 写出Multi-Head Attention2. Pre-Norm vs Post-Norm3. Layer NormRMS NormBatch Norm 4. SwiGLU从ReLU到SwishSwiGLU 5. AdamW6. 位置编码Transformer位置编码RoPEALibi 7. LoRA初始化 参考文献 1. 写出Multi-Head Attention import torch import torch.nn as nn …

【VMware】vSphere 8.0 安装和设置简介

本信息的目标读者为熟悉虚拟机技术和数据中心操作并具有丰富经验的 Windows 或 Linux 系统管理员。 vSphere 8.0 提供了各种安装和设置选项&#xff0c;这些选项定义了相应的任务序列。 vSphere 的两个核心组件是 ESXi 和 vCenter Server。ESXi 是可用于创建和运行虚拟机和虚拟…

【算法】最短路问题 bfs 到 dijkstra

1976、到达目的地的方案数 你在一个城市里&#xff0c;城市由 n 个路口组成&#xff0c;路口编号为 0 到 n - 1 &#xff0c;某些路口之间有 双向 道路。输入保证你可以从任意路口出发到达其他任意路口&#xff0c;且任意两个路口之间最多有一条路。 给你一个整数 n 和二维整…

laravel8 导入 excel常见问题

上传xls 或 xlsx 文件后&#xff0c;文件解析为 zip 格式&#xff0c;输入正常情况&#xff0c;不影响解析 里面的内容 遇到解析内容&#xff0c;解析为空的情况&#xff0c;可能是 因为excel 存在多个 Sheet1 造成&#xff0c;服务器不能解析一个 Sheet1 的情况&#xff0…

小程序获取手机号,用户昵称,头像

一、手机号 在微信小程序中&#xff0c;获取用户手机号也需要用户的明确授权。你可以使用 button 组件的 open-type 属性设置为 getPhoneNumber 来实现这个功能。当用户点击这个按钮时&#xff0c;会弹出一个对话框请求用户的授权。如果用户同意&#xff0c;你可以在 bindgetp…

如何通过优质服务建立客户忠诚度,促进口碑传播

在生活中&#xff0c;我们经常听到“客户忠诚度”一词&#xff0c;但很少有人真正理解客户忠诚度的含义。其实&#xff0c;客户忠诚度是指企业忠实于其所提供的产品或服务的程度&#xff0c;客户忠诚度对企业和个人都非常重要。高忠诚度的客户会给企业带来巨大的经济和社会效益…

VMware虚拟机故障:“显示指定的文件不是虚拟磁盘“,处理办法

一、故障现象 由于虚拟机宕机&#xff0c;强制重新启动虚拟机后显示错误&#xff0c;没有办法启动虚拟机。 虚拟机有快照&#xff0c;执行快照还原&#xff0c;结果也不行&#xff0c;反复操作&#xff0c;在虚拟机文件目录出现很多莫名文件 二、故障原因 根据故障提示&#…

Swift 初学者趣谈:一招教你记住模式匹配 if case let 的语法,永不忘记

概览 相信初学 Swift 头发茂盛的小伙伴们都对 Swift 简洁且极富表现力的语法倾心不已。不过凡事皆有例外&#xff0c;模式匹配&#xff08;Pattern Matching&#xff09;的语法就是其中之一。 在本篇博文中&#xff0c;您将学到如下内容 概览1. 诡异的 if case let 语法&…

代码随想录算法训练营第二十五天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树 题目链接/文章讲解&#xff1a; 代码随想录 视频讲解&#xff1a; 你修剪的方式不对&#xff0c;我来给你纠正一下&#xff01;| LeetCode&#xff1a;669. 修剪二叉搜索树_哔哩哔哩_bilibili 解题思路 在上一题的删除二叉树节点中&#xff0c;我们通过在…

python实现星号打印出金字塔

#编程实现下列图形的打印 a input() for i in range(int(a)//21): num * * ((i1)*2-1) print(num.center(int(a), )) 编译后通过。输入20后得到下面的星号金字塔

麒麟kylin-v10系统,虚拟机kvm的使用

kvm的使用 虚拟机新建 点击选择对应的iso文件 选择相应的系统 &#xff08;注意&#xff0c;如果这里没有相应的系统比如&#xff1a;windows&#xff0c;可以直接选择Generic default这是通用默认的意思&#xff09; 选择cpu 完成即可 等待安装完毕 网络设置-ssh连接 虚拟…

在 Navicat 17 创建一个数据字典

即将于 5 月 13 日发布的 Navicat 17&#xff08;英文版&#xff09;添加了许多令人兴奋的新功能。其中之一就是数据字典工具。它使用一系列 GUI 指导你完成创建专业质量文档的过程&#xff0c;该文档为跨多个服务器平台的数据库中的每个数据元素提供描述。在今天的博客中&…

企业网络需求及适合的解决方案

近年来&#xff0c;企业网络通信需求可谓五花八门&#xff0c;变幻莫测。它不仅为企业的生产、办公、研发、销售提供全面赋能&#xff0c;同时也让企业业务规模变大成为了可能。 在当前的技术格局下&#xff0c;中大型企业常见的技术方案有很多&#xff0c;而同时也有各自不可替…

docker部署minio和业务服务因变更minio密码导致访问不到图片的问题

问题起因 业务application和minio都是docker部署。按部署规则minio的环境变量中设置了MINIO_ROOT_USER和MINIO_ROOT_PASSWORD。这样就可以用这套用户名密码登录minio了。而我的application中是通过api访问minio获取资源URL&#xff0c;提供给前端的。所以在application的环境变…

4种最佳后端开发语言(2024版本)

本文发表于 入职啦 公众号。 什么是后端语言&#xff1f; 在开发方面&#xff0c;前端和后端技术之间有非常明显的区别。 Web开发方面虽然由于浏览器兼容性&#xff0c;前端生态系统仅限于 JavaScript&#xff08;和其他基于 JavaScript 的语言&#xff0c;如 TypeScript&…

C++笔试强训day17

目录 1.小乐乐改数字 2.十字爆破 3.比那名居的桃子 1.小乐乐改数字 链接 简单把他当成字符串遍历即可。 详细代码&#xff1a; #include <iostream> #include <string> using namespace std; int main() {string s;cin >> s;for (int i 0; i < s.si…

MySQL innodb_buffer_pool_size 相关常用语句

对于MySQL速度慢的问题&#xff0c;除了优化 SQL 以外&#xff0c;应该必须优先想到的即使 MySQL 数据库的 innodb_buffer_pool_size 配置问题。 一般来说&#xff0c;innodb_buffer_pool_size 的默认大小都是很小的&#xff0c;尤其是 win 下其默认大小更是只有离谱的 8M。Li…

1-2亿条数据需要缓存,如何合理设计存储

单机是不可能的&#xff0c;肯定是分布式存储 数据怎么落&#xff1f; 一般业界有三种解决方案 哈希取余分区 一致性哈希算法分区 哈希槽分区&#xff08;大厂专用&#xff0c;都在用&#xff09;最终的选择