SPIFFS文件系统移植–基于STM32F407

http://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=616126&highlight=%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F

 

本帖最后由 huangxuejia-29212 于 2018-6-3 22:47 编辑
 

SPIFFS文件系统,有什么特别呢?
从名字就可知,这是一个用于SPI FLASH的file system。
现在好像在ESP8266上用的很多,感觉慢慢有的人气了。
从特性上说,这个文件系统用很少的RAM资源。
但是,我最后会吐槽吐槽这个特性的。
网络上资源不多,好在github上说明文档挺全。

 

github

地址:https://github.com/pellepl/spiffs
最新版本是0.3.7.
目录结构如下:

添加到工程的文件如下:

在github上有wiki说明如何移植
https://github.com/pellepl/spiffs/wiki
认真读完这个wiki,基本就知道如何使用spiffs。
对于spiffs的设计,有一个网站可做参考, spiffs技术手册。
https://blog.csdn.net/zhangjinxing_2006/article/details/75050611


移植概述

下面我们说说移植的过程。
1. 配置
spiffs-0.3.7\src\default下有一个默认的配置文件,spiffs_config.h。
为了方便,拷贝一个到spiffs-0.3.7\src。
在工程中,头文件搜索路径,只包含src路径,不要包含\src\default。
spiffs_config.h头部包含的头文件修改如下。
在这里也定义了变量名。

  1. //#include
  2. #include
  3. #include
  4. #include
  5. #include "stm32f4xx.h"
  6.  
  7. typedef u32  u32_t;
  8. typedef u16 u16_t;
  9. typedef u8  u8_t;
  10.  
  11. typedef s32  s32_t;
  12. typedef s16 s16_t;
  13. typedef s8  s8_t;

复制代码

 

修改几个宏定义

  1. #ifndef SPIFFS_USE_MAGIC
  2. #define SPIFFS_USE_MAGIC                (1)
  3. #endif
  4.  
  5. #ifndef SPIFFS_USE_MAGIC_LENGTH
  6. #define SPIFFS_USE_MAGIC_LENGTH         (1)
  7. #endif
  8. #endif

复制代码

 

在spiffs-0.3.7\src\spiffs_nucleus.h文件中定义的联合用了一个gcc特性,在MDK编译会报错。
在联合前增加一句代码#pragma anon_unions 即可。

  1.   
  2.   #pragma anon_unions 
  3.   union {
  4.     // type read cache
  5.     struct {
  6.       // read cache page index
  7.       spiffs_page_ix pix;
  8.     };
  9. #if SPIFFS_CACHE_WR
  10.     // type write cache
  11.     struct {
  12.       // write cache
  13.       spiffs_obj_id obj_id;
  14.       // offset in cache page
  15.       u32_t offset;
  16.       // size of cache page
  17.       u16_t size;
  18.     };
  19. #endif
  20.   };
  21. } spiffs_cache_page;

复制代码

 

2 应用
首先,
要实现SPI FLASH操作函数,SPIFFS需要的函数格式如下

  1. s32_t core_spiflash_spiffs_read(u32_t addr, u32_t size, u8_t *dst);
  2. static s32_t core_spiflash_spiffs_write(u32_t addr, u32_t size, u8_t *src);
  3. static s32_t core_spiflash_spiffs_erase(u32_t addr, u32_t size);

复制代码

 

第二,
定义文件系统相关参数

  1. /*
  2.         文件系统配置
  3.         
  4.         #define SPIFFS_SINGLETON (0) 这个宏配置为0,也就是支持多个spiffs
  5. */
  6. spiffs_config cfg=
  7.         {        
  8.                 /* 分配给SPIFFS的空间 要是逻辑扇区的整数倍*/
  9.                 .phys_size = 1024*4*4*128,
  10.                 /* 起始地址 */
  11.                 .phys_addr = 0,
  12.                 /*
  13.                         物理扇区,也就是一次擦除的大小,要跟hal_erase_f函数擦除的一致
  14.                 */
  15.                 .phys_erase_block = 1024*4, 
  16.                 /* 逻辑扇区,必须是物理扇区的整数倍
  17.                         最好是: log_block_size/log_page_size = (32-512)
  18.                 */
  19.                 .log_block_size = 1024*4*4,
  20.                 /*逻辑页,通常是256*/
  21.                 .log_page_size = LOG_PAGE_SIZE, 
  22.                 
  23.                 .hal_read_f = core_spiflash_spiffs_read,
  24.                 .hal_write_f = core_spiflash_spiffs_write,
  25.                 .hal_erase_f = core_spiflash_spiffs_erase,
  26.         
  27.         };

