目录
2.26 FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR
1. 简介
FATFS是面向小型嵌入式系统的一种通用的FAT文件系统。它完全是由C语言编写并且完全独立于底层I/O介质。支持的内核有:8051、PIC、AVR、SH、Z80、H8、ARM等。FATFS支持FAT12、FAT16、FAT32等格式。
1.1 Fatfs目录结构
1.1.1 documents
doc文件中是编译好的html文档,在res文件中主要是一些照片。对于整个document文件我们不需要关注。移植的时候只需要将source文件添加到工程中即可。
1.1.2 source
- ffconf.h:FATFS模块配置文件(根据需要进行配置)
- ff.h:FATFS和应用模块公用的包含文件(不需要修改)
- ff.c:FATFS模块源码(不需要修改)
- diskio.c:FATFS和disk I/O模块接口层文件(与平台相关的代码,需要用户根据存储介质来编写函数。)
- diskio.h:FATFS和disk I/O模块公用的包含文件(不需要修改)
- ffsystem.c:当使用了操作系统时,该文件必须要由用户来实现!源码包中的
ffsystem.c
给出了需要实现的各函数接口!用户需要根据自己使用的操作系统,修改其中的各接口的实现。- ffunicode.c:处理 Unicode 编码相关的功能
注意:FATFS模块在移植的时候,一般只需要修改2个文件,即ffconf.h和diskio.c。FATFS模块的所有配置项都是存放在ffconf.h里面,可以通过配置里面的一些选项,来满足自己的需求。diskio.c是硬件层,负责与底层硬件接口适配。
2. ffconf.h
2.1 FFCONF_DEF
FatFs 的版本号,与实际功能无关
2.2 FF_FS_READONLY
定义 FatFs 是否工作在只读模式。
- 0:读/写。默认值。
- 1:只读。只读模式下,写相关的函数 f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 以及其他和写操作相关的函数都将被移除。
2.3 FF_FS_MINIMIZE
用来极限精简 FatFs,此选项定义最小化级别,以删除一些基本 API 函数,如下所示
0:所有基本的 API 函数都可用。默认值。
1:f_stat,f_getfree,f_unlink,f_mkdir,f_chmod,f_utime,f_truncate和f_rename函数被删除。
2:除了移除 1 中的函数,还将移除 f_opendir, f_readdir and f_closedir
3:除了移除 2 中的函数,还将移除 f_lseek
2.4 FF_USE_FIND
FF_USE_STRFUNC
定义字符操作的相关函数 f_gets(), f_putc(), f_puts() 及 f_printf() 是否有效。0:禁用所有的字符串相关操作函数。默认值。
1:启用,但是没有 LF-CRLF 转换。即:不会忽略回车符 \r
2:启用,且带有 LF-CRLF转换。即:忽略回车符 \r
2.5 FF_USE_MKFS
定义函数 f_mkfs() 是否有效
- 0: 禁用。默认值
- 1: 启用
2.6 FF_USE_FASTSEEK
定义快速 seek 模式是否有效。
- 0: 禁用。默认值
- 1: 启用。会额外记录很多信息,以供在 f_lseek 中使用
2.7 FF_USE_EXPAND
定义函数 f_expand() 是否有效
- 0: 禁用。默认值
- 1: 启用
2.8 FF_USE_CHMOD
定义属性操作函数 f_chmod() 和 f_utime() 是否有效
- 0: 禁用。默认值
- 1: 启用。此外必须定义 FF_FS_READONLY 为 0。即:不能开启只读模式
2.9 FF_USE_LABEL
定义卷标函数 f_getlabel() 和 f_setlabel() 是否有效
- 0: 禁用。默认值
- 1: 启用
2.10 FF_USE_FORWARD
定义函数 f_forward() 是否有效
- 0: 禁用。默认值
- 1: 启用
2.11 FF_CODE_PAGE
指定要在目标系统上使用的 OEM 代码页,错误的编码页设置将导致读写文件失败。支持的编码页如下:
/ 437 - U.S. / 720 - Arabic / 737 - Greek / 771 - KBL / 775 - Baltic / 850 - Latin 1 / 852 - Latin 2 / 855 - Cyrillic / 857 - Turkish / 860 - Portuguese / 861 - Icelandic / 862 - Hebrew / 863 - Canadian French / 864 - Arabic / 865 - Nordic / 866 - Russian / 869 - Greek 2 / 932 - Japanese (DBCS) / 936 - Simplified Chinese (DBCS) / 949 - Korean (DBCS) / 950 - Traditional Chinese (DBCS) / 0 - Include all code pages above and configured by f_setcp()
2.12 FF_USE_LFN
此选项可切换对长文件名(LFN)的支持。 启用 LFN 时,需要将 Unicode 支持模块 ffunicode.c 添加到项目中。 当使用堆栈作为工作缓冲区时,请注意堆栈溢出。 当使用堆内存作为工作缓冲区时,需要将 ffsystem.c 添加到项目中,并实现其中的内存管理函数 ff_memalloc 和 ff_memfree。
0: 不启用。默认值。FF_MAX_LFN 无效
1: 启用。且 LFN 在代码段 BSS 上具有静态工作缓冲区。 始终不是线程安全的。
2: 启用。且在 STACK 上具有动态工作缓冲区的 LFN。需要注意栈溢出的问题。
3: 启用。且在 HEAP 上具有动态工作缓冲区的 LFN。此时,必须要启用 ffsystem.c 中的动态内存申请函数 ff_memalloc() 和 ff_memfree()
2.13 FF_MAX_LFN
启用 LFN ,会增加 (FF_MAX_LFN + 1) * 2 字节的固定缓冲区空间。具体使用方式见 ff.c 文件的开头部分的宏定义即可。如果是 exFAT 文件系统,则还需要再占用 (FF_MAX_LFN + 44) / 15 * 32 字节的缓冲区空间。且 exFAT 必须启用长文件名支持
FF_MAX_LFN 以 UTF-16 代码单位定义工作缓冲区的大小,它可以在 12 到 255 的范围内。建议将 255 设置为完全支持LFN规范。长文件名是微软的专利,使用中与上面的编码有关系。
2.14 FF_LFN_UNICODE
此选项可在 API 上切换文件名的字符编码。选择 Unicode 时,FF_CODE_PAGE 实际上没有任何意义,除了与遗留系统的兼容性,例如 MS-DOS 和任何不支持 LFN 的系统。 FatFs 支持代码点达到 U + 10FFFF。
0: ANSI/OEM in current CP (TCHAR = char)。默认值
1: Unicode in UTF-16 (TCHAR = WCHAR)
2: Unicode in UTF-8 (TCHAR = char)
3: Unicode in UTF-32 (TCHAR = DWORD)
此外,字符串输入/输出函数的行为也会受到此选项的影响。如果关闭了长文件名支持,则该项无效
2.15 FF_LFN_BUF、FF_SFN_BUF
这组选项定义了FILINFO结构中文件名成员的大小,该结构用于读取目录项。这些值应该足够文件名被读取。可读文件名的最大可能长度取决于字符编码。当LFN未启用时,这些选项不起作用。
2.16 FF_FS_RPATH
定义是否支持相对路径
- 0: 禁用。且相对路径相关的函数也被移除
- 1: 支持。f_chdir() 和 f_chdrive() 有效
- 2: 支持。除了提供 1 中的函数,还提供 f_getcwd()
2.17 FF_VOLUMES
此选项配置要使用的卷数(逻辑驱动器最多10个),最小值 1。
2.18 FF_VOLUME_STRS
此选项定义每个逻辑驱动器的卷ID字符串。项目数不得少于FF_VOLUMES。 卷ID字符串的有效字符是A-Z,a-z和0-9,但是,它们在不区分大小写的情况下进行比较。
如果 FF_STR_VOLUME_ID == 0,则此选项无效。 如果 FF_STR_VOLUME_ID > = 1且未定义此选项,则需要定义用户定义的卷字符串表,如下所示。 该表不应动态修改。
const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
2.19 FF_MULTI_PARTITION
禁用(0)或启用(1)。 此选项可切换多分区功能。 默认情况下(0),每个逻辑驱动器号绑定到相同的物理驱动器号,并且仅安装物理驱动器中的卷。 启用后,每个逻辑驱动器都绑定到用户定义的分区解析表 VolToPart [] 中列出的物理驱动器上的分区。 此外,还将提供 f_fdisk功能。
2.20 FF_MIN_SS, FF_MAX_SS
这组选项定义了低级磁盘 I/O 接口,disk_read 和 disk_write函数使用的扇区大小范围。 有效值为 512、1024、2048 和 4096。FF_MIN_SS定义最小扇区大小,FF_MAX_SS 定义最大扇区大小。 始终为存储卡和硬盘设置 512。 但是,板载闪存和某些类型的光学介质可能需要更大的值。 当FF_MAX_SS > FF_MIN_SS 时,启用对可变扇区大小的支持,并且需要对 disk_ioctl 函数实现 GET_SECTOR_SIZE 命令
2.21 FF_USE_TRIM
定义是否支持 ATA-TRIM
- 0: 禁止
- 1: 支持。此时,disk_ioctl() 函数需要实现 CTRL_TRIM 命令。
2.22 FF_FS_NOFSINFO
取值 0 到 3。如果您需要知道FAT32 卷上的正确可用空间,请设置此选项的第0位,并且在卷 mount 后第一时间执行 f_getfree函数,将强制进行完整的FAT扫描。 位1 控制最后分配的簇编号的使用。
/ bit0=0: Use free cluster count in the FSINFO if available. / bit0=1: Do not trust free cluster count in the FSINFO. / bit1=0: Use last allocated cluster number in the FSINFO if available. / bit1=1: Do not trust last allocated cluster number in the FSINFO.
2.23 FF_FS_TINY
取值为 正常(0)或微小(1)。 在微小的配置中,文件对象 FIL 的大小减少了 FF_MAX_SS 字节。 不是从文件对象中消除私有数据缓冲区,而是将文件系统对象 FATFS 中的公共扇区缓冲区用于文件数据传输。
2.24 FF_FS_EXFAT
此选项定义对 exFAT 文件系统的支持,Enabled(1)或 Disabled(0)。开启之后,将同时支持 exFAT、FAT/FAT32。要启用 exFAT,还必须启用LFN 并为全功能 exFAT 功能配置 FF_LFN_UNICODE> = 1 和 FF_MAX_LFN == 255。 请注意,由于需要64位整数类型,启用 exFAT会丢弃ANSI C(C89)兼容性。
2.25 FF_FS_NORTC
此选项控制时间戳功能,0:使用RTC;1:不使用 RTC。 如果系统没有任何 RTC 功能或不需要有效时间戳,请将 FF_FS_NORTC 设置为1 以禁用时间戳功能。此时,FatFs 修改的每个对象都有一个由 FF_NORTC_MON,FF_NORTC_MDAY 和 FF_NORTC_YEAR 定义的固定时间戳。 要使用时间戳功能,请设置 FF_FS_NORTC == 0 并将 get_fattime 函数添加到项目中以从 RTC 获取当前时间。 此选项对只读配置无效。
2.26 FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR
FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR
2.27 FF_FS_LOCK
选项切换文件锁定功能,以控制打开重复文件和打开对象的非法操作。 请注意,文件锁定功能独立于重入。 只读配置时,此选项必须为 0。
- 0:禁用文件锁定功能。 为避免文件操作错误导致文件崩溃,应用程序需要避免非法打开,删除和重命名为打开的对象。
- >0:启用文件锁定功能。 该值定义在文件锁定控制下可以同时打开多少文件/子目录。 使用FR_LOCKED将拒绝对打开对象的非法操作。
2.28 FF_FS_REENTRANT
此选项可切换 FatFs 模块本身的重入(线程安全),取值为 禁用(0)或启用(1)。 请注意,对不同卷的文件/目录访问始终是可重入的,无论此选项如何,它都可以同时工作。但是,卷管理函数 f_mount,f_mkfs 和 f_fdisk 始终不可重入。
只有文件/目录访问同一个卷,换句话说,独占使用每个文件系统对象,才能受此功能的控制。 要启用此功能,用户需要将 ffsystem.c 添加到自己的项目中,同时实现其中的同步处理程序 ff_req_grant,ff_rel_grant,ff_del_syncobj和ff_cre_syncobj
2.29 FF_FS_TIMEOUT
当等待时间太长时,使用 FF_FS_TIMEOUT中止文件功能的时间滴答数。 当 FF_FS_REENTRANT == 0 时,此选项无效。
2.30 FF_SYNC_t
此选项定义 OS 相关的同步对象类型。 例如 HANDLE,ID,OS_EVENT *,SemaphoreHandle_t等。用于OS 定义的头文件需要包含在 ff.c范围内的某处。 当 FF_FS_REENTRANT == 0 时,此选项无效。
3. ff.c/ff.h
3.1 f_mount 、f_unmount
3.2 f_mkfs
3.3 f_open
3.4 f_close
3.5 f_read
3.6 f_write
3.7 f_lseek
4. diskio.c/diskio.h
在Fatfs文件移动移植中,我们最需要注意的便是diskio.c文件函数的实现
4.1 disk_status
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
/* 返回磁盘的状态 */
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
4.2 disk_initialize
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
/* 对需要使用的磁盘进行初始化 */
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_initialize();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
4.3 disk_read
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
/* 对磁盘进行读操作 */
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
4.4 disk_write
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
/* 对磁盘进行写操作 */
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
4.5 disk_ioctl
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
/* 对磁盘进行其他命令的操作 */
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// Process of the command for the RAM drive
return res;
case DEV_MMC :
// Process of the command for the MMC/SD card
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}