FATFS学习(2.3):ff.h

发布于:2025-02-27 ⋅ 阅读:(11) ⋅ 点赞:(0)

一:/* File information structure (FILINFO) */

typedef struct {
	FSIZE_t	fsize;			/* File size */
	WORD	fdate;			/* Modified date */
	WORD	ftime;			/* Modified time */
	BYTE	fattrib;		/* File attribute */
#if FF_USE_LFN
	TCHAR	altname[FF_SFN_BUF + 1];/* Alternative file name */
	TCHAR	fname[FF_LFN_BUF + 1];	/* Primary file name */
#else
	TCHAR	fname[12 + 1];	/* File name */
#endif
} FILINFO;

FILINFO 结构体分析总结

FILINFO 是 FatFs 文件系统库中用于存储 文件或目录元数据 的结构体,提供文件大小、属性、时间戳及文件名等信息。其成员根据配置选项(如 FF_USE_LFN)动态调整,支持不同文件系统的特性(如长文件名)。


核心成员变量解析
成员变量 类型 说明
fsize FSIZE_t 文件大小:以字节为单位,FSIZE_t 通常为 DWORD 或 QWORD(64位),支持大文件。
fdate WORD 修改日期:编码为 FAT 日期格式(详见下文)。
ftime WORD 修改时间:编码为 FAT 时间格式(详见下文)。
fattrib BYTE 文件属性:位掩码值,如 AM_DIR(目录)、AM_RDO(只读)等。
altname TCHAR[] 短文件名(8.3格式):仅在启用 FF_USE_LFN 时存在,用于兼容 FAT 传统格式。
fname TCHAR[] 文件名
FF_USE_LFN 禁用时:短文件名(fname[13])。
FF_USE_LFN 启用时:长文件名(fname[FF_LFN_BUF+1])。

关键特性说明
  1. FAT 日期和时间编码

    • fdate:16 位格式为 0bYYYYYYYMMMMDDDDD,其中:

      • YYYYYYY = 年 - 1980(范围 0-127,即 1980-2107)。

      • MMMM = 月(1-12)。

      • DDDDD = 日(1-31)。

    • ftime:16 位格式为 0bHHHHHMMMMMMSSSSS,其中:

      • HHHHH = 小时(0-23)。

      • MMMMMM = 分钟(0-59)。

      • SSSSS = 秒/2(0-29,实际秒数为值×2)。

  2. 文件属性(fattrib

    属性宏 说明
    AM_RDO 0x01 只读文件
    AM_HID 0x02 隐藏文件
    AM_SYS 0x04 系统文件
    AM_DIR 0x10 目录
    AM_ARC 0x20 归档标记(备份用)
  3. 文件名存储

    • 短文件名altname):8.3 格式(如 FILENAME.TXT),ASCII 编码。

    • 长文件名fname):Unicode(UTF-16 或 UTF-8,由 FF_LFN_UNICODE 配置)。

    • 缓冲区大小

      • altnameFF_SFN_BUF + 1(默认 13 字节,兼容 8.3 格式)。

      • fnameFF_LFN_BUF + 1(默认 255 字节,支持长文件名)。


配置选项影响
配置宏 影响成员变量 功能扩展说明
FF_USE_LFN altnamefname 启用长文件名支持,同时存储短名和长名。
FF_LFN_UNICODE fname 编码 长文件名使用 Unicode 编码(否则为 ANSI/OEM)。

FILINFO 的使用场景

  1. 获取文件信息
    通过 f_stat() 获取文件元数据:

    FILINFO fno;
    FRESULT res = f_stat("file.txt", &fno);
    if (res == FR_OK) {
        printf("Size: %lu bytes\n", fno.fsize);
        printf("Name: %s\n", fno.fname);
    }
  2. 遍历目录项
    结合 f_readdir() 读取目录内容:

DIR dir;
FILINFO fno;
f_opendir(&dir, "/");
while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
    printf("%s\n", fno.fname);
}
f_closedir(&dir);
  1. 过滤文件类型
    根据 fattrib 判断是否为目录或隐藏文件:

    if (fno.fattrib & AM_DIR) {
        printf("This is a directory.\n");
    }
    if (fno.fattrib & AM_HID) {
        printf("This is a hidden file.\n");
    }

日期和时间解码示例

将 fdate 和 ftime 转换为可读格式:

