你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

SPIFFS文件系统移植–基于STM32F407

[复制链接]
wujique 发布时间:2018-6-3 22:44
本帖最后由 huangxuejia-29212 于 2018-6-3 22:47 编辑 7 m0 b; |6 d" m
" e7 f* o1 d8 J  D
SPIFFS文件系统,有什么特别呢?: D% _- W: t" j2 ]" h8 ?
从名字就可知,这是一个用于SPI FLASH的file system。
/ d) ^# N0 a* b5 o# G现在好像在ESP8266上用的很多,感觉慢慢有的人气了。
8 o8 O0 F' w1 D; n从特性上说,这个文件系统用很少的RAM资源。
7 Q' j5 S: \  m& z, T/ f. u但是,我最后会吐槽吐槽这个特性的。, R" {" l3 N# }8 T8 Y
网络上资源不多,好在github上说明文档挺全。
7 V3 A' W. x6 k) Y: I
github
地址:http://github.com/pellepl/spiffs+ ~# T/ \: }+ [! G1 a9 c
最新版本是0.3.7.1 _* o+ f+ v4 j% q* }
目录结构如下:
" G$ A- g0 f; h7 Z( Y
" o! I0 R' a# C) I添加到工程的文件如下:
- T2 d8 o% o: B1 _6 m0 r
在github上有wiki说明如何移植
3 k8 N3 N' ^( r& @http://github.com/pellepl/spiffs/wiki8 |! d* L& f, Y4 F5 Z
认真读完这个wiki,基本就知道如何使用spiffs。( ]2 R5 b8 H3 c* f
对于spiffs的设计,有一个网站可做参考, spiffs技术手册。8 y& F% b* v" D" L; A
http://blog.csdn.net/zhangjinxing_2006/article/details/75050611
+ P- W# ?5 @$ T6 d8 a2 v( I
移植概述
2 u/ P  w- z1 V: a% H
下面我们说说移植的过程。; [' ^& z! E  W6 F8 @
1. 配置1 N! L% X3 m1 `) A  |
spiffs-0.3.7\src\default下有一个默认的配置文件,spiffs_config.h。" D$ w& K3 K, [2 i  u; [
为了方便,拷贝一个到spiffs-0.3.7\src。
6 \! Q: A  h' r在工程中,头文件搜索路径,只包含src路径,不要包含\src\default。
( U: _3 z: }! R. C  _. S4 z3 Qspiffs_config.h头部包含的头文件修改如下。
* ]# D$ `- S( \; Y' ^9 @在这里也定义了变量名。
  1. //#include <stdio.h>
    ! a, S" u- i& A, x/ X2 O4 [# N
  2. #include <stdlib.h>
    ' v7 A2 c4 n8 }8 |- Q) U0 d8 E
  3. #include <string.h>  {0 @& U9 a: a
  4. #include <stddef.h>
    3 R/ u+ w  Q3 I3 w3 r
  5. #include "stm32f4xx.h"
    " z+ \  h1 G  U8 W  P
  6. 8 |9 R% L2 H# y9 U
  7. typedef u32  u32_t;
    ) g  Y5 L, a, b; ?! \) [0 h
  8. typedef u16 u16_t;
    5 q+ ~8 X* L/ O& E
  9. typedef u8  u8_t;5 Z) I& J- b$ A

  10. 3 y- C* P3 q9 `
  11. typedef s32  s32_t;5 s9 A& ?! x$ {) }( m3 {+ v
  12. typedef s16 s16_t;+ @+ U% h9 A- c4 ~, Y8 e8 j
  13. typedef s8  s8_t;
复制代码

. Z: q1 P- L& a* s3 U- t
修改几个宏定义
  1. #ifndef SPIFFS_USE_MAGIC7 P+ w# ]/ z1 w' [9 N3 q
  2. #define SPIFFS_USE_MAGIC                (1), }; h6 n. ^2 V  ?/ O, J$ P
  3. #endif, n+ n7 l! f+ d3 G- U. r

  4. 7 H* R: E! _" s7 H7 u$ M0 M
  5. #ifndef SPIFFS_USE_MAGIC_LENGTH
    ; p, A3 G6 Z5 ]* `: Q  j; x
  6. #define SPIFFS_USE_MAGIC_LENGTH         (1)/ o) u# ]" ]2 d$ O  w% O
  7. #endif* ~2 K+ O, W, T" e2 ?
  8. #endif
