搜索
bottom↓
回复: 0

《DNESP32S3使用指南-IDF版_V1.6》第三十八章 SPIFFS实验

[复制链接]

出0入234汤圆

发表于 2024-7-29 17:44:41 | 显示全部楼层 |阅读模式
2.jpg
1)实验平台:正点原子ESP32S3开发板
2)购买链接:https://detail.tmall.com/item.htm?id=768499342659
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-347618-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子手把手教你学ESP32S3快速入门视频教程:https://www.bilibili.com/video/BV1sH4y1W7Tc
6)正点原子FPGA交流群:132780729
1.png
3.png

第三十八章 SPIFFS实验


       上一章实验中已经成功驱动SD卡,并可对SD卡进行读写操作,但读写SD卡时都是直接读出或写入二进制数据,这样使用起来显得十分不方便,因此本章将介绍SPIFFS,SPIFFS是一个用于SPI NOR flash设备的嵌入式文件系统,支持磨损均衡以及文件系统一致性检查等功能。通过本章的学习,读者将学习到SPIFFS的基本使用。
       本章分为如下几个小节:
       38.1 SPIFFS简介
       38.2 硬件设计
       38.3 程序设计
       38.4 下载验证

       38.1 SPIFFS介绍
       SPIFFS是一个用于嵌入式目标上的SPI NOR flash设备的文件系统,并且有如下特点:

       小目标,没有堆的少量RAM

       只有大范围的数据块才能被擦除

       擦除会将块中的所有位重置为1

       写操作将1置0

       0只能被擦除成1

       磨损均衡

       以上几点是SPIFFS的特点,下面则说明了SPIFFS具体能做些什么:

       专门为低ram使用而设计

       使用静态大小的ram缓冲区,与文件的数量无关

       类可移植操作系统接口:打开、关闭、读、写、查找、统计等

       它可以在任何NOR闪存上运行,不仅是SPI闪存,理论上也可以在微处理器的嵌入式闪存上运行

       多个spiffs配置可以在相同的目标上运行—甚至可以在相同的SPI闪存设备上运行

       实现静态磨损调平(也就是flash的寿命维护)

       内置文件系统一致性检查

       高度可配置的

       38.2 硬件设计

       38.2.1 例程功能

       1.在nor flash指定区域新建holle.txt文件,然后对这文件进行读写操作

       2. LED闪烁,指示程序正在运行

       38.2.2 硬件资源

       1. LED灯
              LED -IO0

       2. XL9555
              IIC_SDA-IO41
              IIC_SCL-IO42

       3. SPILCD
              CS-IO21
              SCK-IO12
              SDA-IO11
              DC-IO40(在P5端口,使用跳线帽将IO_SET和LCD_DC相连)
              PWR- IO1_3(XL9555)
              RST- IO1_2(XL9555)

       4. SPIFFS

       38.2.3 原理图
       本章实验使用的SPIFFS为软件库,因此没有对应的连接原理图。

       38.3 程序设计

       38.3.1 程序流程图
       程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:

第三十八章 SPIFFS实验1015.png
图38.3.1.1 IIC_EXIO实验程序流程图

       38.3.2 SPIFFS函数解析
       SPIFFS涉及到的文件并不算多,主要调用到了C库的函数,关于C库的函数我们在这里就不过多介绍了,主要介绍一下调用到ESP32 IDF库中的函数。

       1,注册装载SPIFFS
       该函数使用给定的路径前缀将SPIFFS注册并装载到VFS,其函数原型如下所示:
  1. esp_err_t esp_vfs_spiffs_register(const esp_vfs_spiffs_conf_t * conf);
复制代码
       该函数的形参描述,如下表所示:

1.png
表38.3.2.1 函数esp_vfs_spiffs_register ()形参描述

       该函数的返回值描述,如下表所示:

2.png
表38.3.2.2 函数esp_vfs_spiffs_register ()返回值描述

       该函数使用esp_vfs_spiffs_conf_t类型的结构体变量传入,该结构体的定义如下所示:

3.png
表38.3.2.3 esp_vfs_spiffs_conf_t结构体参数值描述

       完成上述结构体参数配置之后,可以将结构传递给esp_vfs_spiffs_register 函数,用以实例化SPIFFS。

       2,获取SPIFFS的信息
       该函数用于获取SPIFFS的信息,其函数原型如下所示:
  1. esp_err_t esp_spiffs_info(const char* partition_label,
  2.                                                    size_t *total_bytes,
  3.                                                    size_t *used_bytes);
复制代码
       该函数的形参描述,如下表所示:

4.png
表38.3.2.4 函数esp_spiffs_info ()形参描述

       该函数的返回值描述,如下表所示:

