FATFS文件系统架构及源码介绍

前言:

FATFS作为一个优秀的文件系统开源项目,具有高性能、易移植的特点。本文主要分二个部分:FATFS的架构介绍、源码剖析。

开发文档下载地址:https://download.csdn.net/download/wjb123sw99/15663489?spm=1001.2014.3001.5501

架构:

FATFS处于应用层和磁盘IO层之间,对应用层提供的接口封装风格与标准C的文件操作接口风格一致,应用程序只需进行少量的修改即可使用。对与磁盘IO层,FATFS完全与其分开,开发人员需要自己实现FATFS中diskio.h中声明的磁盘控制函数,其架构如下:

 

源码剖析:

FATFS源代码精简,只包括diskio.h、diskio.c、ff.h、ff.c、ffconf.h、ffsystem.c、ffunicode.h七个源码文件,其调用顺序如下:

 

diskio:

diskio为FATFS项目的磁盘接口模块,为FATFS提供磁盘控制函数。

磁盘控制函数返回值定义:

DRESULT定义

描述

RES_OK

成功

RES_ERROR

读写失败

RES_WRPRT

写保护

RES_NOTRDY

未准备好

RES_PARERR

参数错误

磁盘状态定义:

DSTATUS定义

描述

STA_NOINIT

未初始化驱动器

STA_NODISK

驱动器中没有介质(未找到物理磁盘)

STA_PROTECT

写保护

初始化驱动函数:

接口定义

DSTATUS disk_initialize (BYTE pdrv);

参数说明

输入:pdrv:物理驱动器号,用于识别驱动器。

返回值:成功返回0,失败返回DSTATUS定义错误码

备注

该函数用于初始化驱动器,开发者可在此处定义磁盘驱动初始化逻辑,如果磁盘驱动无需初始化则直接返回0。

获取驱动状态函数:

接口定义

DSTATUS disk_status (BYTE pdrv);

参数说明

输入:pdrv:物理驱动器号,用于识别驱动器。

返回值:成功返回0,失败返回DSTATUS定义错误码

备注

该函数用于获取驱动器状态,如果有异常则返回DSTATUS定义的异常类型,如果正常则返回0。

磁盘读函数:

接口定义

DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);

参数说明

输入:pdrv:物理驱动器号,用于识别驱动器。

      buff:用于存储读取数据的缓存,大小为count*扇区大小

      sector:读取数据起始扇区号

      count: 读取扇区个数  

输出:buff: 读取的数据

返回值:成功返回0,失败返回DRESULT定义错误码

备注

FATFS扇区大小可进行配置,默认扇区大小为512字节。一般情况下设备的扇区大小是固定的即FF_MIN_SS == FF_MAX_SS。此时disk_read函数读取count参数恒为1,即单次读取数据大小为磁盘扇区大小。Sector扇区号从0开始计数,例如8GB的磁盘,扇区号取值范围在[0, 16777216)

磁盘写函数:

接口定义

DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);

参数说明

输入:pdrv:物理驱动器号,用于识别驱动器。

      buff:待写入数据,大小为count*扇区大小

      sector:写入数据起始扇区号

      count: 读取扇区个数  

返回值:成功返回0,失败返回DRESULT定义错误码

备注

FATFS扇区大小可进行配置,默认扇区大小为512字节。一般情况下设备的扇区大小是固定的即FF_MIN_SS == FF_MAX_SS。此时disk_write函数读取count参数恒为1,即单次读取数据大小为磁盘扇区大小。sector扇区号从0开始计数,例如8GB的磁盘,扇区号取值范围在[0, 16777216)

磁盘命令函数:

接口定义

DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);

参数说明

输入:pdrv:物理驱动器号,用于识别驱动器。

      cmd:命令

      buff:发送数据

输出:buff:接收数据

返回值:成功返回0,失败返回DRESULT定义错误码

备注

FATFS通过下发命令实现特点功能,开发人员需要根据实际情况针对不同命令进行实现。

cmd命令定义:

cmd定义

描述

CTRL_SYNC

disk_ioctl接收到该命令,如果磁盘具有缓存的功能,则需要将缓存数据立即刷新到磁盘介质中存储。如果磁盘没有缓存数据的功能则无需进行任何操作。

GET_SECTOR_COUNT

disk_ioctl接收到该命令,需要在buff中输出磁盘扇区的数量

GET_SECTOR_SIZE

disk_ioctl接收到该命令,需要在buff中输出磁盘扇区的大小,仅当FF_MAX_SS> FF_MIN_SS时才需要此命令。

GET_BLOCK_SIZE

disk_ioctl接收到该命令,可以选择在buff中填充擦除块的大小,返回在[0, 32768],也可以选择不做任何操作。

