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

【经验分享】STM32 FatFs文件系统移植

[复制链接]
STMCU小助手 发布时间:2022-4-7 18:02
一、把FatFs源码拷贝到工程目录,此此移植文件系统是基于之前SPI_FLASH的工程下进行。
4 w- ^. |# n! p! l% b& _. p1 U+ h- E3 C# k# O) C
源码地址:Petit FAT File System Module。7 i3 M, A, S- ?$ ]5 Q/ C$ }
) E/ F5 d: y7 _, k1 c& Y( {5 O
FXOBFCJ3K9L[~4{9NOSOKW3.png
4 c( j: V( T5 Z# F# T2 c* V5 c) H0 v3 X, \$ |
二、在keil打开工程文件,将源码添加到工程中。
/ |0 [4 _7 }, [+ O/ I1 v' j' a. X2 c
SF[`BVY4XT4]PF(BKZ15RWV.png
( J& o0 o, {3 C+ I, f& M9 T/ H' H  M. f
三、添加FatFs源码的头文件。6 u& K# `4 H! ^
4 l- }- e# Z+ `
TIA[82}~T28`T_Y5`2]GXY7.png - s4 D. q6 n% N- C# N5 n4 [! G& w5 q
4 k* H/ |0 [0 [& A( j
四、尝试构建程序,解决错误。
" m& J6 Q% m' m+ j3 p  @7 {: k, J# L6 b3 d+ C- y7 J* L
        主要错误为函数未定义却使用了。可以进行删除,或者实现即可。
6 L" b' W8 T: S4 z8 ^* u$ D+ r& j$ p: o. ^& z) ?" z
五、实现FatFs底层驱动的接口。2 }7 U9 I6 G" N9 Q. G) t

, W' F8 c  m3 X- ma.disk_status  获取设备状态的接口。示例代码如下:
) L/ z( W1 x2 k) n( x3 q+ B) W3 y
( T% U: V5 r: w$ a* u6 I5 O- ^1 k
  1. DSTATUS disk_status (
    & E# B6 `4 z  u6 d( Q* }# U+ V
  2.         BYTE pdrv                /* Physical drive nmuber to identify the drive */
    5 T% B$ D; Y" K! x2 u! v: @2 k) B
  3. )
    , d4 u, [) M4 ~6 R7 z6 X4 G
  4. {
    . Y# {$ T' z: o) H
  5.         DSTATUS stat=STA_NOINIT;( \2 o5 ?. B- o
  6.         switch (pdrv) {( T/ l: v) a6 \0 ?5 ]
  7.         case DEV_FLASH :+ A; A2 J0 q  J5 y* q1 K
  8.                 {
    : H% I0 s4 V! o$ T5 |
  9.                     if(SPI_FLASH_ReadID()==sFLASH_ID)3 O6 i7 b* P3 R: Z+ u% w- f  w$ V
  10.                       stat&=~STA_NOINIT;: x% L" l+ a' c; }/ \$ R
  11.                     else) _6 P  k6 s/ y$ W- o  D
  12.                       stat=STA_NOINIT;
    ! j" S5 G7 G  a8 ?
  13.                 }8 T) k" N3 o1 M/ U8 d2 m+ T! L
  14.                 return stat;        - ?8 X. ^9 t/ n$ M& _
  15.         }8 _* G- h0 {# p  v2 I1 W
  16.         return STA_NOINIT;
    1 A  W, }6 ~1 o/ G
  17. }
复制代码

+ d" v; P" A0 b5 |/ @- T9 O% s6 _2 G& \$ k) W
b.disk_initialize 初始化设备的接口。示例代码如下:: U! E  x: J6 D& |
( u' K* }: L2 g
  1. DSTATUS disk_initialize (
    % S$ L8 x) o8 Y. P2 D5 H  e
  2.         BYTE pdrv                                /* Physical drive nmuber to identify the drive */( w' W! m; f8 u$ U: |* _, P
  3. )+ U, e( b5 d1 s- S3 F# d4 |) v# N
  4. {5 o  M  l* h+ Q( a& C6 T6 G$ q
  5.         DSTATUS stat=STA_NOINIT;6 e! a' c5 Y& J( f5 C' U
  6.         switch (pdrv) {2 {+ `4 a5 ]. o$ c& K; M
  7.         case  DEV_FLASH :
    * t; F, v5 `5 W  J( F! Z; g2 z
  8.                 {
    8 ^7 l0 v, {5 c  R
  9.                     SPI_FLASH_Init();+ _% e# G+ B6 Q$ h6 r
  10.                     if(SPI_FLASH_ReadID()==sFLASH_ID)
    1 K9 Q4 J" O0 L3 ~5 J" v. {: C2 _/ X
  11.                       stat&=~STA_NOINIT;
    + r' ?' ?! i2 W; E4 S
  12.                     else' C) E; _; k3 }+ k, q$ \9 @
  13.                       stat=STA_NOINIT;- S, m& R0 L6 ]* w$ D" c( A. D- k
  14.                 }
    ) N3 c; B$ _. y/ m8 N3 p9 k
  15.                 return stat;3 N1 P7 f; v  W
  16.         }
    ( |$ i; j! {6 ?4 g
  17.         return STA_NOINIT;' M7 D0 o! K+ w! j' A
  18. }
复制代码
  q! _* l; I6 C. N: g( c. D
c.disk_read 读。示例代码如下:
$ U3 X% t3 ^6 n7 B+ d# i
/ e+ N4 V; y5 o( z2 ?/ N/ G
  1. DRESULT disk_read (; O* f) ]9 @. k7 b( p
  2.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
    / b+ O4 l0 _( g" `% q( c5 C
  3.         BYTE *buff,                /* Data buffer to store read data */. }; s6 g( {5 b$ ^# y% B9 R8 f8 {
  4.         LBA_t sector,        /* Start sector in LBA */
    : P4 c+ ?/ e5 o. c+ x% c* G
  5.         UINT count                /* Number of sectors to read */! D' \: _# B& X8 u7 A* S
  6. )
    . b. N/ {0 ]! y3 \1 U9 q
  7. {' o# n1 c2 q+ Q1 D9 b$ h! }" g8 D" X6 {
  8.         DRESULT res;
    & [2 U2 }" h5 Q5 W9 f& Z5 M# b
  9.         switch (pdrv) {* Q6 U' i$ W9 g
  10.         case  DEV_FLASH :. p- g) Q0 C# E) y! T& t4 `
  11.                 {& u+ \/ B6 l$ W
  12.                         SPI_FLASH_BufferRead(buff, sector*4096, count*4096);
    * h* m& |% }- l; d" |
  13.                         res=RES_OK;
    4 ], ~. K  D5 {, y; `8 X( i0 y; @, \
  14.                 }6 F# R0 f3 M+ z9 X
  15.                 return res;
    / V; U( `6 Y  v5 r  D
  16.         }8 r* }2 a0 I& Z% V' F
  17.         return RES_PARERR;7 f$ Z9 H2 R1 F" `
  18. }
复制代码

, j8 b$ K  }; d/ V0 x) B5 ~. B& M$ u$ N4 J
d.disk_write 写。示例代码如下:: }2 E8 z# j! v7 ^& V2 H

0 L1 j+ o5 W8 q9 S
  1. DRESULT disk_write (
    0 u7 j: ?3 j4 _1 s) }1 D% U. P
  2.         BYTE pdrv,                        /* Physical drive nmuber to identify the drive */
    ; i& M# T+ N+ l% x4 [
  3.         const BYTE *buff,        /* Data to be written */
    8 K+ q) W* }- K( Q
  4.         LBA_t sector,                /* Start sector in LBA */0 H3 [; y4 J2 n8 b' Y" D& n
  5.         UINT count                        /* Number of sectors to write */9 z" D+ N% `" `6 Q
  6. ), i( F; p3 \2 G% j
  7. {) g4 w7 B* v/ h3 T
  8.         DRESULT res;
    ( |/ Z4 x6 F8 {6 E
  9.         switch (pdrv) {
    ; f1 v* t7 d- G1 s9 m" r8 C
  10.         case  DEV_FLASH :
    0 {. v) Q4 S1 @: C. {5 T! A( H) B
  11.                 {8 @) J0 l4 X# E. Y3 f
  12.                         SPI_FLASH_SectorErase(sector*4096);         9 S1 d8 I9 J4 Z' X
  13.                         SPI_FLASH_BufferWrite((BYTE *)buff, sector*4096, count*4096);/ K4 Q, G9 o1 u2 A! S5 G7 z
  14.                         res=RES_OK;
    3 ]8 h, V% Z$ B2 E
  15.                 }- c. g* U/ t3 G: Y9 r5 Y5 {9 T
  16.                 return res;- J: S2 r  ^) L  ]9 U8 b
  17.         }5 V8 P. v6 V( m
  18.         return RES_PARERR;
    0 v( F7 r. T2 E( J- Z; J
  19. }
    7 a0 y, U) \3 d+ O, |% u4 P. I
复制代码

: Y' z' V5 N1 i" d4 W4 |+ ae.disk_ioctl 设备属性接口。示例代码如下:
7 S; c- n  j- \5 U4 V3 F( e! V6 T. \9 H; T' D" G" Q
  1. DRESULT disk_ioctl () U, D5 W0 J. m
  2.         BYTE pdrv,                /* Physical drive nmuber (0..) */% }# k' Q3 D2 d( L$ y9 y
  3.         BYTE cmd,                /* Control code */
    9 X( o' P2 y- o7 e
  4.         void *buff                /* Buffer to send/receive control data */2 |/ W6 p3 ^# }: P( w
  5. )
    2 |3 R0 p# h8 L8 E4 |- z
  6. {, w8 t3 t) K+ p7 C9 j& v
  7.         DRESULT res;. T" ?6 C6 y3 J) s$ x
  8.         switch (pdrv) {
    4 q' o9 [# E. p/ l4 c/ w% ^! j
  9.         case  DEV_FLASH :
    ) i* B' K) S; V! m9 u: @
  10.                 {
    ) R& n- t: Z6 _
  11.                         switch (cmd) {0 x5 k' e/ \5 g
  12.                                 /* 扇区数量:2048*4096/1024/1024=8(MB) */5 c5 v# P1 k! k7 n3 J6 A  T
  13.                                       case GET_SECTOR_COUNT:
    # ], j! g. k  Y& }
  14.                                      *(DWORD * )buff = 2048;                . Q+ @$ m( D) \# Q1 @$ z
  15.                                               break;
    : i7 }) k4 O; G6 S3 m8 [
  16.                                             /* 扇区大小  */& [# Q$ ~) V' t; L: E
  17.                                              case GET_SECTOR_SIZE :
    . y. Q2 k) ~. J+ ?6 |) M3 @
  18.                                              *(WORD * )buff = 4096;
    " B& O1 _: ^6 W6 O5 G" t, t
  19.                                      break;) {) o& W  K( q
  20.                                       /* 同时擦除扇区个数 */2 v, f4 T# x, P" [) E1 s) f
  21.                                         case GET_BLOCK_SIZE :7 C$ ?; E3 |* s2 G2 d  b) U
  22.                                                *(DWORD * )buff = 1;
    1 b) F! Z; o9 P1 J9 J8 V
  23.                                              break;        ) w5 [- g. Y! r: h8 D. q  r# l
  24.                                       }
    / b3 I- L" w6 Q- _# {
  25.                         res=RES_OK;
    ( c. j8 c4 k, m  Q0 W1 g
  26.                 }+ q8 ~( z, o$ G8 K) v
  27.                 return res;        ! R8 e$ f$ I( |( }0 G# j3 g- \3 D
  28.         }
    0 i0 S, @2 f- g& Y: M( o9 W
  29.         return RES_PARERR;
    , p  k+ f# R( A) u  t- X$ a
  30. }
复制代码

) p4 ?* i, y9 @f.DWORD get_fattime 获取时间。示例代码如下:- V: @7 W; p1 d4 P: I; m

9 ]" \' T# o! V  R- E+ Q
  1. DWORD get_fattime (void)" `) O2 M& C# W5 U
  2. {$ U$ S, h% T# X% T
  3.         return ((2021-1980)<<(25)|(1)<<(21)|(1)<<(16)|(1)<<(11)|(1)<<(5)|(2)<<(0));
    % {, U+ r9 f, J3 t6 u
  4. }
复制代码

4 A& z$ U/ F4 P2 `6 ]: w8 u: i六、修改ffconf.h,配置文件系统的具体功能。
  h  j- ^% ]% p& ^: p# m& F9 f4 r& P3 |. ?5 d
a.FF_USE_MKFS        1        使用格式化的功能, [7 w2 t# b1 U/ Z

- Q. _; H+ V  J# ?4 T; sb.FF_CODE_PAGE     936        修改编码页以支持中文文件名
- T% X) d& I  p" N( m
, L8 g9 O: A( Y! gc.FF_USE_LFN        0        支持长文件名6 @* t6 Z; k8 z
: |5 J! h3 t# D' Z1 z" a% }$ |) `
d.FF_MAX_SS        4096        修改支持最大的设备扇区大小,与flash设备对应。
# S" E2 d; y/ i$ L$ G3 G2 f
7 z* [5 P# `4 o 七、尝试使用文件系统来测试是否移植成功。& x2 o! b3 v8 p, G
. f0 y# R, K/ F% K1 ]: Q
常规使用流程1 n: g2 T& h- s3 q
" X% b' M# G: ]6 x, T+ U
a.挂在文件系统到一个设备。使用函数:f_mount()2 c0 E- |  b% o8 x7 e
3 [, p( F: E4 n+ a. j! i
b.打开文件。使用函数:f_open()
& y$ g$ W: c& V3 U! T  @0 y4 m0 h  k, U0 x) j" Q3 R& ^4 q
c.数据的读取与写入
! P" z6 [5 \2 m  `1 q4 [, }1 ^0 v* m7 Z! m) L. q# U
d.关闭文件。使用函数:f_close()
/ g0 ?" n; H8 b6 ?6 X2 J! h2 \$ ^: m$ ?  G! B& c8 C1 T
注意:测试过程可使用返回值判断是否移植成功。在挂载设备时,存在错误FR_NO_FILESYSTEM(13),可采用函数f_mkfs进行解决,该函数用于格式化文件系统。相关代码如下:
. C, c& g; w/ z: ^- w0 u' H( J1 a. L
6 J& k9 j  B7 A% i
  1. printf("\r\nFatFs测试实验\r\n");
    2 d* F+ V4 A: `
  2.         res=f_mount(&flash_fs, "", 1);8 B* `# \; W* @' h7 B# w, }7 M0 X! }, [
  3.          if(res==FR_OK)+ l$ F: ^3 }# r
  4.         {' g* d3 M& D" X( ~4 t
  5.                 printf("\r\n文件系统挂载成功!\r\n");
    * d8 `8 E, V: |! I* z
  6.         }
    / R; K7 T6 }: E* Z
  7.         else- t3 {+ v- c4 t0 s" q. u! u3 z7 g
  8.         {$ H& E, w0 h# ]8 m* f
  9.                 printf("\r\nf_mount错误代码:%d\r\n",res);
    6 I! ]$ @3 B6 T1 o4 |3 S
  10.                 if(res == FR_NO_FILESYSTEM)1 f9 j2 S2 p9 o5 E
  11.                 {" [/ D" {1 X' c6 T$ G1 x
  12.                         res=f_mkfs("", 0, work, sizeof work);
    7 l6 L( r6 \2 D# a  l
  13.                         if(res==FR_OK)2 Z7 b7 S3 _& U
  14.                         {& B2 }& c# m' @+ |5 f; A8 A. Q
  15.                                    printf("\r\n文件系统格式化成功!\r\n");
    0 `2 g) m2 p  w5 j
  16.                         }) \, b" S" }" l; w+ V/ D
  17.                         else3 P# t* G7 x, B8 |) E+ r9 G
  18.                         {; X2 ~6 I- G9 b, {1 K' ^
  19.                                   printf("\r\nf_mkfs错误代码:%d\r\n",res);6 l, ~  x4 E, \, Z
  20.                         }
    & F. ]6 E$ R5 s, A  X7 K1 ?3 m
  21.                 }
    ( _" \4 H' i; K
  22.         }
    / A+ M/ Q2 ]8 [! W8 Z
  23.         //打开文件,写入数据,关闭文件! P1 }! a# H2 G) H
  24.          res = f_open(&flash_fil, "hello.txt", FA_OPEN_ALWAYS|FA_WRITE|FA_READ);
    3 b, Y1 w: T) W) S; p6 G
  25.          if(res==FR_OK)) A  @7 X! j& ^; N
  26.         {' o. B- q- x( D; G7 F3 h" C5 s
  27.                 printf("\r\nf_open测试成功!\r\n");& x: K/ F2 @2 G' [1 i. _
  28.         }; ?" q  V" W) s5 L
  29.         else1 {0 Y; t* Q7 G. |# X% p
  30.         {
    ' Q3 E* A' w* L. R
  31.                 printf("\r\nf_open错误代码:%d\r\n",res);
    7 W9 `5 Q) O/ n- b7 _" m6 C
  32.         }
    , H; F/ k  I8 x& B+ X+ r
  33.         //3 x( @$ J" r; v9 Y3 y; _
  34.         printf("\r\n正在写入:%s\r\n",Tx_Buffer);
    / {2 m6 D. Q8 r5 g
  35.         res=f_write(&flash_fil, Tx_Buffer,BufferSize,&Num_Of_Written);, f! ~; ^* \" j$ O# z
  36.         if(res==FR_OK)
    0 f8 I7 G5 x1 h
  37.         {; O* e0 P/ F2 d( y: w$ w- D
  38.                 printf("\r\nf_write测试成功!\r\n");9 y$ D' }7 Z/ \. f
  39.         }6 c+ [9 [% O% T. b, W/ a  R
  40.         else7 g3 l, P1 D" [' e
  41.         {. P* p- U% ]) d0 k/ }
  42.                 printf("\r\nf_write错误代码:%d\r\n",res);8 h. j' ]0 g/ c  O2 I# f0 @" p" R7 {
  43.         }+ K8 A8 R) o1 G6 I& O# ?
  44.         //9 S7 {# i9 I* m
  45.         f_close(&flash_fil);
    ; ?% N' M6 h. w8 y; A7 H/ o$ ]3 w
  46.         //打开文件,读取数据,关闭文件
    % d/ H, w$ z2 d: [6 M3 r
  47.         res = f_open(&flash_fil, "hello.txt", FA_OPEN_ALWAYS|FA_WRITE|FA_READ);% k" R5 i2 v- D* ]. N
  48.          if(res==FR_OK)1 a' y+ P; @/ u0 p( F0 N+ z
  49.         {
    ! d0 X% |7 y8 @' F
  50.                 printf("\r\nf_open测试成功!\r\n");
    , K, W) w( i! G, N
  51.         }
    8 m- h" ?4 b- I: N2 |
  52.         else: t. {: }9 }: p6 o$ W3 v/ y  t
  53.         {
    5 h$ s6 V. j, [9 `1 J$ N" Y( M
  54.                 printf("\r\nf_open错误代码:%d\r\n",res);6 a# U/ ?- n" Q8 N$ P
  55.         }
    + x. g6 E! p$ x: m7 s# t0 J- \0 Q0 n
  56.         /// [, O1 P9 r) K/ w9 \1 v- m
  57.         res=f_read(&flash_fil, Rx_Buffer, BufferSize, &Num_Of_Read);
    5 J3 e5 `2 O0 n6 X1 E
  58.         printf("\r\n读取完成:%s\r\n",Rx_Buffer);
    $ ^- _% b' D8 j0 M) S
  59.         if(res==FR_OK)
    6 x  D% f9 E1 L" y# j2 T
  60.         {/ f* T7 ]( u: n
  61.                 printf("\r\nf_read测试成功!\r\n");
    5 t! n+ ?7 w" H$ A
  62.         }
    , V; {# \0 a/ j2 j1 a* h9 R7 f# I
  63.         else8 b/ _( ]3 H2 X( }
  64.         {
    5 X, L. B4 W2 K0 C7 c
  65.                 printf("\r\nf_read错误代码:%d\r\n",res);* {( u" n/ E( `' F, _
  66.         }" G7 _& o2 W* W* a$ w, M* j9 n3 w4 I$ n
  67.         //0 G9 W& j3 M9 a, G" V# v
  68.         f_close(&flash_fil);
复制代码

3 A. c4 ^. D1 k% Z0 c9 w- K
) \7 C! _! m. c/ a9 Z, g! g 结果展示:" |( C0 i# F4 @) N  W$ d

. n& z2 q; n% N7 t 0(J
N[9NXU1~3KU6EIMO9.png
- ]- m- v. R8 G, V4 u/ C# J6 Y! u4 Z0 g/ g( z3 F7 O

1 N5 V4 q$ g" u$ n* ^
赞 收藏 评论0 发布时间:2022-4-7 18:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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