5.png
表38.3.2.5 函数esp_spiffs_info ()返回值描述

       3,注销和卸载SPIFFS
       该函数从VFS注销和卸载SPIFFS,其函数原型如下所示:
  1. esp_err_t esp_vfs_spiffs_unregister(const char* partition_label);
复制代码
       该函数的形参描述,如下表所示:

6.png
表38.3.2.6 函数esp_vfs_spiffs_unregister ()形参描述

       该函数的返回值描述,如下表所示:

7.png
表38.3.2.7 函数esp_vfs_spiffs_unregister ()返回值描述

       38.3.3 SPIFFS驱动解析
       在IDF版的27_spiffs例程中,作者在分区表中添加了SPIFFS的内容,27_spiffs \components\BSP路径下并无新的驱动文件增加。分区表内容如下:
  1. # ESP-IDF Partition Table
  2. # Name,     Type,     SubType,     Offset,     Size,     Flags
  3.   nvs,      data,     nvs,         0x9000,     0x6000,   ,
  4.   phy_init, data,     phy,         0xf000,     0x1000,   ,
  5.   factory,  app,      factory,     0x10000,    0x1F0000, ,
  6.   vfs,      data,     fat,         0x200000,   0xA00000, ,
  7.   storage,  data,     spiffs,      0xc00000,   0x400000, ,
复制代码

       38.3.4 CMakeLists.txt文件
       打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
  1. set(src_dirs
  2.             IIC
  3.             LCD
  4.             LED
  5.             SPI
  6.             XL9555)

  7. set(include_dirs
  8.             IIC
  9.             LCD
  10.             LED
  11.             SPI
  12.             XL9555)

  13. set(requires
  14.             driver
  15.             )

  16. idf_component_register(SRC_DIRS ${src_dirs}
  17. INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})

  18. component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
复制代码
       该例程驱动文件与依赖库并没有新的文件添加。

       38.3.5 实验应用代码
       打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
  1. i2c_obj_t i2c0_master;

  2. #define DEFAULT_FD_NUM          5
  3. #define DEFAULT_MOUNT_POINT     "/spiffs"
  4. #define WRITE_DATA              "ALIENTEK ESP32-S3\r\n"
  5. static const char               *TAG = "spiffs";

  6. /**
  7. * @brief       spiffs初始化
  8. * @param       partition_label:分区表的分区名称
  9. * @param       mount_point:文件系统关联的文件路径前缀
  10. * @param       max_files:可以同时打开的最大文件数
  11. * @retval      无
  12. */
  13. esp_err_t spiffs_init(char *partition_label,char *mount_point,size_t max_files)
  14. {
  15.     /* 配置spiffs文件系统各个参数 */
  16.     esp_vfs_spiffs_conf_t conf = {
  17.         .base_path = mount_point,
  18.         .partition_label = partition_label,
  19.         .max_files = max_files,
  20.         .format_if_mount_failed = true,
  21.     };

  22.     /* 使用上面定义的设置来初始化和挂载SPIFFS文件系统 */
  23.     esp_err_t ret_val = esp_vfs_spiffs_register(&conf);

  24.     /* 判断SPIFFS挂载及初始化是否成功 */
  25.     if (ret_val != ESP_OK)
  26.     {
  27.         if (ret_val == ESP_FAIL)
  28.         {
  29.             printf("Failed to mount or format filesystem\n");
  30.         }
  31.         else if (ret_val == ESP_ERR_NOT_FOUND)
  32.         {
  33.             printf("Failed to find SPIFFS partition\n");
  34.         }
  35.         else
  36.         {
  37.             printf("Failed to initialize  SPIFFS(%s)\n",esp_err_to_name(ret_val));
  38.         }

  39.         return ESP_FAIL;
  40.     }

  41.     /* 打印SPIFFS存储信息 */
  42.     size_t total = 0, used = 0;
  43.     ret_val = esp_spiffs_info(conf.partition_label, &total, &used);

  44.     if (ret_val != ESP_OK)
  45.     {
  46.         ESP_LOGE(TAG,
  47.            "Failed to get SPIFFS partition information(%s)",
  48.            esp_err_to_name(ret_val));
  49.     }
  50.     else
  51.     {
  52.         ESP_LOGE(TAG, "Partition size: total: %d, used: %d", total, used);
  53.     }

  54.     return ret_val;
  55. }

  56. /**
  57. * @brief       注销spiffs初始化
  58. * @param       partition_label:分区表标识
  59. * @retval      无
  60. */
  61. esp_err_t spiffs_deinit(char *partition_label)
  62. {
  63.     return esp_vfs_spiffs_unregister(partition_label);
  64. }

  65. /**
  66. * @brief       测试spiffs
  67. * @param       无
  68. * @retval      无
  69. */
  70. void spiffs_test(void)
  71. {

  72.     ESP_LOGI(TAG, "Opening file");
  73.     /* 建立一个名为/spiffs/hello.txt的只写文件 */
  74.     FILE* f = fopen("/spiffs/hello.txt", "w");

  75.     if (f == NULL)
  76.     {
  77.         ESP_LOGE(TAG, "Failed to open file for writing");
  78.         return;
  79.     }

  80.     /* 写入字符 */
  81.     fprintf(f, WRITE_DATA);

  82.     fclose(f);
  83.     ESP_LOGI(TAG, "File written");

  84.     /* 重命名之前检查目标文件是否存在 */
  85.     struct stat st;

  86.     if (stat("/spiffs/foo.txt", &st) == 0) /* 获取文件信息,获取成功返回0 */
  87.     {
  88.         /*  从文件系统中删除一个名称。
  89.             如果名称是文件的最后一个连接,并且没有其它进程将文件打开,
  90.             名称对应的文件会实际被删除。 */
  91.         unlink("/spiffs/foo.txt");
  92.     }

  93.     /* 重命名创建的文件 */
  94.     ESP_LOGI(TAG, "Renaming file");

  95.     if (rename("/spiffs/hello.txt", "/spiffs/foo.txt") != 0)
  96.     {
  97.         ESP_LOGE(TAG, "Rename failed");
  98.         return;
  99.     }

  100.     /* 打开重命名的文件并读取 */
  101.     ESP_LOGI(TAG, "Reading file");
  102.     f = fopen("/spiffs/foo.txt", "r");

  103.     if (f == NULL)
  104.     {
  105.         ESP_LOGE(TAG, "Failed to open file for reading");
  106.         return;
  107.     }

  108.     char line[64];
  109.     fgets(line, sizeof(line), f);
  110.     fclose(f);
  111.    
  112.     char* pos = strchr(line, '\n'); /* 指针pos指向第一个找到‘\n’ */

  113.     if (pos)
  114.     {
  115.         *pos = '\0';                /* 将‘\n’替换为‘\0’ */
  116.     }

  117.     ESP_LOGI(TAG, "Read from file: '%s'", line);
  118.     lcd_show_string(90, 110, 200, 16, 16, line, RED);
  119. }