void decode_fat_time(WORD date, WORD time) {
    int year = ((date >> 9) & 0x7F) + 1980;
    int month = (date >> 5) & 0x0F;
    int day = date & 0x1F;

    int hour = (time >> 11) & 0x1F;
    int minute = (time >> 5) & 0x3F;
    int second = (time & 0x1F) * 2;

    printf("Last modified: %04d-%02d-%02d %02d:%02d:%02d\n",
           year, month, day, hour, minute, second);
}

注意事项

  1. 长文件名配置

    • 启用 FF_USE_LFN 会增加内存占用(需定义 FF_LFN_BUF 大小)。

    • 若使用 Unicode,需确保系统编码一致(如 UTF-8)。

  2. 时间戳的局限性

    • FAT 时间戳精度为 2 秒(秒字段存储值为实际秒数的一半)。

    • 不支持创建时间或访问时间(仅修改时间)。

  3. 文件名缓冲区溢出

    • 长文件名可能超出 FF_LFN_BUF,需合理设置缓冲区大小。


总结

  • FILINFO 结构体 是 FatFs 中管理文件元数据的核心,涵盖大小、时间、属性及文件名。

  • 短文件名与长文件名 通过条件编译支持,适应不同文件系统需求。

  • 日期和时间 需按 FAT 格式解码,属性通过位掩码判断。

  • 典型应用 包括文件信息查询、目录遍历和文件过滤。

二:/* Format parameter structure (MKFS_PARM) */

typedef struct {
	BYTE fmt;			/* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
	BYTE n_fat;			/* Number of FATs */
	UINT align;			/* Data area alignment (sector) */
	UINT n_root;		/* Number of root directory entries */
	DWORD au_size;		/* Cluster size (byte) */
} MKFS_PARM;

成员变量分析

  1. fmt

    • 类型BYTE

    • 作用: 指定文件系统类型。

    • 可选值:

      • FM_FAT: 传统 FAT12/FAT16 文件系统(适用于小容量存储设备)。

      • FM_FAT32: FAT32 文件系统(支持大分区,广泛用于 USB 驱动器和 SD 卡)。

      • FM_EXFAT: exFAT 文件系统(专为大文件和闪存优化,支持更大的单文件和分区)。

      • FM_SFD: Super Floppy 格式(将整个磁盘视为单一 FAT 卷,如软盘或某些虚拟磁盘)。

  2. n_fat

    • 类型BYTE

    • 作用: 指定 FAT 表的数量。

    • 典型值:

      • 1 或 2(默认值通常为 2,用于冗余备份)。

    • 注意:

      • 多个 FAT 表可提高文件系统容错性(例如 FAT1 损坏时可用 FAT2 恢复)。

  3. align

    • 类型UINT

    • 作用: 数据区对齐的扇区数。

    • 用途:

      • 优化磁盘访问性能(如对齐到物理扇区或 SSD 的擦除块边界)。

      • 避免因未对齐导致的读写效率下降(尤其是在高级格式磁盘或 RAID 场景)。

  4. n_root

    • 类型UINT

    • 作用: 根目录条目数(仅对 FAT12/16 有效)。

    • 典型值:

      • FAT12/16 默认值为 512(即根目录最多存储 512 个文件/目录项)。

    • 注意:

      • 在 FAT32/exFAT 中,根目录为动态链表结构,此参数可能被忽略。

  5. au_size

    • 类型DWORD

    • 作用: 簇(Cluster)的大小(字节单位)。

    • 影响:

      • 小簇:节省空间但增加 FAT 表大小和碎片风险。

      • 大簇:减少碎片但浪费空间(如存储大量小文件时)。

    • 典型值:

      • 根据分区大小自动计算,但可手动指定(如 4096、8192 字节)。


关键设计思想

  1. 灵活性

    • 通过组合不同参数,支持多种文件系统类型(FAT/exFAT)和存储介质(U盘、SD卡、虚拟磁盘)。

    • 允许开发者控制底层细节(如对齐、簇大小)以优化性能或兼容性。

  2. 兼容性

    • FM_SFD 选项保留了传统软盘格式的支持,体现对旧设备的兼容性。

    • n_root 的存在是为了兼容 FAT12/16 的固定根目录结构。

  3. 性能优化

    • align 和 au_size 参数直接关联磁盘 I/O 效率,适用于对性能敏感的场景(如嵌入式系统或实时数据处理)。


