Fatfs系统移植

目录

1. 简介

1.1 Fatfs目录结构

1.1.1  documents

1.1.2 source 

2. ffconf.h

2.1 FFCONF_DEF

2.2 FF_FS_READONLY 

2.3 FF_FS_MINIMIZE

2.4 FF_USE_FIND

2.5 FF_USE_MKFS

2.6 FF_USE_FASTSEEK

2.7 FF_USE_EXPAND

2.8 FF_USE_CHMOD

2.9 FF_USE_LABEL 

2.10 FF_USE_FORWARD

 2.11 FF_CODE_PAGE

2.12 FF_USE_LFN

2.13 FF_MAX_LFN

2.14 FF_LFN_UNICODE

2.15 FF_LFN_BUF、FF_SFN_BUF

2.16  FF_FS_RPATH

2.17 FF_VOLUMES

2.18 FF_VOLUME_STRS

2.19 FF_MULTI_PARTITION

2.20 FF_MIN_SS, FF_MAX_SS 

2.21 FF_USE_TRIM 

2.22 FF_FS_NOFSINFO

2.23 FF_FS_TINY

2.24 FF_FS_EXFAT

2.25 FF_FS_NORTC

2.26 FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR 

2.27 FF_FS_LOCK

2.28 FF_FS_REENTRANT

2.29 FF_FS_TIMEOUT

2.30 FF_SYNC_t

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

4.1 disk_status

4.2 disk_initialize

 4.3 disk_read

4.4 disk_write

4.5 disk_ioctl

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;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 硬件平台选择 首先,需要选择一个适合自己应用的硬件平台,可以根据自己的需求选择不同的平台,比如STM32、GD32、ESP32、Arduino等等。 在本文中,我们选择了GD32F303VCT6作为硬件平台。 2. FatFs库介绍 FatFs是一个轻量级的文件系统,支持FAT12、FAT16、FAT32等多种文件系统格式,可以在各种嵌入式系统中运行。FatFs提供了一组API函数,可以方便地对文件系统进行读写操作。 3. 移植步骤 步骤一:创建工程 首先,需要创建一个GD32的Keil工程,选择自己的芯片型号。然后,在工程目录下新建一个fatfs文件夹,用于存放FatFs库和相关的驱动代码。 步骤二:添加FatFs库 将FatFs库添加到工程中。可以在官网上下载最新的FatFs库,然后将其解压到fatfs文件夹下。 步骤三:配置FatFsfatfs文件夹下创建一个diskio.h文件,用于定义磁盘驱动接口。然后,在fatfs文件夹下创建一个ffconf.h文件,用于配置FatFs的一些参数,比如支持的文件系统格式、簇大小等等。 步骤四:实现磁盘驱动接口 在diskio.h文件中,定义以下磁盘驱动接口: ``` DSTATUS disk_initialize(BYTE pdrv); DSTATUS disk_status(BYTE pdrv); DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count); DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count); DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff); ``` 这些接口函数需要在磁盘驱动文件中实现,比如SD卡驱动文件sdio_sd.c中就实现了这些接口函数。 步骤五:初始化FatFs 在main函数中,调用以下代码初始化FatFs: ``` FATFS fs; FRESULT res; res = f_mount(&fs, "", 1); if (res != FR_OK) { // mount failed } ``` 这段代码将FatFs挂载到默认的磁盘上,如果挂载失败,则说明磁盘不存在或者格式不支持。 步骤六:使用FatFs 使用FatFs的API函数对文件系统进行读写操作,比如: ``` FIL file; FRESULT res; res = f_open(&file, "file.txt", FA_READ); if (res != FR_OK) { // open failed } char buf[128]; UINT read_bytes; res = f_read(&file, buf, sizeof(buf), &read_bytes); if (res != FR_OK) { // read failed } f_close(&file); ``` 这段代码打开一个名为file.txt的文件,并读取其中的内容。 至此,FatFs文件系统移植工作完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值