复制代码
2 k% D& E) x) R3 e% [  \
在spiffs-0.3.7\src\spiffs_nucleus.h文件中定义的联合用了一个gcc特性,在MDK编译会报错。
8 i) Q! y& m& q9 A. ^在联合前增加一句代码#pragma anon_unions 即可。
  1.   0 |+ k7 u4 M% M8 {
  2.   #pragma anon_unions
    ( B3 m+ y, o* e
  3.   union {; v# i: c2 b; {- b6 S2 k; L
  4.     // type read cache
    . o0 O8 R4 m& U  x- k" t$ a9 s7 S
  5.     struct {1 l. V. u  s2 k, c" Z, U. b
  6.       // read cache page index- W) _9 A; P8 G& w6 `# N
  7.       spiffs_page_ix pix;* [4 g: y% o  l# }' D
  8.     };9 q; v4 C# }; @
  9. #if SPIFFS_CACHE_WR: E1 M0 Y5 I% `: E: T9 ?2 ]
  10.     // type write cache3 B/ V- i6 i9 {! y/ r* \
  11.     struct {
    + r7 z- D2 y4 w, M
  12.       // write cache1 \9 P0 G* V9 ]# y5 W) }5 G6 ]8 G
  13.       spiffs_obj_id obj_id;
    : G( m! c% g: s) i! R0 {
  14.       // offset in cache page1 C* D: W0 Q; P: J; t: b
  15.       u32_t offset;
    ' e) R% A# I/ u& Z
  16.       // size of cache page
    2 \0 C, c+ v- x
  17.       u16_t size;; D2 h( D3 z7 Z# ?) i# P
  18.     };' [8 N/ ^+ Y) _$ C: H& G* G
  19. #endif
    9 P/ e: K  Z. I2 Q0 B
  20.   };& ~+ F  Y3 D4 l/ E4 d$ ~* R: k
  21. } spiffs_cache_page;
复制代码

0 f9 Q4 Q1 ]' @) C
2 应用
, Y% ?$ U/ D- k6 B) K) ]) }, d6 h首先,
* F2 f; g# B& O- l要实现SPI FLASH操作函数,SPIFFS需要的函数格式如下
  1. s32_t core_spiflash_spiffs_read(u32_t addr, u32_t size, u8_t *dst);
    ! Z: h5 f5 f) h
  2. static s32_t core_spiflash_spiffs_write(u32_t addr, u32_t size, u8_t *src);
    ; o  N% b5 k! Q" ]6 u
  3. static s32_t core_spiflash_spiffs_erase(u32_t addr, u32_t size);
复制代码

