利用ESP32-S3和板载flash实现FATFS文件系统

利用ESP32-S3及其板载flash实现FATFS文件系统

前言

距离上一次更新,已经是很久远的事了,考研,秋招,让自己并没有过多的时间去更新文章,尽管在此期间,自己确实有积累一定的项目经验,但因为懒以及各种小项目的推进,导致更新计划屡屡搁浅。
目前,手头上的事情终于没有那么多了,自己也终于可以进行一些文章的更新了,希望可以给自己这个菜鸟带来一点点进步。
在这里插入图片描述

背景

最近入手了一块ESP32-S3-WROOM-2的板子,其板子上搭载了一块32MB的flash,我下意识就想着说,这么大的flash能不能跑个fafts,顺便可以给lvgl的图片显示提供支持,于是便有了这篇文章。
在这里插入图片描述

开发环境

vscode+idf

主要开发步骤

1.在例程的基础上进行修改
在这里插入图片描述
利用乐鑫idf提供的例程,我们可以很轻松的在上面进行修改,所以我们在示例项目中选择ext_flash_fafts这个例程去进行修改。
后续的改动也是按照这个例程去进行修改。

2.例程的相关代码进行修改
例程创建后,会发现烧录到板子上根本就没有办法正常使用,以及跟flash正常握手,这是一个很奇怪的现象。
其中有几个要去注意修改的点
第一个点就是,例程中所使用的引脚就是VSPI引脚,而很多时候,在实际的开发中,我们并不可能每一次都是用VSPI的引脚去进行对板载flash的握手,在大多数时候都是要进行修改的,而这次也不例外。
其主要的修改处如下所示:
在这里插入图片描述
上图中的修改处主要在于对总线配置引脚的结构体进行修改,治理需要结合自己的引脚去进行修改,其次就是host_id以及cs_id也要进行修改,一般来说前者应该是SPI1_HOST,而后者是一。
为什么?
在这里插入图片描述通过SPI1总线可以访问外部的flash,其次在SPI1总线的使用注意事项中也有提及这一事项
在这里插入图片描述可以从中获取到的信息就是,SPI1总线可以在设备跟flash或者psram中的数据缓存区去进行数据传输。

回到正题
第二个现象就是修改了管脚之后还是会出现问题,
其主要的错误现象如下图所示:
在这里插入图片描述

其主要的问题就在于flash的初始化问题,也就是例程中的example_init_ext_flash()函数,更准确来说,问题是出在ESP_ERROR_CHECK(spi_bus_initialize(VSPI_HOST, &bus_config, 1));这一条函数语句上,板子会不停的上电重启,其主要原因就是在于spi总线的初始化并不能顺利进行。
在这里插入图片描述

那我们应该怎么去修改??
主要的思路就是偷懒,如何理解?就是自己编写一个初始化的程序,但并不与其对应的错误检查函数进行配套使用。
具体的代码如下所示:

#define MOUNT_PATH "/storage/data"
static void initialize_filesystem(void)
{
    spi_flash_init();
    ESP_LOGE(TAG,"chip_size is (%d)",spi_flash_get_chip_size());
    static wl_handle_t wl_handle;
    const esp_vfs_fat_mount_config_t mount_config = {
        .max_files = 40,
        .format_if_mount_failed = true};
    esp_err_t err = esp_vfs_fat_spiflash_mount(MOUNT_PATH, "storage", &mount_config, &wl_handle);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
        return;
    }
}

上述代码中的MOUNT_PATH,需要与后续的文件系统分区去进行对应。
在主函数中,对应的初始化函数也要进行替换。

3.对例程进行添加和设置
很好理解,例程改完错,我们还要对自己的板子进行设置,毕竟搭载的flash大小和psram并不一致。

首先是进行flash的修改
在这里插入图片描述注意:是要在ESP-IDF Terminal 中输入idf.py menuconfig,而不是传统的CMD窗口中进行输入。
在这里插入图片描述在serial flash config中选择合适的flash大小,以及采样模式等等的参数

其次就是对分区表进行修改

从例程esp-idf\examples\system\console下面找到partitions_example.csv并刚才复制到工程文件夹下。
并且根据自己的需要,对于分区的大小进行修改。
在这里插入图片描述对上图的分区做出一点解释:
factory:是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。OTA 升级永远都不会更新 factory 分区中的内容.如果您希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
其次,fat就是我们的flash中搭载的fafts文件系统的占用空间的大小。
最后,我们可以不用写偏移地址,只需要需要的大小即可,系统会自动帮我们进行折算。

