FatFs 文件系统
版本:R0.15
下载: elm-chan.org/fsw/ff/00index_e.html
- 平台无关:
- ff.c FatFs 模块。
- ffconf.h FatFs模块的配置文件。
- ff.h FatFs 和应用程序模块的通用包含文件。
- diskio.h FatFs 和磁盘 I/O 模块的通用包含文件。
- ffunicode.c 可选的 Unicode 实用函数。
- 平台相关:
- diskio.c 将现有磁盘 I/O 模块附加到 FatFs 的粘合函数示例。
- 示例
- ffsystem.c 可选 O/S 相关函数的示例。
低级磁盘 I/O 模块不包含在该档案中,因为 FatFs
模块只是一个通用的文件系统层,它不依赖于任何特定的
存储设备。您需要提供一个写入的低级磁盘 I/O 模块
控制连接到目标系统的存储设备。
移植过程:
1、复制 ffconf.h、 ff.c、ff.h、diskio.h、diskio.c、ffunicode.c 文件到项目;
2、修改 ffconf.h 配置文件和 diskio.c 底层存储设备驱动文件。
配置文件(ffconf.h)
功能 配置 | 默认值 | 说明 |
---|---|---|
FFCONF_DEF | 5380 | 修定版本ID |
FF_FS_READONLY | 0 | 0 - 读/写;1 - 只读 |
FF_FS_MINIMIZE | 0 | 0 - 基本功能全启用; 1 - 删除 f_stat()、f_getfree()、f_unlink()、f_mkdir()、f_truncate(); 2 - 除了1之外,还删除了f_opendir()、f_readdir()、f_closedir(); 3 - 除了2之外,还删除了f_lseek() |
FF_USE_FIND | 0 | 0 - 禁用f_findfirst()和f_findnet(); 1 - 启用; 2 - 同时启动匹配的 altname[] |
FF_USE_MKFS | 0 | 0 - 禁用f_mkfs();1 - 启用 |
FF_USE_FASTSEEK | 0 | 0 - 禁用快速寻道功能;1 - 启用 |
FF_USE_EXPAND | 0 | 0 - 禁用f_expand();1 - 启用 |
FF_USE_CHMOD | 0 | 0 - 禁用f_chmod()和f_utime();1 - 启用 |
FF_USE_LABEL | 0 | 0 - 禁用f_getlabel()和f_setlable();1 - 启用 |
FF_USE_FORWARD | 0 | 0 - 禁用f_forward();1 - 启用 |
FF_USE_STRFUNC | 0 | 使用字符串API:f_get()、f_putc()、f_puts()、f_printf() 0 - 禁用。FF_PRINT_LLI、FF_PRINT_FLOAT、FF_STRF_ENCODE 无效; 1 - 启用而不进行 LF-CRLF转换 2 - 启动LF-CRLF转换 |
FF_PRINT_LLI | 0 | 1 - 使用 f_printf()支持long long参数; |
FF_PRINT_FLOAT | 0 | 1/2 - 使用f_printf()支持浮点参数 |
FF_STRF_ENCODE | 3 | 0 - 当前CP中的ANSI/OEM;1 - UTF-16LE 中的Unicode;2 - UTF-16BE 中的Unicode;3 - UTF-8 中的Unicode |
区域/命名空间 配置 | 默认值 | 说明 |
---|---|---|
FF_CODE_PAGE | 932 | 932 - 日语; 936 - 简体中文; 0 - 包含所有并由f_setcp()配置 |
FF_USE_LFN | 0 | 0 - 禁用长文件名,FF_MAX_LFN无效; 1 - 在BSS上使用静态工作缓冲区启用LFN。始终非线程安全 2 - 在STACK上启用具有动态工作缓冲区的LFN 3 - 在HEAP上使用动态工作缓冲区启用LFN 要启用LFN,需要将ffunicode.c添加到项目中 |
FF_MAX_LFN | 255 | 缓冲区的大小 |
FF_LFN_UNICODE | 0 | 0 - 当前CP中的ANSI/OME (TCHAR= char) 1 - UTF-16中的Unicode (TCHAR= WCHAR) 2 - UTF-8中的Unicode (TCHAR= char) 3 - UTF-32中的Unicode (TCHAR= DWORD) |
FF_LFN_BUF | 255 | 定义FILINFO结构中文件名的大小 |
FF_SFN_BUF | 12 | |
FF_FS_RPATH | 0 | 0 - 禁用相对路径并删除相关API函数; 1 - 启用相对路径。f_chdir()和f_chdrive()可用; 2 - 除了1之外,还有f_getcwd()可用 |
驱动器/卷 配置 | 默认值 | 说明 |
---|---|---|
FF_VOLUMES | 1 | 卷(逻辑驱动器)数量。(1-10) |
FF_STR_VOLUME_ID | 0 | 1/2 - 可以使用任意字符串作为驱动器 |
FF_VOLUME_STRS | “RAM”, “NAND”, “CF”, “SD”, “SD2”, “USB”, “USB2”, “USB3” | 定义每个卷ID字符串 |
FF_MULTI_PARTITION | 0 | 0 - 每个逻辑驱动器号都绑定到同一个物理驱动器号; 1 - 每个逻辑驱动器号都可以绑定到VolToPart[]。另外f_fdisk()将可用 |
FF_MIN_SS | 512 | 扇区大小范围(512、1024、2048、4096) |
FF_MAX_SS | 512 | |
FF_LBA64 | 0 | 0 - 禁用64位LBA的支持;1 - 启用。要启用64位LBA,还需要启用exFAT。(FF_FS_EXFAT == 1) |
FF_MIN_GPT | 0x10000000 | 将GPT切换为f_mkfs()分区格式的最不扇区数 |
FF_USE_TRIM | 0 | 0 - 禁用ATA-TRIM的支持;1 - 启用。 |
系统 配置 | 默认值 | 说明 |
---|---|---|
FF_FS_TINY | 0 | 0 - 正常版本;1 - tiny版本 |
FF_FS_EXFAT | 0 | 0 - 禁用exFAT文件系统的支持;1 - 启用 |
FF_FS_NORTC | 0 | 0 - 启用时间戳功能,需要添加get_fattime(); 1 - 禁用时间戳 |
FF_NORTC_MON | 11 | FF_FS_NORTC ==0时,固定时间戳 |
FF_NORTC_MDAY | 1 | FF_FS_NORTC ==0时,固定时间戳 |
FF_NORTC_YEAR | 2014 | FF_FS_NORTC ==0时,固定时间戳 |
FF_FS_NOFSINFO | 0 | 0 - f_getfree()将强制完整的FAT扫描 |
FF_FS_LOCK | 0 | 0 - 关闭文件锁定功能; >0 - 启用。该值定义文件/子目录的数量 |
FF_FS_REENTRANT | 0 | 0 - 禁用重入。FF_FS_TIMEOUT没有效果 1 - 启用。ff_mutex_create()、ff_mutex_delete()、ff_mutex_take()和ff_mutex_give()必须添加到项目中。示例在ffsystem.c中 |
FF_FS_TIMEOUT | 1000 | 定义超时时间 |
应用程序接口
函数定义 | 说明 | 参数 |
---|---|---|
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); | 打开或创建文件 | mode: FA_READ FA_WRITE FA_OPEN_EXISTING FA_CREATE_NEW FA_CREATE_ALWAYS FA_OPEN_ALWAYS FA_OPEN_APPEND |
FRESULT f_close (FIL* fp); | 关闭一个打开的文件对象 | |
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); | 从文件读取数据 | |
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); | 将数据写入文件 | |
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); | 移动文件对象的文件指针 | |
FRESULT f_truncate (FIL* fp); | 截断文件 | |
FRESULT f_sync (FIL* fp); | 刷新写入文件的缓存数据 | |
FRESULT f_opendir (DIR* dp, const TCHAR* path); | 打开目录 | |
FRESULT f_closedir (DIR* dp); | 关闭打开的目录 | |
FRESULT f_readdir (DIR* dp, FILINFO* fno); | 读取目录项 | |
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); | 查找第一个文件 | |
FRESULT f_findnext (DIR* dp, FILINFO* fno); | 查找下一个文件 | |
FRESULT f_mkdir (const TCHAR* path); | 创建子目录 | |
FRESULT f_unlink (const TCHAR* path); | 删除现有文件或目录 | |
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); | 重命名/移动文件或目录 | |
FRESULT f_stat (const TCHAR* path, FILINFO* fno); | 获取文件状态 | |
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); | 更改文件/目录的属性 | |
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); | 更改文件/目录的时间戳 | |
FRESULT f_chdir (const TCHAR* path); | 更改当前目录 | |
FRESULT f_chdrive (const TCHAR* path); | 更改当前驱动器 | |
FRESULT f_getcwd (TCHAR* buff, UINT len); | 获取当前目录 | |
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); | 获取驱动器上的可用簇数 | |
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); | 获取卷标 | |
FRESULT f_setlabel (const TCHAR* label); | 设置卷标 | |
FRESULT f_forward (FIL* fp, UINT(func)(const BYTE,UINT), UINT btf, UINT* bf); | 将数据转发至流 | |
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); | 为文件分配一个连续的块 | |
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); | 安装/卸载逻辑驱动器 | |
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); | 创建 FAT 卷 | FM_FAT FM_FAT32 FM_EXFAT FM_ANY FM_SFD |
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); | 将物理驱动器划分为若干个分区 | |
FRESULT f_setcp (WORD cp); | 设置当前代码页 | |
int f_putc (TCHAR c, FIL* fp); | 将一个字符放入文件 | |
int f_puts (const TCHAR* str, FIL* cp); | 将字符串放入文件 | |
int f_printf (FIL* fp, const TCHAR* str, …); | 将格式化的字符串放入文件 | |
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); | 从文件中获取字符串 |
格式结构体 (MKFS_PARM) | 说明 | 枚举 |
---|---|---|
BYTE fmt; | 格式选项 | FM_FAT FM_FAT32 FM_EXFAT FM_SFD |
BYTE n_fat; | FAT 的数量 | |
UINT align; | 数据区对齐(扇区) | |
UINT n_root; | 根目录条目的数量 | |
DWORD au_size; | 簇大小(字节) |
文件系统结构体 (FATFS) | 说明 | 枚举 |
---|---|---|
BYTE fs_type; | 文件系统类型 (0:空白文件系统对象) | |
BYTE pdrv; | 托管物理驱动器的卷 | |
BYTE ldrv; | 逻辑驱动器号(仅在 FF_FS_REENTRANT 时使用) | |
BYTE n_fats; | FAT 数量(1 或 2) | |
BYTE wflag; | win[] 状态 (1:dirty) | |
BYTE fsi_flag; | 分配信息控制 (b7:disabled, b0:dirty) | |
WORD id; | 卷安装 ID | |
WORD n_rootdir; | 根目录条目数 (FAT12/16) | |
WORD csize; | 簇大小 [扇区] | |
WORD ssize; | 扇区大小 (512、1024、2048 或 4096) | |
WCHAR* lfnbuf; | LFN 工作缓冲区 | |
BYTE* dirbuf; | exFAT 的目录条目块暂存缓冲区 | |
DWORD last_clst; | 最后分配的簇 | |
DWORD free_clst; | 空闲簇的数量 | |
DWORD cdir; | 当前目录起始簇 (0:root) | |
DWORD cdc_scl; | 包含目录起始簇(cdir 为 0 时无效) | |
DWORD cdc_size; | b31-b8:包含目录的大小,b7-b0:链状态 | |
DWORD cdc_ofs; | 包含目录中的偏移量(cdir 为 0 时无效) | |
DWORD n_fatent; | FAT 条目数(簇数 + 2) | |
DWORD fsize; | 每个 FAT 的扇区数 | |
LBA_t volbase; | 卷基扇区 | |
LBA_t fatbase; | FAT基扇区 | |
LBA_t dirbase; | 根目录基扇区 (FAT12/16) 或簇 (FAT32/exFAT) | |
LBA_t database; | 数据基扇区 | |
LBA_t bitbase; | 分配位图基扇区 | |
LBA_t winsect; | 当前在 win[] 的扇区 | |
BYTE win[FF_MAX_SS]; | 磁盘访问窗口 |
FILINFO
文件信息结构体 (FILINFO) | 说明 | 枚举 |
---|---|---|
FSIZE_t fsize; | 文件大小 | |
WORD fdate; | 修改日期 | |
WORD ftime; | 修改时间 | |
BYTE fattrib; | 文件属性 | AM_RDO - 只读 AM_HID - 隐藏 AM_SYS - 系统 AM_DIR - 目录 AM_ARC - 存档 |
TCHAR altname[FF_SFN_BUF + 1]; | 替代文件名 | |
TCHAR fname[FF_LFN_BUF + 1]; | 主文件名 | |
TCHAR fname[12 + 1]; | 文件名 |
FRESULT
返回枚举 (FRESULT) | 说明 |
---|---|
FR_OK = 0 | (0) 函数成功 |
FR_DISK_ERR | (1)低级磁盘 I/O 层发生硬错误 |
FR_INT_ERR | (2) 断言失败 |
FR_NOT_READY | (3)物理驱动器不工作 |
FR_NO_FILE | (4) 找不到文件 |
FR_NO_PATH | (5) 找不到路径 |
FR_INVALID_NAME | (6) 路径名格式无效 |
FR_DENIED | (7) 由于禁止访问或目录已满而拒绝访问 |
FR_EXIST | (8) 由于禁止访问而拒绝访问 |
FR_INVALID_OBJECT | (9) 文件/目录对象无效 |
FR_WRITE_PROTECTED | (10)物理驱动器受到写保护 |
FR_INVALID_DRIVE | (11) 逻辑驱动器号无效 |
FR_NOT_ENABLED | (12)没有可用的文件系统对象 |
FR_NO_FILESYSTEM | (13)找不到有效的 FAT 卷 |
FR_MKFS_ABORTED | (14)f_mkfs 函数由于某些问题中止 |
FR_TIMEOUT | (15)无法在定义的时间内控制卷 |
FR_LOCKED | (16) 根据文件共享策略拒绝该操作 |
FR_NOT_ENOUGH_CORE | (17) 无法分配 LFN 工作缓冲区或给定的缓冲区大小不足 |
FR_TOO_MANY_OPEN_FILES | (18) 打开文件数 > FF_FS_LOCK |
FR_INVALID_PARAMETER | (19) 给定的参数无效 |
链接 diskio
typedef struct
{
DSTATUS (*disk_initialize) (BYTE);
DSTATUS (*disk_status) (BYTE);
DRESULT (*disk_read) (BYTE, BYTE*, DWORD, UINT);
#if FF_FS_READONLY == 0
DRESULT (*disk_write) (BYTE, const BYTE*, DWORD, UINT);
#endif
DRESULT (*disk_ioctl) (BYTE, BYTE, void*);
} Diskio_drvTypeDef;
typedef struct
{
uint8_t is_initialized[FF_VOLUMES];
const Diskio_drvTypeDef *drv[FF_VOLUMES];
uint8_t lun[FF_VOLUMES];
volatile uint8_t nbr;
} Disk_drvTypeDef;
// 链接驱动器并增加活动驱动器的数量。返回: 0 - 成功; 1 - 失败。
uint8_t FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path);
uint8_t FATFS_LinkDriverEx(const Diskio_drvTypeDef *drv, char *path, BYTE lun);
// 取消驱动器的链接,并减少活动链接的数量 返回:0 - 成功; 1 - 失败。
uint8_t FATFS_UnLinkDriver(char *path);
uint8_t FATFS_UnLinkDriverEx(char *path, BYTE lun);
// 获取链接到FatFs的驱动器数量。
uint8_t FATFS_GetAttachedDriversNbr(void);
例子:
FATFS fs; // 文件系统对象
FIL fp; // 文件对象
char SDPath[4]; /* SD逻辑驱动器路径 */
uint8_t res = FATFS_LinkDriver(&SD_Driver, SDPath);
if(res == 0 ) // 成功
{
// 加载驱动器
res = f_mount(&fs,SDPath,1);
if(res != FR_OK)
{
Error_Handler();
}
// 以写方式打开文件,如果不存在则创建
res = f_open(&fp, "text.txt", FA_CREATE_ALWAYS | FA_WRITE);
if(res != FR_OK)
{
Error_Handler();
}
else
{
// 写内容
uint8_t write_text[] = "Test";
uint32_t write_bytes = 0
res = f_write(&fp, write_text, strlen(write_text), &write_bytes );
// ...
}
// 关闭文件
if (f_close(&fp) != FR_OK )
{
Error_Handler();
}
// 弹出驱动器
f_mount(&fs,SDPath, 0);
// 断开链接
FATFS_UnLinkDriver(SDPath);
}