复制代码
       在SPIFFS驱动中,首先初始化并挂载了一个SPIFFS分区,然后使用POSIX和C库API写入和读取数据。
  1. i2c_obj_t i2c0_master;
  2. /**
  3. * @brief       程序入口
  4. * @param       无
  5. * @retval      无
  6. */
  7. void app_main(void)
  8. {
  9.     esp_err_t ret;
  10.     ret = nvs_flash_init();                                    /* 初始化NVS */
  11.     if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret==ESP_ERR_NVS_NEW_VERSION_FOUND)
  12.     {
  13.         ESP_ERROR_CHECK(nvs_flash_erase());
  14.         ret = nvs_flash_init();
  15.     }
  16.     ESP_ERROR_CHECK(ret);
  17.     led_init();                                                /* LCD初始化 */
  18.     i2c0_master = iic_init(I2C_NUM_0);                         /* 初始化IIC0 */
  19.     spi2_init();                                               /* SPI初始化 */
  20.     xl9555_init(i2c0_master);                                  /* XL9555初始化 */
  21.     lcd_init();                                                /* LCD初始化 */
  22.     spiffs_init("storage", DEFAULT_MOUNT_POINT, DEFAULT_FD_NUM);/*SPIFFS初始化*/
  23.     /* 显示实验信息 */
  24.     lcd_show_string(10, 50, 200, 16, 16, "ESP32", RED);
  25.     lcd_show_string(10, 70, 200, 16, 16, "SPIFFS TEST", RED);
  26.     lcd_show_string(10, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  27.     lcd_show_string(10, 110, 200, 16, 16, "Read file:", BLUE);
  28.     spiffs_test();                                             /* SPIFFS测试 */
  29.     while (1)
  30.     {
  31.         LED_TOGGLE();
  32.         vTaskDelay(500);
  33.     }
  34. }
复制代码
       可以看到,本实验的应用代码中,在一系列初始化之后,配置spiffs文件系统各个参数,再建立一个名为/spiffs/hello.txt的只写文件,LED闪烁表明程序正在运行。

       38.4 下载验证
       在完成编译和烧录操作后,在指定区域新建hello.txt文件,然后对这文件进行读写操作。

第三十八章 SPIFFS实验8554.png
图38.4.1 程序运行效果图

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 06:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表