7 Y$ h) Z+ Q2 L8 o
第二,& f0 Q  f- U2 c9 r+ s. u
定义文件系统相关参数
  1. /*
    ) U3 z. }3 I) h
  2.         文件系统配置: |8 x& m# r$ N3 Y; V, r6 [
  3.        
    / T# B! ^: o# V$ j0 C* Q
  4.         #define SPIFFS_SINGLETON (0) 这个宏配置为0,也就是支持多个spiffs
    & h: a& K5 C3 }& x; W' r
  5. */: V7 w) l* G% ^' N/ d+ s
  6. spiffs_config cfg=/ A$ T  |$ \% ^7 L
  7.         {        % N( F9 Z4 ~2 v+ r7 f; [" n9 k) h9 z; D$ G
  8.                 /* 分配给SPIFFS的空间 要是逻辑扇区的整数倍*/- f3 ?! Z1 m" ^% [
  9.                 .phys_size = 1024*4*4*128,* s; \: G+ Y8 i4 Z
  10.                 /* 起始地址 */. ?$ j: N' a# C  V% {$ D7 F
  11.                 .phys_addr = 0,
    ! D$ i. C  f7 @+ \& Z( n
  12.                 /*
    9 m7 |  k" Y4 L
  13.                         物理扇区,也就是一次擦除的大小,要跟hal_erase_f函数擦除的一致
    , [. F2 j  u2 D
  14.                 */
    8 ]  G: A, B; S9 J- s
  15.                 .phys_erase_block = 1024*4, . v/ V5 _8 O7 R: N- b* M
  16.                 /* 逻辑扇区,必须是物理扇区的整数倍
    ! A& F3 S. F: c2 R
  17.                         最好是: log_block_size/log_page_size = (32-512). c% d, P! _  s% I) m- {
  18.                 */, m* z6 V3 a. i+ d2 s
  19.                 .log_block_size = 1024*4*4,
    8 i5 i- _* t' A2 |& o
  20.                 /*逻辑页,通常是256*/. C3 d5 K" l. }2 j" q
  21.                 .log_page_size = LOG_PAGE_SIZE, 7 X' }* `  v# P  n1 D
  22.                
    7 {! ^/ y3 u* W% K; g6 `0 q( O
  23.                 .hal_read_f = core_spiflash_spiffs_read,
    / }' A' l: A$ q* @
  24.                 .hal_write_f = core_spiflash_spiffs_write,
    + l: W) @& Y5 y8 n7 V6 S
  25.                 .hal_erase_f = core_spiflash_spiffs_erase,; D; p% b  E0 N9 @! [  x
  26.        
    ' {( n2 h" d% t# p% h
  27.         };
复制代码
5 d% Y. h- ^1 r) G, }2 @6 \
第三,* M1 t4 H+ [; t4 g; V( n! x
挂载文件系统,如果是第一次挂载会失败,需要卸载文件系统再格式化文件系统,最后重新挂载即可。
  1. /*文件系统结构体*/3 m4 y+ Q, ^6 I
  2. static spiffs fs;
    " I8 ~! ^: F+ T* V8 _: p
  3. % K# C2 F( Q' h: x# |. f
  4. /*页定义*/- t  x/ o/ W5 u- y2 c( K1 ]7 j/ y
  5. #define LOG_PAGE_SIZE                256
    3 A. ^- t" ^/ S/ ?- x9 v4 C1 P

  6. + m* k+ h- ?# l+ x5 U8 o/ l
  7. static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];: E3 p# n3 Z3 s
  8. static u8_t spiffs_fds[32*4];
    6 g" P( A. L* t8 r' j- x% u
  9. static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];0 z- M0 p! j9 Y

  10. 3 g( {4 l& }( h
  11. /**
    % U; l$ G. B# p5 A& f& R
  12. *@brief:     
    ( Q2 V1 D+ x  R7 O* i, v0 u9 w. {
  13. *@details: 格式化文件系统# z8 i( F& _+ }3 G! Z
  14. *@param[in]   
    9 m: ?! r, Z  z6 }# M8 Q0 z# U
  15. *@param[out]  ) ~2 a$ g* M# S1 f5 Q* L. C" j
  16. *@retval:     
    9 x$ x6 a) D+ S$ M) i" t3 \
  17. */
    7 ^+ |$ E  B8 n- U* L& Z
  18. void sys_spiffs_format(void)
    3 h) x* {5 m% z  a* {+ w
  19. {
    8 F8 h8 g) P5 \; l" \) O5 z: J

  20. 0 D/ p7 f: p; G% @7 z2 u- z
  21.         wjq_log(LOG_INFO, ">---format spiffs coreflash\r\n");+ R$ g$ H7 N  e: M! `( H

  22. . T/ P* \, r/ d: e1 s
  23.         /* 格式化之前要先unmount */
    $ w4 N5 t4 n. Y( m9 t
  24.         SPIFFS_unmount(&fs);
    $ B3 J& O. ]4 @- O
  25.                        
    + q# i2 O4 W( Z& s6 N- }
  26.         SPIFFS_format(&fs);
    7 u' y7 |5 n. f

  27. , u  n2 p  s# X- x4 G
  28.         int res = SPIFFS_mount(&fs,6 a3 _% t% J& I% D8 F1 M  b
  29.           &cfg,/ L3 r" U# N1 l! u" q% \9 f3 |
  30.           spiffs_work_buf,
    : h( e9 x( g* V/ L& f2 ^
  31.           spiffs_fds,
    5 B& H' x7 U2 W4 O
  32.           sizeof(spiffs_fds),# Y+ z/ H, @: K# ?
  33.           spiffs_cache_buf,
    ' `9 Y) G- Q. Z
  34.           sizeof(spiffs_cache_buf),
    3 x8 x0 g% \+ o' h1 n
  35.           0);$ P; w+ C0 B1 U8 e2 C/ B( s
  36.         wjq_log(LOG_INFO, "mount res: %i\r\n", res);: v/ `! e+ v- U+ U0 V3 {$ N
  37.         . @# I  }% ?5 |
  38.         wjq_log(LOG_INFO, ">---format spiffs coreflash finish\r\n");
    $ _, q) B/ G7 n8 U8 @! R

  39. 0 e& i; c* L7 H; N* P6 f* t7 y7 ]
  40. }
    6 y8 n, Z/ }  ]/ z! v  q2 \3 f
  41. /**# ?7 F( w- B7 {0 a$ x* ^
  42. *@brief:     
    . m' Z% I$ U. w2 g" s0 O
  43. *@details: 挂载spiffs文件系统
    1 h6 P# m# m7 v" m* K$ Y
  44. *@param[in]   
    % i2 k( e+ K7 c& n
  45. *@param[out]  " {( R! W1 O3 A$ d
  46. *@retval:     9 R. z7 Q: o2 R3 w' C
  47. */
    % `& W5 U6 o: G9 i
  48. void sys_spiffs_mount_coreflash(void)
    5 d5 G) ~0 h: u5 f7 i; l
  49. {
    ' J$ d# f6 I4 h6 i: `( F( c
  50.     int res = SPIFFS_mount(&fs,
    " u+ q5 M* u4 s" K: w1 E
  51.                                                       &cfg,
    , w# [( }6 o9 Z/ `! z! _8 h
  52.                                                       spiffs_work_buf,
    , u- p, o& Q. J
  53.                                                       spiffs_fds,
    2 U$ Y3 |: @" C) _% d
  54.                                                       sizeof(spiffs_fds),2 I9 E( Q& a) O8 r
  55.                                                       spiffs_cache_buf,6 W: d* A, o/ b4 ]
  56.                                                       sizeof(spiffs_cache_buf),4 ]4 X% D& P8 q. ^3 Z
  57.                                                       0);
    8 h) C6 k% e: c" j& L
  58.     wjq_log(LOG_INFO, "mount res: %i\r\n", res);
    / l. A' b, o5 T" b. Q* p: m9 @

  59. ) c+ }6 H9 i' K0 l, K
  60.         if(SPIFFS_ERR_NOT_A_FS == res )
    9 @. L! g, _+ Z1 |( ?( V( q5 Y
  61.         {
    * V: G& P. C3 ?
  62.                 sys_spiffs_format();       
    " L7 g( g6 D2 c7 g1 ^
  63.         }* v$ M7 {* o( C: }2 o
  64. }
复制代码

8 o, l9 |: {# C4 ?( K
然后,就可以进行基本读写测试啦。
/ z7 |8 {6 V+ f
吐槽
4 O. f. d' D: x* O) @
11 U% b4 A% K8 G: ^' `; F" k$ G
如果要好好用这个文件系统,需要多次测试找一个设置平衡点。3 a% V) N' V0 G8 {. X$ b" M
什么意思呢?也就是你这个文件系统如何配置。( w. H9 \! @- u8 |6 |6 A( N, v
也就是spiffs_config中的:逻辑块多大,页设置多大。不同的设置会严重影响性能。" H2 Y# r, W% ^* U6 D
因为这个文件系统为了省内存,没有任何索引。
6 ~' h" ~4 e0 K* Y具体细节大家自己分析,我就说一个事实:
打开一个文件,很可能要轮询所有BLOCK的第一页。
. H3 H2 r& t: O. T; }当你BLOCK跟页设置小,数量就多,操作文件就会很慢很慢,,,,。1 ?+ P( a% ~3 j% w
为什么这么慢?作者在WIKI上有说明。
2
4 X/ X. v% c' T$ q9 Z8 c" j7 N$ r  F目前还没有认真使用这个文件系统,但是总感觉它有点上不成下不就的感觉。0 x% f& |( P9 {
是的,嵌入式RAM紧张,但是嵌入式对速度也敏感啊!$ Z! ]# `" ^, T7 p3 d  x0 ~" W
想起以前公司用的文件系统,速度不慢,RAM用得也不算多。
% J4 h2 b& Y; u: n怎么做到呢?
0 G3 ^& d2 y- L& ^/ S# z限制其他性能,例如,最多只能创建100个文件,文件系统最大只能到1M。! z8 d( q. A! c& L7 M
这样的限制对于单片机系统来说,其实是能用的。: P! X6 C8 ]) I/ \9 }* n; |
(带这个文件系统的产品估计出货也1000万台了吧)
+ E1 F4 Z. P, R9 x
移植源码
& U* B9 t& y2 b+ u
在开源STM32代码上有这个文件系统的移植,需要请参观:& x; d8 Y. ~' D( x; C; T! \
http://github.com/wujique/stm32f407/tree/sw_arch
这个仓库是个人写的一些代码,主要是按照经验进行了一些程序设计,自认为比大部分教程的例程代码要好。2 P3 d5 w/ b* b6 Y3 J
后续会慢慢添加各种外设驱动。大家拿来用即可。# X  m  I# N. p/ r8 \/ G$ Z; U7 ^, x
欢迎商用,后果自负

8 t, u* }  m- r
5 H2 J1 y" P' |2 e- y

评分

参与人数 1 ST金币 +6 收起 理由
MrJiu + 6 很给力!

查看全部评分

收藏 4 评论6 发布时间:2018-6-3 22:44

举报

6个回答
MrJiu 回答时间:2018-6-4 09:49:03
很好啊!!!有时间阅读一下!!!看起来不错。。。
勿忘心安110 回答时间:2018-6-26 08:45:07
感谢楼主分享 有空去拜读一下代码
gaokai1992yy 回答时间:2018-9-26 09:41:06
谢谢,正好最近在看这个东西
streamlee 回答时间:2020-4-20 15:20:59
最近要上这个文件系统,参考
李康1202 回答时间:2020-4-23 08:49:20
谢谢分享
3 S" {( N+ P" a4 p, e3 P
david69chen 回答时间:2020-5-14 04:12:31
very good!
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版