典型应用场景

  1. 格式化工具

    • 在命令行或 GUI 工具中,用户通过设置 MKFS_PARM 的参数自定义格式化行为(如指定簇大小或对齐)。

    • 例如:mkfs.fat -F 32 -s 4096 -S 512 /dev/sda1(对应 fmt=FM_FAT32au_size=4096align=1)。

  2. 嵌入式系统

    • 在资源受限的设备中,通过调整参数平衡存储效率和性能(如为日志文件分配大簇以减少碎片)。

  3. 文件系统驱动开发

    • 在实现 FAT/exFAT 驱动时,该结构体作为核心配置传递给底层格式化函数。


潜在问题与注意事项

  1. 参数冲突

    • 某些组合可能无效(如为 exFAT 指定 n_root 会被忽略)。需根据 fmt 类型验证参数合法性。

  2. 簇大小限制

    • FAT32 的簇大小范围受分区大小限制(如 4KB~32KB)。手动设置时需符合规范。

  3. 对齐与物理扇区

    • 若 align 不匹配磁盘物理扇区大小(如 4K 高级格式磁盘),可能导致性能下降。


总结

MKFS_PARM 是一个高度面向文件系统底层细节的结构体,通过精确控制格式化参数,开发者可以适配不同硬件特性和应用需求。其设计体现了对 FAT 家族文件系统的历史兼容性和现代存储需求的平衡。在实际使用中,需结合具体文件系统规范和硬件特性选择参数。

三:/* File function return code (FRESULT) */

typedef enum {
	FR_OK = 0,				/* (0) Succeeded */
	FR_DISK_ERR,			/* (1) A hard error occurred in the low level disk I/O layer */
	FR_INT_ERR,				/* (2) Assertion failed */
	FR_NOT_READY,			/* (3) The physical drive cannot work */
	FR_NO_FILE,				/* (4) Could not find the file */
	FR_NO_PATH,				/* (5) Could not find the path */
	FR_INVALID_NAME,		/* (6) The path name format is invalid */
	FR_DENIED,				/* (7) Access denied due to prohibited access or directory full */
	FR_EXIST,				/* (8) Access denied due to prohibited access */
	FR_INVALID_OBJECT,		/* (9) The file/directory object is invalid */
	FR_WRITE_PROTECTED,		/* (10) The physical drive is write protected */
	FR_INVALID_DRIVE,		/* (11) The logical drive number is invalid */
	FR_NOT_ENABLED,			/* (12) The volume has no work area */
	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume */
	FR_MKFS_ABORTED,		/* (14) The f_mkfs() aborted due to any problem */
	FR_TIMEOUT,				/* (15) Could not get a grant to access the volume within defined period */
	FR_LOCKED,				/* (16) The operation is rejected according to the file sharing policy */
	FR_NOT_ENOUGH_CORE,		/* (17) LFN working buffer could not be allocated */
	FR_TOO_MANY_OPEN_FILES,	/* (18) Number of open files > FF_FS_LOCK */
	FR_INVALID_PARAMETER	/* (19) Given parameter is invalid */
} FRESULT;

概述

FRESULT 是一个枚举类型,用于表示文件系统操作(如读写文件、目录操作、格式化等)的返回状态。它是文件系统库(如 FatFs)中的核心错误码设计,通过明确的状态值帮助开发者诊断操作失败的原因。每个枚举成员对应一种特定类型的成功或错误状态,注释中的 (n) 表示其底层整数值(例如 FR_OK 的值为 0)。


枚举成员详解

枚举成员 描述
FR_OK 0 操作成功。所有函数执行成功的默认返回值。
FR_DISK_ERR 1 底层磁盘 I/O 错误。可能是硬件故障(如存储介质损坏、连接断开)。
FR_INT_ERR 2 断言失败或内部逻辑错误。通常由代码缺陷或内存损坏引发。
FR_NOT_READY 3 物理驱动器未就绪。例如 SD 卡未插入或未初始化完成。
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 物理驱动器写保护。例如 SD 卡的写保护开关开启。
FR_INVALID_DRIVE 11 无效的逻辑驱动器号。指定的驱动器编号超出范围。
FR_NOT_ENABLED 12 卷未挂载或工作区未分配。需先调用 f_mount 挂载文件系统。
FR_NO_FILESYSTEM 13 未找到有效的文件系统。分区未格式化或格式不被支持(如非 FAT/exFAT)。
FR_MKFS_ABORTED 14 格式化操作中止。可能因参数错误或磁盘问题导致无法完成格式化。
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 参数非法。调用函数时传入无效参数(如空指针或越界值)。