设置分区表
在这里插入图片描述
选用自己修改过后的分区表进行分区。

4.编写测试函数以及烧录程序和结果测试

主函数如下:

void app_main(void)
{

     initialize_filesystem();
    // // Print FAT FS size information 
   
    size_t bytes_total, bytes_free;
    example_get_fatfs_usage(&bytes_total, &bytes_free);
    ESP_LOGI(TAG, "FAT FS: %d kB total, %d kB free", bytes_total / 1024, bytes_free / 1024);
    FILE *f = fopen("/storage/data/hello.txt", "wb");
    // // Create a file in FAT FS
    ESP_LOGI(TAG, "Opening file");
     
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }
    fprintf(f, "this is a goddamn fafts %s\n", esp_get_idf_version());
    fclose(f);
    ESP_LOGI(TAG, "File written");

    // Open file for reading
    ESP_LOGI(TAG, "Reading file");
    f = fopen("/storage/data/hello.txt", "rb");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }
    char line[128];
    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);
  
}

主要目的在于创建文件,写入文件,读取文件,反馈对应的数据进行参考,具体就不做过多的解释了。

最后选择好对应的串口,型号,和下载方式即可。
在这里插入图片描述

结果测试

boot loader的打印
在这里插入图片描述对该分区表进行解释
flash从0x9000以前的区域,都是bootloader,用于esp32的启动。
而factory分区,我是分了5M的大小给他,具体的length计算方式为510241024=(hex)500000;
同理,对应的 storage分区,我分了25M给他,具体的length计算方式为2510241024=(hex)1900000;
初步验证成功。

最后通过日志打印查看结果,并且做出一定解释:
在这里插入图片描述
1.33554432:33554432/1024/1024=32,与flash的大小对的上。
2.25348kb即为24.75390625MB,大致与分区表设置相同。
3.文件内容的读写正常。

最后,你还可以更改名字,一样可以使用,只用调整对应的代码以及分区表名称即可。
例如:
在这里插入图片描述label处就变为了fatfs,更方便管理,提高了可读性。

**

综上所述,目标已经达到。

**

在这里插入图片描述
具体代码已开源。
https://gitee.com/kockpaiki/kockpaiki_esp32_est_flash_fafts.git

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要删除SD卡中的文件夹,需要使用FATFS文件系统提供的相关函数。以下是一个简单的例子,可以让你了解如何在STM32上使用FATFS文件系统删除SD卡中的文件夹。 首先,你需要初始化FATFS文件系统,包括挂载SD卡、打开文件夹等操作。下面是一个初始化FATFS的示例代码: ```c FATFS fs; FRESULT res; DIR dir; res = f_mount(&fs, "", 1); if (res != FR_OK) { // 处理挂载失败的情况 } res = f_opendir(&dir, "/folder_name"); if (res != FR_OK) { // 处理打开文件夹失败的情况 } ``` 上面的代码中,`f_mount`函数用于挂载FATFS文件系统,`f_opendir`函数用于打开指定的文件夹。 接下来,你可以使用`f_readdir`函数遍历文件夹中的所有文件和子文件夹,然后使用`f_unlink`函数删除子文件夹和其中的文件。下面是一个示例代码: ```c FILINFO fileInfo; while (f_readdir(&dir, &fileInfo) == FR_OK && fileInfo.fname[0] != 0) { if (fileInfo.fattrib & AM_DIR) { // 如果是子文件夹,则递归删除 if (strcmp(fileInfo.fname, ".") != 0 && strcmp(fileInfo.fname, "..") != 0) { char path[64]; sprintf(path, "/folder_name/%s", fileInfo.fname); res = f_unlink(path); if (res != FR_OK) { // 处理删除失败的情况 } } } else { // 如果是文件,则直接删除 char path[64]; sprintf(path, "/folder_name/%s", fileInfo.fname); res = f_unlink(path); if (res != FR_OK) { // 处理删除失败的情况 } } } ``` 上面的代码中,`f_readdir`函数用于读取文件夹中的文件信息,`f_unlink`函数用于删除文件或文件夹。在遍历文件夹时,需要忽略`.`和`..`两个特殊的文件夹。 最后,你可以使用`f_closedir`函数关闭文件夹,以释放相关资源: ```c f_closedir(&dir); ``` 这样,你就可以使用FATFS文件系统在STM32上删除SD卡中的文件夹了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kockpaiki

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值