复制代码

 

第三,
挂载文件系统,如果是第一次挂载会失败,需要卸载文件系统再格式化文件系统,最后重新挂载即可。

  1. /*文件系统结构体*/
  2. static spiffs fs;
  3.  
  4. /*页定义*/
  5. #define LOG_PAGE_SIZE                256
  6.  
  7. static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
  8. static u8_t spiffs_fds[32*4];
  9. static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];
  10.  
  11. /**
  12. *@brief:     
  13. *@details: 格式化文件系统
  14. *@param[in]    
  15. *@param[out]  
  16. *@retval:     
  17. */
  18. void sys_spiffs_format(void)
  19. {
  20.  
  21.         wjq_log(LOG_INFO, ">---format spiffs coreflash\r\n");
  22.  
  23.         /* 格式化之前要先unmount */
  24.         SPIFFS_unmount(&fs);
  25.                         
  26.         SPIFFS_format(&fs);
  27.  
  28.         int res = SPIFFS_mount(&fs,
  29.           &cfg,
  30.           spiffs_work_buf,
  31.           spiffs_fds,
  32.           sizeof(spiffs_fds),
  33.           spiffs_cache_buf,
  34.           sizeof(spiffs_cache_buf),
  35.           0);
  36.         wjq_log(LOG_INFO, "mount res: %i\r\n", res);
  37.         
  38.         wjq_log(LOG_INFO, ">---format spiffs coreflash finish\r\n");
  39.  
  40. }
  41. /**
  42. *@brief:     
  43. *@details: 挂载spiffs文件系统
  44. *@param[in]    
  45. *@param[out]  
  46. *@retval:     
  47. */
  48. void sys_spiffs_mount_coreflash(void) 
  49.     int res = SPIFFS_mount(&fs,
  50.                                                       &cfg,
  51.                                                       spiffs_work_buf,
  52.                                                       spiffs_fds,
  53.                                                       sizeof(spiffs_fds),
  54.                                                       spiffs_cache_buf,
  55.                                                       sizeof(spiffs_cache_buf),
  56.                                                       0);
  57.     wjq_log(LOG_INFO, "mount res: %i\r\n", res);
  58.  
  59.         if(SPIFFS_ERR_NOT_A_FS == res )
  60.         {
  61.                 sys_spiffs_format();        
  62.         }
  63. }

复制代码

 

然后,就可以进行基本读写测试啦。

 

吐槽

1
如果要好好用这个文件系统,需要多次测试找一个设置平衡点。
什么意思呢?也就是你这个文件系统如何配置。
也就是spiffs_config中的:逻辑块多大,页设置多大。不同的设置会严重影响性能。
因为这个文件系统为了省内存,没有任何索引。
具体细节大家自己分析,我就说一个事实:

打开一个文件,很可能要轮询所有BLOCK的第一页。
当你BLOCK跟页设置小,数量就多,操作文件就会很慢很慢,,,,。
为什么这么慢?作者在WIKI上有说明。

2
目前还没有认真使用这个文件系统,但是总感觉它有点上不成下不就的感觉。
是的,嵌入式RAM紧张,但是嵌入式对速度也敏感啊!
想起以前公司用的文件系统,速度不慢,RAM用得也不算多。
怎么做到呢?
限制其他性能,例如,最多只能创建100个文件,文件系统最大只能到1M。
这样的限制对于单片机系统来说,其实是能用的。
(带这个文件系统的产品估计出货也1000万台了吧)

 

移植源码

在开源STM32代码上有这个文件系统的移植,需要请参观:
https://github.com/wujique/stm32f407/tree/sw_arch

这个仓库是个人写的一些代码,主要是按照经验进行了一些程序设计,自认为比大部分教程的例程代码要好。
后续会慢慢添加各种外设驱动。大家拿来用即可。
欢迎商用,后果自负

你可能感兴趣的:(SPIFFS文件系统移植–基于STM32F407)