目 录
1.1
1.2
1.3
第 1 章 FatFs 使用说明................................................................................................1
简介...........................................................................................................................1
特性...........................................................................................................................1
应用...........................................................................................................................1
FatFs 软件包中相关文件.................................................................................2
1.3.1
FatFs 应用范围.................................................................................................2
1.3.2
FatFs 配置.........................................................................................................2
1.3.3
FatFs API 函数选择..........................................................................................4
1.3.4
1.3.5 路径名格式.......................................................................................................5
1.3.6 关于长文件名...................................................................................................6
1.3.7 重入...................................................................................................................7
1.3.8 执行有效的文件访问.......................................................................................7
1.3.9 临界区...............................................................................................................8
1.3.10
FatFs 的其它特性和新进展.............................................................................8
1.3.11 程序移植...........................................................................................................9
FatFs 软件包提供的 API 函数.......................................................................17
1.3.12
1.1 简介
第1章 FatFs 使用说明
随着信息技术的发展,当今社会的信息量越来越大,以往由单片机构成的系统简单地对
存储媒介按地址、按字节的读/写已经不能满足人们实际应用的需要,于是利用文件系统对
存储媒介进行管理成了今后单片机系统的一个发展方向。目前常用的文件系统主要有微软的
FATl2、FATl6、FAT32、NTFS 以及 Linux 系统下的 EXT2 和 EXT3 等。由于微软 Windows
的广泛应用,在当前的消费类电子产品中,用得最多的还是 FAT 文件系统,如 U 盘、MP3、
MP4 和数码相机等,所以找到一款容易移植和使用、占用硬件资源相对较小而功能又强大
的 FAT 开源文件系统,对于单片机系统设计者来说是很重要的。
FatFs Module 是一种完全免费开源的 FAT 文件系统模块,专门为小型的嵌入式系统而
设计。它完全用标准 C 语言编写,且完全独立于 I/O 层,可以移植到 8051、PIC、AVR、SH、
Z80、H8 和 ARM 等系列单片机上且只需做简单的修改。它支持 FATl2、FATl6 和 FAT32,
支持多个存储媒介,有独立的缓冲区,可以对多个文件进行读/写。
FatFs Module 有个简化版本 Tiny-FatFs,它跟完全版 FatFs 不同之处主要有两点:
(1) 占用内存更少,只要 1 KB RAM;
(2) 1 次仅支持 1 个存储介质。
完全版 FatFs 和 Tiny-FatFs 的用法一样,仅仅是包含不同的头文件,本文主要以完全版
讲解 FatFs 的使用。
1.2 特性
Windows 兼容的 FAT 文件系统;
平台无关,容易移植;
代码量小;
多种配置选项:
支持多卷(物理驱动器或分区);
多个 ANSI/OEM 代码页包括 DBCS;
支持长文件名,ANSI/OEM 或 Unicode;
支持 RTOS;
支持多种扇区大小;
只读、最小化的 API 和 I/O 缓冲区等。
1.3 应用
FatFs Module 一开始就是为了能在不同的单片机上使用而设计的,所以具有良好的层次
结构,如图 1.1 所示。
图 1.1 FatFs 模块层次结构图
1
最顶层是应用层,使用者无需理会 FatFs Module 的内部结构和复杂的 FAT 协议,只需
要调用 FatFs Module 提供给用户的一系列应用接口函数,如 f_open,f_read,f_write 和 f_close
等,就可以像在 PC 上读/写文件那样简单。
中间层 FatFs Module 实现了 FAT 文件读/写协议。FatFs Module 的完全版提供的是 ff.c、
ff.h,简化版 Tiny-FatFs 提供的是 tff.c、tff.h。除非有必要,使用者一般不用修改,使用时将
需要版本的头文件直接包含进去即可。
需要使用者编写移植代码的是 FatFs Module 提供的底层接口,它包括存储媒介读/写
接口 Disk I/O 和供给文件创建修改时间的实时时钟。
本文讲解时移植硬件平台为 ZLG 公司的 SmartCortexM3-1700 和普通 U 盘。LPC1768
是一款 32 位 Cortex-M3 内核的单片机,具有多达 64 KB 的 SRAM、512 KB 的内部 Flash 和
丰富的外设。软件平台是 Keil 集成开发环境。
1.3.1 FatFs 软件包中相关文件
1. 平台无关
ffconf.h FatFs 模块配置文件
ff.h FatFs 和应用模块公用的包含文件
ff.c FatFs 模块
diskio.h FatFs and disk I/O 模块公用的包含文件
integer.h 数据类型定义
option 可选的外部功能
2. 平台相关(不属于 FatFs 需要由用户提供)
diskio.c FatFs 与 disk I/O 模块接口层文件
1.3.2 FatFs 应用范围
支持 FAT12、FAT16 和 FAT32;
可打开的文件:无限制,依赖于有效的存储器;
支持最多 10 个卷;
文件大小:与 FAT 类型有关(upto 4G-1 bytes);
卷大小:与 FAT 类型有关(upto 2T bytes on 512 bytes/sector);
簇大小:与 FAT 类型有关(upto 64K bytes on 512 bytes/sector);
扇区大小:与 FAT 类型有关(upto 4K bytes)。
FatFs 模块在移植时需先注意以下两点:
ANSI C
FatFs 模块是用 ANSI C 编写的中间件,只要编译器遵循 ANSI C,它都是平台无关的。
整型大小
FatFs 假定 char/short/long 的长度为 8/16/32 位,而 int 为 16 位或 32 位,这些相应的定
义位于 integer.h 文件。这在大多数的编译器上都不会是问题,但是当与预定义的内容发生冲
突时,需要用户注意。
1.3.3 FatFs 配置
文件系统的配置项都在 ffconf.h 文件之中。
(1) _FS_TINY :这个选项在 R0.07 版本之中开始出现,在之前的版本都是以独立的 C
2
文件出现,现在通过一个宏来修改使用起来更方便;
(2) _FS_MINIMIZE、_FS_READONLY、_USE_STRFUNC、_USE_MKFS、
_USE_FORWARD 这些宏是用来对文件系统进行裁剪的,下面的 1.3.4 小节中有详
细介绍;
(3) _CODE_PAGE :本选项用于设置语言码的类型,对应的字库可以在网上下载,其
选项如下:
932 - Japanese Shift-JIS (DBCS, OEM, Windows)
936 - Simplified Chinese GBK (DBCS, OEM, Windows)
949 - Korean (DBCS, OEM, Windows)
950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
1250 - Central Europe (Windows)
1251 - Cyrillic (Windows)
1252 - Latin 1 (Windows)
1253 - Greek (Windows)
1254 - Turkish (Windows)
1255 - Hebrew (Windows)
1256 - Arabic (Windows)
1257 - Baltic (Windows)
1258 - Vietnam (OEM, Windows)
437 - U.S. (OEM)
720 - Arabic (OEM)
737 - Greek (OEM)
775 - Baltic (OEM)
850 - Multilingual Latin 1 (OEM)
858 - Multilingual Latin 1 + Euro (OEM)
852 - Latin 2 (OEM)
855 - Cyrillic (OEM)
866 - Russian (OEM)
857 - Turkish (OEM)
862 - Hebrew (OEM)
874 - Thai (OEM, Windows)
ASCII only (Valid for non LFN cfg.)
(4) _USE_LFN :取值为 0~3,主要用于长文件名的支持及缓冲区的动态分配:
0:不支持长文件名;
1:支持长文件名存储的静态分配,一般是存储在 BSS 段;
2:支持长文件名存储的动态分配,存储在栈上;
3:支持长文件名存储的动态分配,存储在堆上。
(5) _MAX_LFN :可存储长文件的最大长度,其值一般为(12~255),但是缓冲区一
般占(_MAX_LFN + 1) * 2 bytes;
(6) _LFN_UNICODE :为 1 时才支持 unicode 码;
(7) _FS_RPATH :R0.08a 版本改动配置项,取值范围 0~2:
0:去除相对路径支持和函数;
1:开启相对路径并且开启 f_chdrive()和 f_chdir()两个函数;
2:在 1 的基础上添加 f_getcwd()函数。
3
(8) _VOLUMES :支持的逻辑设备数目;
(9) _MAX_SS :扇区缓冲的最大值,其值一般为 512;
(10) _MULTI_PARTITION:定义为 1 时,支持磁盘多个分区;
(11) _USE_ERASE :R0.08a 新加入的配置项,设置为 1 时,支持扇区擦除;
(12) _WORD_ACCESS :如果定义为 1,则可以使用 word 访问;
(13) _FS_REENTRANT :定义为 1 时,文件系统支持重入,但是需要加上跟操作系统
信号量相关的几个函数,函数在 syscall.c 文件中;
(14) _FS_SHARE :文件支持的共享数目。
FatFs 只要求提供 FatFs 模块所必需的底层磁盘 I/O 函数,如果存在一个可工作的目标磁
盘模块,你仅需将编写的新函数附加到 FatFs 模块上,如果没有,则需要提供其它磁盘模块
或者从头编写底层驱动。FatFs 中所有定义的函数并不总是必需的,例如,在只读配置模式
下,磁盘写函数是不需要的。表 1.1 显示了 FatFs 的函数需要依赖于配置选项。
表 1.1 函数依赖配置选项
函数
要求
注意事项
disk_initialize
disk_status
disk_read
disk_write
disk_ioctl (CTRL_SYNC)
disk_ioctl
(GET_SECTOR_COUNT)
disk_ioctl (GET_SECTOR_SIZE)
disk_ioctl (GET_BLOCK_SIZE)
disk_ioctl
(CTRL_ERASE_SECTOR)
get_fattime
ff_convert
ff_wtoupper
ff_cre_syncobj
ff_del_syncobj
ff_req_grant
ff_rel_grant
ff_mem_alloc
ff_mem_free
1.3.4 FatFs API 函数选择
Always
Always
Always
_FS_READONLY == 0
_FS_READONLY == 0
_USE_MKFS == 1
_MAX_SS >= 1024
_USE_MKFS == 1
_USE_ERASE == 1
_FS_READONLY == 0
_USE_LFN >= 1
_USE_LFN >= 1
_FS_REENTRANT == 1
_FS_REENTRANT == 1
_FS_REENTRANT == 1
_FS_REENTRANT == 1
_USE_LFN == 3
_USE_LFN == 3
磁盘 I/O 函数
Unicode 支持函数
有效文件位于 option/cc*.c.
操作系统依赖函数
有效文件位于 option/sysca ll.c.
表 1.2 显示了通过配置选项对 API 函数进行选择(剪裁)以减小模块代码大小。
4
功能
f_mount
f_open
f_close
f_read
f_write
f_sync
f_lseek
f_opendir
f_readdir
f_stat
f_getfree
f_truncate
f_unlink
f_mkdir
f_chmod
f_utime
f_rename
f_chdir
f_chdrive
f_getcwd
f_mkfs
f_forward
f_putc
f_puts
f_printf
f_gets
表 1.2 API 函数选择
_FS_MINIMIZE
0 1 2
x
x
x x
x x
x x
x x
x x
x x
x x
x x
3
x
x
x
x
x
x
x
x
x
x
x
_FS_READONLY
1
0
x
x
x
x
x
x
x
x
x
x
x
x
x
_USE_STRFUNC
1
0
x
x
x
x
_FS_RPATH
0
2
1
x
x
x
x
_USE_MKFS
1
0
x
_USE_FORWARD
1
0
x
1.3.5 路径名格式
FatFs 模块上使用的路径名格式类似于 DOS/Windows 下的文件名,格式如下:
"[drive#:][/]directory/file"
FatFs 模块支持长文件名(LFN)和 DOS 8.3 文件名(SFN)。当使能 LFN 特性时 (_USE
_LFN > 0),可以使用长文件名,子目录用‘\’或者‘/’隔开,这与 DOS/Windows API 函
数接口是相同的方式,不同的是逻辑驱动器用数字带一个冒号来指定的。当一个驱动器号被
忽略时,默认为驱动器 0 或者当前驱动器。控制字符(\0~\x1F)被认为是路径名的末尾。
首位或中间嵌入的空格是合法的,当配置为 LFN 时被看作是名字的一部分,配置为非 LFN
时被视为路径名的末尾。空格和点号被忽略。
默认配置下(_FS_RPATH == 0),FatFs 没有一个像操作系统面向文件系统的当前目录
的概念。卷上的所有对象总是以根目录下的完整路径名来指定,不允许点目录名。标题分隔
符’/’被忽略,它可以存在或省略,默然的驱动器号为 0。
5
当使能相对路径时(_FS_RPATH == 1),如果存在标题分隔符,指定的路径是指相对
于根目录,如果没有标题分隔符,指定目录是指相对于用 f_chdir 函数设置的当前目录,路
径名中允许使用点名称。默认的驱动器是用 f_chdrive 函数设定的当前驱动器。
表 1.3 路径名格式
_FS_RPATH == 0
_FS_RPATH == 1
驱动器 0 根目录
驱动器 0 根目录
驱动器 2 根目录
驱动器 2 根目录
路径名
file.txt 驱动器 0 根目录下的一个文件 当前驱动器当前目录下的一个文件
/file.txt 驱动器 0 根目录下的一个文件 当前驱动器根目录下的一个文件
/
2:
2:/
2:file.txt 驱动器 2 根目录下的一个文件 驱动器 2 当前目录下的一个文件
../file.txt 文件名非法
.
文件名非法
..
文件名非法
dir1/.. 文件名非法
/..
文件名非法
上级目录下的一个文件
此目录
当前目录的上级目录
当前目录
根目录()
当前驱动器当前目录
当前驱动器根目录
驱动器 2 当前目录
驱动器 2 根目录
1.3.6 关于长文件名
FatFs 从 0.07 版本开始支持长文件名(LFN)。在调用文件函数时,一个文件的两个文
件名(SFN 与 LFN)是通用的,除了 f_readdir 函数。支持长文件特性将需要一个额外的工
作缓冲区,此缓冲区的大小可以通过设置_MAX_LFN 来以可用的内存大小相符。因为长文
件名可长达 255 个字符,因此_MAX_LFN 应该设置为 255 来支持全特性的 LFN 选项。当工
作缓冲区的大小容不下给出的文件名时文件函数就会因为 FR_INVALID_NAME 而调用失
败。
表 1.4 ARM7 上的 LFN 配置
编码页
程序大小
SBCS(单字节字符集) +3.7K
932(日文 Shift-JIS)
+62K
936(简体中文 GBK) +177K
949(韩文 Korean)
+139K
950(繁体中文 Big5)
+111K
当使能 LFN,模块增加的大小由编码页(Code Page)类型决定,表 1.4 显示了 LFN 禁
用与使用某些编码来使能时模块的不同大小。日语、中文与韩国语拥有成千上万的字词,因
需要一个巨大的 OEM-Unicode 双向转换表,模块的大小将大大的增大,如表 1.4 所示。
注:FAT 文件系统的 LFN 特性是微软公司的专利。当在商用产品上使用时,根据最终目的的不同可
能需要获得微软的许可证。
6
1.3.7 重入
对不同卷的文件操作总是可以同时地工作,而与重入设置无关。而对于同一个卷的重入
访问可以通过使能_FS_REENTRANT 选项。此时,在 ff.c 中的与平台相关的锁定函数必须
为每个 RTOS 重新编写。如果一个文件函数调用时其访问的卷正被另一个线程使用,则此
访问将阻塞直到该卷解锁。如果等待时间超过了_TIMEOUT 毫秒,则函数将因 FR_TIMEOUT
而终止。某些 RTOS 可能不支持超时操作。
f_mount 与 f_mkfs 函数是个例外,这些函数对于同一个卷不会重入。当使用这些函数时,
其它线程必须关闭此卷中相应的文件,避免对此卷的访问。
注意此部分描述的是 FatFs 自身的重入,与底层磁盘 I/O 的重入无关。
1.3.8 执行有效的文件访问
为了在小型的嵌入式系统中得到优秀的读写效率,应用程序程序员需要可考虑 FatFs 究
竟做了什么。磁盘中的数据是通过下面的方式来被 f_read 函数传送。
图 1.2 读非对齐扇区(短型)
图 1.3 读非对齐扇区(长型)
图 1.4 读对齐扇区
文件 I/O 缓冲区(file I/O buffer)表示一个将被读/写数据的扇区的缓冲区。扇区缓冲区
可以是每个文件对象私有的,或者是文件系统共享的,缓冲区配置选项_FS_TINY 决定在文
件数据传输中使用哪种扇区缓冲区。当选择小缓冲区(1),数据内存的使用量将降低到每
个文件对象 512 字节。在这种情况下,FatFs 只使用一个扇区缓冲区来进行文件数据传输以
及 FAT/目录访问。配置为小缓冲区的缺点是:每次文件数据传输时 FAT 数据缓冲都会丢失
而必须从一个簇的边界开始重新载入数据。不过从其体面的表现与少内存消耗这方面来考
虑,这对于多数的应用也是合适的。
7