CTRL_TRIM

disk_ioctl接收到该命令,可以选择擦除buff中指定的扇区号数组,也可以不做任何操作。

FF:

ff为FATFS项目提供各种文件系统功能函数。

文件系统功能函数定义:

FRESULT定义

描述

FR_OK

成功

FR_DISK_ERR

磁盘错误,底层disk_read、disk_write或disk_ioctl函数调用发生错误时返回。

FR_INT_ERR

程序断言错误,该问题大多数情况下是由于工作区堆栈溢出导致

FR_NOT_READY

文件系统没有准备好,该问题是由于调用disk_initialize报错导致的

FR_NO_FILE

没有该文件

FR_NO_PATH

没有该路径

FR_INVALID_NAME

无效名称,请检查编码问题或者FF_MAX_LFN小于文件名

FR_DENIED

禁止访问,可能是文件权限问题或者磁盘已满

FR_EXIST

对象已存在

FR_INVALID_OBJECT

无效对象,可能是句柄已关闭或者磁盘驱动未准备好

FR_WRITE_PROTECTED

写保护

FR_INVALID_DRIVE

无效驱动

FR_NOT_ENABLED

驱动器工作区尚未未通过f_mount函数注册

FR_NO_FILESYSTEM

没有有效的FAT卷,该错误建议重新格式化磁盘文件系统

FR_MKFS_ABORTED

调用f_mkfs函数报错,可能是由于f_mkfs入参错误,或者是磁盘IO提供的可用扇区太小(>=128个扇区)

FR_TIMEOUT

超时,不能在规定的时间内获得访问卷的授权

FR_LOCKED

根据文件共享策略拒绝此操作

FR_NOT_ENOUGH_CORE

工作缓冲区长度不足

FR_TOO_MANY_OPEN_FILES

打开文件数 > FF_FS_LOCK

FR_INVALID_PARAMETER

无效参数

FATFS提供的f_open、fclose等文件操作函数与POSIX标准提供的fopen、fclose等文件操作函数调用方法基本一致,应用程序只需进行少许修改即可应用,例子如下:

#include <stdio.h>

#include "ff.h"



int main()

{

FATFS fs0;   /* Fatfs驱动句柄 */

FIL fsrc;    /* 文件句柄 */

BYTE buffer[4096];

FRESULT fr;  /* FatFs函数返回值 */

UINT br;    /* File read/write count */



/* 挂载驱动 */

f_mount(&fs0, "0:", 0);



/* 打开文件句柄 */

fr = f_open(&fsrc, "0:file.bin", FA_WRITE | FA_CREATE_ALWAYS);

if (fr)

{

f_unmount("0:");

return (int)fr;

}



/*  写数据 */

fr = f_write(&fsrc, buffer, sizeof buffer, &br);

if (fr)

{

f_close(&fsrc);

f_unmount("0:");

return (int)fr;

}

if (br != sizeof buffer)

{

/* 实际写入字节数不对 */

f_close(&fsrc);

f_unmount("0:");

return -1;

}



/* 关闭文件句柄 */

f_close(&fsrc);



/* 卸载驱动*/

f_unmount("0:");



return (int)fr;

}

POSIX标准的fopen函数文件标志与FATFS的f_open函数文件标志对应关系如下:

POSIX mode定义

FATFS mode 定义

"r"

FA_READ

"r+"

FA_READ | FA_WRITE

"w"

FA_CREATE_ALWAYS | FA_WRITE

"w+"

FA_CREATE_ALWAYS | FA_WRITE | FA_READ

"a"

FA_OPEN_APPEND | FA_WRITE

"a+"

FA_OPEN_APPEND | FA_WRITE | FA_READ

"wx"

FA_CREATE_NEW | FA_WRITE

"w+x"

FA_CREATE_NEW | FA_WRITE | FA_READ

ffconf:

ffconf为FATFS的功能配置模块,开发者可以根据需求修改对应参数,

参数名

描述

FFCONF_DEF

配置文件修订ID

如果ffconf配置文件中定义的FFCONF_DEF与ff.h中定义的FF_DEFINED不一致,则会报错,代码如下:

#if FF_DEFINED != FFCONF_DEF

#error Wrong configuration file (ffconf.h).

#endif

FF_FS_READONLY

配置读写模式

当该参数设置为0时表示FATFS支持读写,当该参数设置为1是表示FATFS为只读模式。

FF_FS_MINIMIZE

配置FATFS最小化级别

0:基本功能完全开启。

1: 删除f_stat (), f_getfree (), f_unlink (), f_mkdir (), f_truncate()和f_rename ()

2: 在1基础上,删除f_opendir(), f_readdir()和f_closedir()。

3: 在1、2基础上,删除f_lseek()。

