一. FatSL 介绍, d: [) |8 d. [9 U; |% d& P
FatSL 是嵌入式软件供应商 HCC 开发的一种 FAT 类型的文件系统。FatSL 具有以下特性:5 C9 s! C, r; D( K _ J) Y3 A
极低的 RAM 和 ROM 需求 <1K bytes RAM, 大约 4K bytes ROM
2 N7 M( P, l+ A; n: f4 R" t高性能,针对 FAT 风险的安全特性设计
O; P8 S% G) ~支持 FAT12,FAT16,FAT32 类型
; Y, @0 m N- A5 k' z4 dFatSL 的结构如下图所示 (FatSL 的软件结构设置的非常清晰,赞)
& Z# g# L+ w$ l) t
. D7 f' C0 C, S( N( ^
, I. s0 `- ~# |% O: O5 b" }+ {' O J5 E# I% e# k
; j, J1 A0 ]5 b二.FatSL 的移植* D8 t& Y' r7 W0 Q( d) z3 E' M) @
如果了解 FAT 的系统结构,并理解了 FatSL 的软件结构,那么文件系统移植并不困难(其实文件系统移植都是大同小异的)。本文给出的例子是基于 STEVAL-CCM007V1 硬件平台,通过 NFTL层(NAND Flash Translation Layer)在 NAND Flash 上建立该文件系统的情况。/ b: F4 w P N+ t. s
1. 数据结构
3 o1 I; G X' z8 O/ h/ W- H F_PHY 主要是对存储介质的描述7 g2 v1 f% m) {! P z6 I* D
- <div>typedef struct</div><div>{</div><div> unsigned short number_of_cylinders; // 磁盘的参数,现在已经很少用到</div><div> unsigned short sector_per_track;</div><div> unsigned short number_of_heads;</div><div> unsigned long number_of_sectors; // 扇区数</div><div> unsigned char media_descriptor; // 介质是否支持拔插</div><div> unsigned short bytes_per_sector; // 扇区大小 512bytes</div><div>} F_PHY;</div>
复制代码 ' P5 T; ]8 m8 {/ z, T1 L) K
& N2 ~3 x. U0 p3 H& r" u_F_DRIVER 就是文件系统对存储介质的驱动接口了,通过 user_ptr 指针(例如指向用户自定% h" O0 ?5 _* A( ~
义的存储介质的数据结构)可以为驱动实现更好的设计。! S1 q4 v6 T8 }+ x' w
- <div>typedef struct F_DRIVER</div><div>{</div><div> unsigned long user_data; /* 用户自定义数据 */</div><div> void * user_ptr; /* 用户定义指针 */</div><div> /* 驱动函数 */</div><div> F_WRITESECTOR writesector;</div><div> F_READSECTOR readsector;</div><div> F_GETPHY getphy;</div><div> F_GETSTATUS getstatus;</div><div> F_RELEASE release;</div><div>} _F_DRIVER;</div>
复制代码 4 c t f( C/ w# S
, d6 R# g2 ^% y" W7 P. V
2. 驱动函数的编写
/ [0 j& p' v' y: E5 o" tF_DRIVER *( *F_DRIVERINIT )( unsigned long ulDriverParameter );0 |) E( m- [) e% `( l4 E
初始化文件系统和存储介质驱动的接口,为 F_DRIVER 结构体添加内容
# t) o1 y) l; C- F_DRIVER *Nand_initfunc(unsigned long driver_param)4 g5 k O: J9 M- f, h
- {7 M( N1 B/ j) I6 ^! J& {
- t_nandDrv *p;$ c: ~' h+ O2 u2 }3 u* T' \9 u! M
- p = nandDrv;
) v5 ~) G% H' m& T0 @ - + j2 Q% F2 V6 x9 `; e
- if (p->use)8 ?" r! V! q# S- K
- {
; `. \7 F- H2 E( \( l - return 0;: H, V; m- P. y" U7 B# h
- }+ Z; W' X* w& V( x7 p1 f5 n
- (void)psp_memset( p->driver, 0, sizeof( F_DRIVER ) );- Y a* J9 \' {* n
- p->driver->readsector = nand_readsector;
' n4 p. v) T% Y5 x' ^) P - p->driver->writesector = nand_writesector;; H, Z7 P* i: c- S4 W: }( ], |
- p->driver->getphy = nand_getphy;. ^" m, m0 @7 N4 p$ t6 Z
- p->driver->getstatus = nand_getstatus;
% s, z: @1 w( q; q1 }" a - p->driver->release = nand_release;: L) i- r& G# ?; E
- p->driver->user_ptr = p;
) i0 f0 C% h, E4 ~ - p->use = 1;! q# L/ J" D# o( X9 i
- return p->driver;7 h& z* B; H/ x& _4 `( _
- }
复制代码
' u' y- x, l; K5 f) j, Ctypedef int ( *F_GETPHY )( F_DRIVER * pxDriver, F_PHY * pxPhy );! k1 x9 d3 f; d. ~; d4 ~: c
将存储介质的信息添加到 F_PHY 结构体中! S( P, r2 o6 c2 G! R
- static int nand_getphy(F_DRIVER *driver, F_PHY *phy)3 q3 w4 r3 E* M) q' u
- {
. a7 [* { h( M+ b$ u$ n* d" P3 J - phy->number_of_sectors = MassBlockCount;- R6 K, O( S, A4 E) b c- y3 q
- phy->media_descriptor = F_MEDIADESC_FIX;+ Z9 L0 F9 i. d0 U) x8 v, `
- phy->bytes_per_sector = 512u;4 r4 F) b/ g' F8 x* h
- return 0;
7 v! L" q" h# P) E* N! G8 h# a/ J! g - }
复制代码 ( P/ z5 w, N1 u/ O( V, a* n
typedef int ( *F_READSECTOR )( F_DRIVER * pxDriver, void * pvBuffer, unsigned long
! p$ `3 e, B6 [ulSector );6 }' D$ n( W4 G4 m5 ] o; @* P
读扇区函数,从逻辑扇区 ulSector 中将数据读到 pvBuffer 所指向的缓存中$ g5 C5 d: U) e. k3 z: U
- static int nand_readsector(F_DRIVER *driver, void *data, unsigned long sector)- w8 N: \4 H5 c: \; F6 p
- {
U7 @" h; W! a - uint16_t res;" p% l0 h5 a6 J, C
- 5 ~6 M! _1 _6 x
- t_nandDrv *p = (t_nandDrv *)(driver->user_ptr);
- n# k7 ?/ m& s8 |2 m- N3 S" i - 2 N; E" }$ j: e9 Z X
- if(sector >= p->maxsector)
' V, R( p! i" Z- e6 I: j - {' w$ O! _9 w4 G: s1 N- {) F7 Z
- return 2;
, B) x% Y, ?+ s: J7 m8 y; } - }
3 A! k8 w8 |. V/ O `% H2 B3 b$ G - , V" j) A- O5 T
- res = NAND_Read(sector, data, 512);
1 k# c7 J1 h$ L# K. R
9 g, H8 A/ z- P. I- if(res != NAND_OK), y' \ @3 d4 F; N
- return 1;1 }! d& ~ q0 N* ]/ Z; q
7 {6 F! ^) d1 S$ A- return 0;: x4 _- c3 k) x7 A
- }
复制代码
3 y5 H7 g/ m5 G+ b8 l' W6 \9 t7 ntypedef int ( *F_WRITESECTOR )( F_DRIVER * pxDriver, void * pvBuffer, unsigned long
% q8 m! _6 d% x* xulSector );* \: e+ P6 L2 s& A, z. b- s* }
写扇区函数,把 pvBuffer 指向的数据写入逻辑扇区 ulSector 中
# a5 @, Q0 y; b. @. F5 z$ y9 I& o0 r. y- static int nand_writesector(F_DRIVER *driver, void *data, unsigned long sector)
! ]8 m$ K/ v2 w - {0 ~2 k/ S/ x+ ~
- uint16_t res;
9 ]* {$ F, D% p0 v
; u- h. o! o' r. ` O+ B- t_nandDrv *p = (t_nandDrv *)(driver->user_ptr);
; a3 D3 P. z$ }9 o2 M; I - 7 ]& A: _% P& N3 x4 U3 M% w
- if(sector >= p->maxsector)* q) i; C! k2 L% f
- {
, Y! r4 e/ t. t, H - return 2; D7 B$ a' {6 [$ \) G: u. ~ \
- }9 o5 t: a6 }% v: w
s- g% G* [/ C% @5 q- res = NAND_Write(sector, data, 512);' S. h" u! [8 f: @
- ( ? H" ^* Y. a! g5 i; K2 J& `
- if(res != NAND_OK)
4 L) [. m- P1 z* L( L5 Y - return 1;
- s: I! i8 J4 v/ s0 k
: x. C0 y8 D* X- return 0;9 Q6 {; L! ^/ o/ |# ?
- }
复制代码 ) m1 g* F( `8 L* p+ G4 @
typedef long ( *F_GETSTATUS )( F_DRIVER * pxDriver );8 n* y) Z+ V! R& o( i
typedef void ( *F_RELEASE )( F_DRIVER * pxDriver ); ]' G: `% ^8 `
这两个函数是检测设备拔插的。
9 y' ^+ W2 y% G" `! J三. 经验杂谈) O6 B, n5 D8 i: E( j
关于文件系统的移植,推荐大家阅读一些 FAT 结构的资料,至少要做到对 FAT 结构心中有数,对调试会有很大的帮助的(工欲善其事,必先利其器)。
. I, Z# l! |4 T( }6 q8 a9 a/ X' q1 A. _, x! q
|