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

SPIFFS文件系统移植–基于STM32F407

[复制链接]
wujique 发布时间:2018-6-3 22:44
本帖最后由 huangxuejia-29212 于 2018-6-3 22:47 编辑 : r  {0 N) ~9 i9 J
/ }7 F- U+ r4 `$ ?6 w+ O
SPIFFS文件系统,有什么特别呢?
- e! O1 J$ g1 {! Z从名字就可知,这是一个用于SPI FLASH的file system。6 [- k0 m$ v# {4 X* D
现在好像在ESP8266上用的很多,感觉慢慢有的人气了。% l0 B  N( I+ ~+ v0 v# U( ~) o
从特性上说,这个文件系统用很少的RAM资源。
7 _9 d  @8 V) C, O. r. c但是,我最后会吐槽吐槽这个特性的。
+ V7 y% |; w+ P网络上资源不多,好在github上说明文档挺全。

; Y7 x7 }8 ~, l3 v. f6 ]' g
github
地址:http://github.com/pellepl/spiffs8 K" V: ?7 ?" A' @, O* w
最新版本是0.3.7.
) ], o: W: L. t# e6 V0 r3 [目录结构如下:
" b2 S# }6 G! w; l; P' Z: N9 ^, S% K1 c
添加到工程的文件如下:( J% u; x$ f+ _7 F% i
在github上有wiki说明如何移植
1 U+ u6 |1 u' k- f2 G7 n3 X! ?$ K% whttp://github.com/pellepl/spiffs/wiki
- [8 A9 u0 B1 z, W认真读完这个wiki,基本就知道如何使用spiffs。
% T2 X, }. }6 w2 a5 r对于spiffs的设计,有一个网站可做参考, spiffs技术手册。
# I2 t$ ?5 p5 U" `* i& Xhttp://blog.csdn.net/zhangjinxing_2006/article/details/75050611
: h% d, E7 @- |' C  K' N
移植概述

) v3 N( e- ?3 D3 Z) K, {7 e
下面我们说说移植的过程。
1 L5 o* k; t& f  k9 Y1. 配置
# S- ?  K" T: {* Q) Cspiffs-0.3.7\src\default下有一个默认的配置文件,spiffs_config.h。# v; K# ^8 I$ ~. d1 e5 r
为了方便,拷贝一个到spiffs-0.3.7\src。
) t1 Y' P2 E. L, T/ ~0 @) t6 R在工程中,头文件搜索路径,只包含src路径,不要包含\src\default。
+ Q3 s% p* T. Y; {. x0 }% t% q( v' hspiffs_config.h头部包含的头文件修改如下。; C8 ~7 I" _) S3 {+ H) d& ^
在这里也定义了变量名。
  1. //#include <stdio.h>6 z) E/ o/ Y8 Z9 q" {/ e; c
  2. #include <stdlib.h>( b" F% z6 w) B) [$ S
  3. #include <string.h>3 L5 q8 ]3 C- }0 y/ _& l
  4. #include <stddef.h>
    # [* R+ a' Y. f
  5. #include "stm32f4xx.h"& F. a2 @$ C# M: i  I. c8 F
  6. + @8 K: R6 q  G& ?- o
  7. typedef u32  u32_t;
    ( E, d: b9 p' o
  8. typedef u16 u16_t;
    1 z$ j* S: d( u1 u! M
  9. typedef u8  u8_t;
    - [- h4 ~3 L: l. T
  10. / N- `. f9 g8 `) l
  11. typedef s32  s32_t;* f1 W: B, D. {3 g2 n" Q- H- @
  12. typedef s16 s16_t;
    : d  B9 F# o* r; y" Q
  13. typedef s8  s8_t;
复制代码

7 E6 H9 ~! _$ M& H" Z$ d
修改几个宏定义
  1. #ifndef SPIFFS_USE_MAGIC* r& s& }+ O7 W: p
  2. #define SPIFFS_USE_MAGIC                (1)8 d( z' L/ s3 s* f% `* m+ j: T8 v& ~
  3. #endif2 o( S$ l" Z* n0 ~6 ?$ h& i

  4. & m! m0 k# S0 l4 h5 G
  5. #ifndef SPIFFS_USE_MAGIC_LENGTH0 g1 B4 f# h3 {. ?# v
  6. #define SPIFFS_USE_MAGIC_LENGTH         (1)
    8 W! W5 O5 A. b  v
  7. #endif
    ) G# z- w6 y3 n2 n8 Q- ~, C1 l3 w
  8. #endif
复制代码
$ w5 `0 A) G# a0 y  j* i
在spiffs-0.3.7\src\spiffs_nucleus.h文件中定义的联合用了一个gcc特性,在MDK编译会报错。
5 K% Y; R  m# v, }在联合前增加一句代码#pragma anon_unions 即可。
  1.   
    " [( D" f9 X- Q: e. p" p; m- F  [2 S
  2.   #pragma anon_unions ) T+ y( R2 r. s
  3.   union {5 l+ H" C' S) j+ p( ]  h
  4.     // type read cache8 h8 O2 Z, j- M! o
  5.     struct {) M, j& {, h2 ?& i5 `: G! R, i" @
  6.       // read cache page index$ }4 s/ v2 Z1 t5 T- p/ V2 A
  7.       spiffs_page_ix pix;
    7 d/ L$ p: s; {  `# {  ?
  8.     };7 o* F9 h0 g- ~- V4 F& |% c
  9. #if SPIFFS_CACHE_WR* {% I& C9 M2 Q4 j8 h
  10.     // type write cache
    % R( h4 p; i: q5 t
  11.     struct {
    & C; Q$ T; w( I- S# c# V
  12.       // write cache! m, q4 S0 ~- q9 X
  13.       spiffs_obj_id obj_id;# J/ ?* b# G, b0 ^3 p/ t2 v1 x0 Y
  14.       // offset in cache page
    : }- u$ ~$ ^6 u) {3 _7 o
  15.       u32_t offset;
    9 j# O2 Q: B# }  H
  16.       // size of cache page
    4 n3 k' w! c3 u% [
  17.       u16_t size;
    ; V$ T0 O$ o- S6 y: n0 c
  18.     };
    # {9 ^# c' @8 [
  19. #endif
    ! C7 X! c' D8 O, C3 Y  Z  ^
  20.   };- s" |& X! x& N; W
  21. } spiffs_cache_page;
复制代码

; S5 l4 G6 x# Y/ T; N: s- c
2 应用
! t! F3 m2 C) W首先,
  n; D" ^! w2 z* p要实现SPI FLASH操作函数,SPIFFS需要的函数格式如下
  1. s32_t core_spiflash_spiffs_read(u32_t addr, u32_t size, u8_t *dst);
    1 o1 n2 b% i/ L5 v* h! P3 c
  2. static s32_t core_spiflash_spiffs_write(u32_t addr, u32_t size, u8_t *src);8 F" ~; n+ I& F) \. R8 N
  3. static s32_t core_spiflash_spiffs_erase(u32_t addr, u32_t size);
复制代码

. Y' k: c7 J- f& P5 k
第二,
4 q3 B3 j: s* v, N8 |$ s定义文件系统相关参数
  1. /*
    " F3 x6 j4 H0 ]0 R
  2.         文件系统配置4 S, T- E$ k1 |) m
  3.         ! v8 j; a2 U0 F
  4.         #define SPIFFS_SINGLETON (0) 这个宏配置为0,也就是支持多个spiffs
    * p+ B& @1 Z, O
  5. */( Z: g; [% Q, `1 Z6 {- k* H
  6. spiffs_config cfg=% `8 K& S- f5 v! e, c
  7.         {       
      A8 Z7 r4 X, ~4 N4 B$ D8 F
  8.                 /* 分配给SPIFFS的空间 要是逻辑扇区的整数倍*/, M1 q0 _/ ~* s- ^% P& H
  9.                 .phys_size = 1024*4*4*128,' w( i: T$ f0 A! O, [/ {. Q
  10.                 /* 起始地址 */
    , J+ W1 V/ v* i6 b; Q3 g4 O
  11.                 .phys_addr = 0,
    & O! {* V, P& ^, m2 A+ u
  12.                 /*8 h' {# X- f" R4 J4 o0 i9 M
  13.                         物理扇区,也就是一次擦除的大小,要跟hal_erase_f函数擦除的一致
    8 v/ t+ y0 \( u8 O/ h
  14.                 */
    0 L3 z/ R4 u' d8 B4 r
  15.                 .phys_erase_block = 1024*4,
    $ o8 P# M6 ]5 f. B' v& S& N) X9 [. X
  16.                 /* 逻辑扇区,必须是物理扇区的整数倍
    9 r8 W6 R$ a7 y; o* y4 Y& ?
  17.                         最好是: log_block_size/log_page_size = (32-512)+ W9 i7 z! V& q+ g: K
  18.                 */. c3 q5 u9 v1 _
  19.                 .log_block_size = 1024*4*4,
    : u2 s, a% Q+ H6 b
  20.                 /*逻辑页,通常是256*/9 Z+ |2 O2 R+ P: m7 D- a) a
  21.                 .log_page_size = LOG_PAGE_SIZE, 4 F/ t2 @" W0 D; O7 T- o
  22.                
    7 {7 ^6 l$ y% m/ D
  23.                 .hal_read_f = core_spiflash_spiffs_read,* w; p7 u; P5 S" ?3 p
  24.                 .hal_write_f = core_spiflash_spiffs_write,! {" q8 S# x8 V  f" ]& Z1 O# `
  25.                 .hal_erase_f = core_spiflash_spiffs_erase,% f  ^4 b2 @( d) T( @# @
  26.         / z* P# H. K" o6 u9 h
  27.         };
复制代码
1 y4 p* |" O; [# [, C4 q9 {' C
第三,
4 ~; d8 n  ~9 j  g2 v, E4 K1 L$ p挂载文件系统,如果是第一次挂载会失败,需要卸载文件系统再格式化文件系统,最后重新挂载即可。
  1. /*文件系统结构体*/
    % O- c, n% x0 M7 _1 h1 s* q
  2. static spiffs fs;
    . m7 y9 `6 E1 n. R% h& H7 I

  3. 9 p  h  Z. S$ S
  4. /*页定义*/( D* i5 R* B7 G
  5. #define LOG_PAGE_SIZE                256! `: m9 V; Q/ P) c- v
  6. : m$ p1 U8 I: R1 _/ q( {. T1 r% ]
  7. static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];% _2 Z) D. V- w
  8. static u8_t spiffs_fds[32*4];8 C  m5 ~: z. K5 X% b- ]
  9. static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];
    ! t: i0 f" I. z

  10. 8 @' D8 b, s& U8 m2 C; M
  11. /**7 ^) l% U# o$ v& |9 _& Z
  12. *@brief:     ) k1 c: N0 L) k, U
  13. *@details: 格式化文件系统/ U9 N4 I, I# n
  14. *@param[in]   
      J6 [* w) T, A
  15. *@param[out]  
    6 n& |, Z( Y2 w0 Z/ B
  16. *@retval:       N! E: z# l1 {- G$ J
  17. */- {1 M. W  F# y8 l# B5 i
  18. void sys_spiffs_format(void)
    & Y# m: A/ Q4 j, i4 {$ O
  19. {( E2 }6 y! _; b+ y- F# U

  20. - y( B! C2 D5 f3 w8 k# s" N
  21.         wjq_log(LOG_INFO, ">---format spiffs coreflash\r\n");6 W' Z% L, }- g8 l- j% b: v

  22. , y+ g$ R) @+ L9 S5 ?* ^# f
  23.         /* 格式化之前要先unmount */
    6 {2 N- C# x' w5 |% M2 l
  24.         SPIFFS_unmount(&fs);6 u7 M( d& x. ^- h: ^' t
  25.                        
    & D- g6 u) J8 u5 j
  26.         SPIFFS_format(&fs);. n& X, y' S- u; ?4 ?
  27. ' V* k: P1 T2 x+ ]+ j% t
  28.         int res = SPIFFS_mount(&fs,
    / z5 u, O' O3 k  P! F7 Q5 O
  29.           &cfg,
    2 {3 ~0 a8 @# F+ a# q/ W9 r
  30.           spiffs_work_buf,
    + \+ d9 P2 O$ ]5 a* f- O3 C7 f
  31.           spiffs_fds,' [+ j: A/ ]" \/ B1 S
  32.           sizeof(spiffs_fds),
    8 u# k/ U+ J* G3 d# T5 v$ R+ s9 a
  33.           spiffs_cache_buf,) U0 u6 g6 y9 i3 H0 H- Q$ v
  34.           sizeof(spiffs_cache_buf),
    ) H" j- M4 K3 \) b
  35.           0);
      o% Q0 \! c6 a- n  i* {* l
  36.         wjq_log(LOG_INFO, "mount res: %i\r\n", res);3 I% |4 I. m" G
  37.         + f& u* |7 E2 S* K
  38.         wjq_log(LOG_INFO, ">---format spiffs coreflash finish\r\n");6 a# D- w! i% F' a. s: \, X/ ~

  39. " A/ C: a! B, F+ B5 N: d' a9 M) [
  40. }
      v% `6 ~9 x# G" \( l( N- h
  41. /**
    % E/ T' V4 r- k" I. c- R1 R
  42. *@brief:     
    % Q( r8 o0 S+ S
  43. *@details: 挂载spiffs文件系统4 x  r+ ?- x% d& c. J# J* u' W
  44. *@param[in]    1 Y$ X0 K* J1 b7 ~. D! n9 d
  45. *@param[out]  1 W3 A5 ]$ f% s5 b+ f% h1 f% e
  46. *@retval:     
    7 O0 R/ i; ^! E1 U8 y
  47. */
    8 H2 M2 M, ^, I# o. B( k0 }
  48. void sys_spiffs_mount_coreflash(void) 7 b, N" o/ c( l
  49. { - f% U2 t  ?4 _9 Y
  50.     int res = SPIFFS_mount(&fs,
    : {% E7 `. \9 d5 b' T
  51.                                                       &cfg,2 i' Q6 i: a- }3 V
  52.                                                       spiffs_work_buf,
    : G% ^4 w2 Q7 w7 a/ [( N( z
  53.                                                       spiffs_fds,
    5 ]0 ^' r6 Q7 w9 x# K
  54.                                                       sizeof(spiffs_fds),. s, W, A' g1 _5 }" |
  55.                                                       spiffs_cache_buf,
      G- ?# }- I* W' @
  56.                                                       sizeof(spiffs_cache_buf),; M9 B$ g' i: e7 |+ z: F! E
  57.                                                       0);( M% i* e+ X0 `- t( }
  58.     wjq_log(LOG_INFO, "mount res: %i\r\n", res);
    5 E' |3 n4 A; }- J; p5 E
  59. 8 Z) i  B* n; m6 u, I9 I
  60.         if(SPIFFS_ERR_NOT_A_FS == res )/ ^! [' R' H. d% L% J! \' [
  61.         {
    / ~- G3 }4 C( E5 A- H, m
  62.                 sys_spiffs_format();        . ^: L: S# h8 s
  63.         }
    * u  q5 R3 d6 L) [2 a) a$ y3 o
  64. }
复制代码
, N& x" h0 v5 z1 e
然后,就可以进行基本读写测试啦。
( v! u' R  u. C* N3 ~
吐槽
! R7 z- O) G3 m: @' I# K7 c
1) C1 Z4 T. t) Y4 x' M/ w" F
如果要好好用这个文件系统,需要多次测试找一个设置平衡点。
9 b$ A% ]2 t8 X8 V什么意思呢?也就是你这个文件系统如何配置。
6 Y7 `* l$ H( P8 f也就是spiffs_config中的:逻辑块多大,页设置多大。不同的设置会严重影响性能。
5 N9 J, L* t6 a$ ]# h* p% @) q3 N因为这个文件系统为了省内存,没有任何索引。
" R5 Y. q/ c+ D* `4 `7 ?" ^' N3 O具体细节大家自己分析,我就说一个事实:
打开一个文件,很可能要轮询所有BLOCK的第一页。
% }, L1 R& {% E7 |. M& R7 t当你BLOCK跟页设置小,数量就多,操作文件就会很慢很慢,,,,。1 Y4 b) K8 V5 s; e% a2 G9 h, ]
为什么这么慢?作者在WIKI上有说明。
2
$ o7 v1 j, {3 P( [目前还没有认真使用这个文件系统,但是总感觉它有点上不成下不就的感觉。
4 t$ o9 N  Y; q, a7 @是的,嵌入式RAM紧张,但是嵌入式对速度也敏感啊!9 a: e+ r1 c: f4 q0 k: r
想起以前公司用的文件系统,速度不慢,RAM用得也不算多。# l6 y  E( H$ F9 I
怎么做到呢?0 c5 J1 U! V1 n+ K
限制其他性能,例如,最多只能创建100个文件,文件系统最大只能到1M。! Y! R! O4 z( l# X
这样的限制对于单片机系统来说,其实是能用的。
4 ~8 Q0 V/ V# D0 a4 {7 L(带这个文件系统的产品估计出货也1000万台了吧)
9 \* n- Q) h3 p4 S" K3 |
移植源码! ^$ s: B  c+ }- ^- s
在开源STM32代码上有这个文件系统的移植,需要请参观:
# w* K9 s3 h  m  p- N" Chttp://github.com/wujique/stm32f407/tree/sw_arch
这个仓库是个人写的一些代码,主要是按照经验进行了一些程序设计,自认为比大部分教程的例程代码要好。
& |" Z2 N/ g7 Y0 R* U3 C后续会慢慢添加各种外设驱动。大家拿来用即可。
( r5 i, [2 h4 @6 e欢迎商用,后果自负

$ o9 n7 n, p- R4 H. K3 o0 f2 {1 B7 [) [6 g1 E) I

评分

参与人数 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
谢谢分享
' q5 H( |1 d3 U9 l; m9 o5 g% }5 {
david69chen 回答时间:2020-5-14 04:12:31
very good!

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版