FF_USE_STRFUNC

配置字符串函数f_gets(), f_putc(), f_puts() and f_printf().

0:不支持这些函数

1:支持这些函数,但不支持 LF-CRLF

2:支持这些函数,且支持 LF-CRLF

FF_USE_FIND

配置文件检索函数 f_findfirst() 、f_findnext()

0:不支持这些函数

1:支持这些函数,匹配fname 主要名称

2:支持这些函数,同时检索altname替代名称

相关信息在结构体FILINFO中有定义,

#if FF_USE_LFN

    TCHAR altname [FF_SFN_BUF +1]; / *替代对象名称* /

    TCHAR fname [FF_LFN_BUF +1];   / *主要对象名称* /

#else

FF_USE_MKFS

配置f_mkfs()函数

0:不启用

1:启用

FF_USE_FASTSEEK

配置快速寻道功能,启用时会在FIL句柄中建立映射表加快查找

0:不启用

1:启用

FF_USE_EXPAND

配置f_expand函数

0:不启用

1:启用

FF_USE_CHMOD

配置 f_chmod() 和f_utime()函数

0:不启用

1:启用

FF_USE_LABEL

配置f_getlabel()和f_setlabel()函数

0:不启用

1:启用

FF_USE_FORWARD

配置f_forward()函数

0:不启用

1:启用

FF_CODE_PAGE

此选项指定要在目标系统上使用的OEM代码页。

FF_USE_LFN

配置长文件名支持

0:不支持长文件名。FF_MAX_LFN没有作用。

1:在BSS上开启FF_MAX_LFN和静态工作缓冲区。但不是线程安全的。

2:在堆栈上开启FF_MAX_LFN与动态工作缓冲区。

3:在堆上启用FF_MAX_LFN和动态工作缓冲区。

FF_MAX_LFN

最大文件名

FF_LFN_UNICODE

切换字符编码

0: ANSI/OEM (TCHAR = char)

1: UTF-16中的Unicode (TCHAR = WCHAR)

2: Unicode的UTF-8 (TCHAR = char)

3: Unicode在UTF-32 (TCHAR = DWORD)

FF_LFN_BUF

当开启检索功能时,F_LFN_BUF定义了FILINFO结构体中fname的缓存长度

FF_SFN_BUF

当开启检索功能时,FF_SFN_BUF定义了FILINFO结构体中altname的缓存长度

FF_STRF_ENCODE

用于转换字符串IO函数的字符编码

0: ANSI/OEM

1: UTF-16LE格式的Unicode

2: UTF-16BE格式的Unicode

3: UTF-8格式的Unicode

FF_FS_RPATH

配置相对路径支持

0: 禁用相对路径

1: 启用相对路径。f_chdir()和f_chdrive()可用

2: 启用相对路径。f_chdir()和f_chdrive()、 f_getcwd()可用

FF_VOLUMES

要使用的卷(逻辑驱动器)的数量,取值范围[1, 10]

FF_STR_VOLUME_ID

自定义卷ID

0: 关闭

1: 开启

FF_VOLUME_STRS

自定义卷名

FF_MULTI_PARTITION

配置驱动器上卷数量

0:只绑定一个卷号

1:支持绑定多个卷

FF_MIN_SS

扇区最小字节数,一般FF_MIN_SS==FF_MAX_SS

FF_MAX_SS

扇区最大字节数,一般FF_MIN_SS==FF_MAX_SS

FF_LBA64

配置支持64位LAB(逻辑区块地址)

0:不支持

1:支持

FF_MIN_GPT

FF_LBA64启动时,FF_MIN_GPT值等于GPT分区格式的最小扇区数

FF_USE_TRIM

配置支持项ATA-TRIM

0:不支持

1:支持

FF_FS

TINY

配置小缓冲区

0:正常

1:小

FF_FS_EXFAT

配置exFAT文件系统的支持

0:不支持

1:支持

FF_FS_NORTC

切换时间戳配置

0:使用get_fattime()函数返回的时间戳

1:使用FF_NORTC_MON FF_NORTC_MDAY FF_NORTC_YEAR默认时间戳

FF_NORTC_MON

默认月份

FF_NORTC_MDAY

默认天

FF_NORTC_YEAR

默认年份

FF_FS_NOFSINFO

配置 f_getfree()函数

0:启用

1:禁止

FF_FS_LOCK

配置文件锁定

0:关闭文件锁定功能

1:打开文件锁定功能

FF_FS_REENTRANT

配置FatFs的可重入性

0:禁用重入。FF_FS_TIMEOUT和FF_SYNC_t不起作用。

1:启用重入。另外,用户提供的同步处理程序

FF_FS_TIMEOUT

定义超时时间

FF_SYNC_t

同步对象类型

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值