.. _fat文件系统: fat文件系统 =============================== | FatFs是一个通用的文件系统,SDK的FAT文件系统驱动包含完整FAT驱动、简易FAT驱动(Simple_FAT)两种,区别如表格所示":ref:`FAT文件系统简易驱动 & FAT文件系统完整驱动`"; | 两种FAT驱动均不支持对sector大小大于512byte的FAT文件系统进行写操作,读操作正常; | Simple_FAT为FAT裁切版,只能通过路径打开文件和读文件接口; | 完整FAT文件系统驱动能使用的接口如下图所示: .. image:: fat_func_ops.jpg :alt: "fat文件系统支持的接口" :align: center .. centered:: 图1.3 fat文件系统支持的接口 FAT文件系统管理函数 ################################ 下面的函数为仅FAT使用的接口,在app/\bsp/\common/\fs/\fat/\fat_resource.c中的fat_demo()接口,可以找到下列函数的使用示例; 函数int fs_ftell(void \*pvfile, void \*parm) *************************************************************************************************** 此函数实现获取文件读写指针,仅FAT可使用该功能。其中参数: :: 1、pvfile:已打开的文件句柄; 2、param:用于保存文件系统读写指针; 3、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_get_fsize(void \*pvfile, void \*parm) *************************************************************************************************** 此函数实现获取文件大小,仅FAT可使用该功能。其中参数: :: 1、pvfile:已打开的文件句柄; 2、param:用于保存文件大小的指针; 3、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数struct vfscan \*vfs_fscan_new(void \*pvfs, const char \*path, const char \*arg, u8 max_deepth, int (\*callback)(void), strcut vfscan \*fsn, struct vfscan_reset_info \*info) ****************************************************************************************************************************************************************************************************** 此函数实现FAT文件系统的文件扫描配置,会返回文件扫描句柄供其他扫描接口使用,与vfs_fscan_release()搭配调用,可在ac104n sdk中的play_file.c中查看该函数具体使用示例。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、path:文件扫描的起始路径; 3、arg:文件扫描配置参数; 例:static const char scan_parm_test[] = “-t” “MP1MP2MP3WAVTXT” “ -sn -r” ; ① 首行”-t”表示需要扫描的文件类型,后面”MP1MP2MP3WAVTXT”即为扫描的后缀名,三个字符为一种类型,最多不可超过20种文件类型; ② 第三行” -sn”表示扫描文件的顺序是按照文件号排序,另一种组合” -st”表示按照时间排序; ③ 第三行” -r”表示搜索会包含文件夹子目录; ④ 各种扫描参数配置间,需要以空格隔开,其他配置有: a)扫描是否将文件夹算入总数,可配置” -d”; b)扫描只读文件配置” -ar”,扫描非读文件配置” -a/r”,不配置默认扫描所有文件; 4、max_deep:扫描深度,最大为8; 5、callback:扫描回调; 6、fsn:文件扫描句柄; 7、info:扫描结果信息,包含文件总数和文件夹总数等信息; 8、返回值: 成功 返回文件扫描句柄; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数void fs_fscan_release(void \*pvfs, struct vfscan \*fs) *************************************************************************************************** 此函数实现释放文件扫描句柄,仅FAT可使用该功能,与vfs_fscan()搭配调用。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、fs:文件扫描句柄; 3、返回值:无。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int fs_get_folderinfo(void \**pvfile, struct vfscan \*fs, int \*start_num, int \*end_num) *************************************************************************************************** 此函数实现文件夹扫描,需使用vfs_fscan()返回的文件扫描句柄,仅FAT可使用该功能。其中参数: :: 1、pvfile:需要扫描的设备里的文件; 2、fs:文件扫描句柄; 3、Start_num:用于保存第一个文件夹的第一个文件号; 4、End_num:用于保存最后一个文件夹的最后一个文件号; 5、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int fs_get_encfolder_info(void \*pvfs, char \*folder, char \*ext, u32 \*last_num, u32 \*total_num) ************************************************************************************************************************************ 此函数实现获取录音文件夹信息,包括录音文件总数,仅FAT可使用该功能。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、folder:文件夹路径,如”/JL_REC”; 3、ext:录音文件的后缀名,如”MP3”; 4、last_num:第一个可以使用的录音文件的文件序号; 5、total_num:总录音文件数; 6、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_file_name(void \*pvfile, void \*name, u32 len) ************************************************************************************************************************************ | 此函数实现获取文件的名字。 | 该函数在获取文件名小于16byte(带后缀名)时,返回的为u8字符; | 在获取大于16byte(带后缀名)时,返回的是unicode码,且不会返回完整的文件名。 | 具体需要获取文件长名并最终转化为u8字符进行打印出来,可参考该issue步骤: | `FAQ:FAT文件系统下如何获取函数文件名(短文件名 / 长文件名)? `_ :: 1、pvfile:已打开的文件句柄; 2、name:获取文件名指针。 3、len:获取文件名长度。 4、返回值:文件名长度; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int fs_select(void \*pvfs, void \**ppvfile, struct vfscan \*fs, int sel_mode, int arg) ************************************************************************************************************************************ 此函数实现FAT文件系统的文件查找,支持多种查找方式,具体示例可查看fat_demo(void)接口。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3、fs:文件扫描句柄; 4、sel_mode:文件查找方式: ① FSEL_BY_NUMBER:按文件号查找; ② FSEL_BY_SCLUST:按簇号查找; ③ FSEL_BY_PATH:按路径查找; 5、arg:文件查找参数; ① 按文件号查找时传入文件号; ② 按簇号查找时传入簇号; ③ 按路径查找时传入相应路径,支持通配符查找; 6、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_mk_dir(void \*pvfs, char \*folder, u8 mode) *************************************************************************************************** 此函数实现获取创建文件夹,仅FAT可使用该功能。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、folder:文件夹路径,如”/JL_REC”; 3、mode:目录属性; 1:设置为隐藏属性; 0:不设置; 4、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_delete_dir(void \*pvfs, char \*path) *************************************************************************************************** 此函数实现获取删除文件夹,仅FAT可使用该功能。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、path:文件夹路径,如”/JL_REC”; 3、返回值: 成功 0; 失败 错误请查看errno-base.h。 使用demo: :: log_info("vfs_delete_dir\n"); err = vfs_delete_dir(pvfs, "/test_dir/adir"); if (err != 0) { log_error("vfs_delet_dir 0x%x\n", err); goto __vfs_delete_fs_close; } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_get_encfolder_info(void \*pvfs, char \*folder, char \*ext, u32 \*last_num, u32 \*total_num) ************************************************************************************************************************* 此函数实现获取录音文件夹信息,包括录音文件总数,仅FAT可使用该功能。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、folder:文件夹路径,如”/JL_REC”; 3、ext:录音文件的后缀名,如”MP3”; 4、last_num:第一个可以使用的录音文件的文件序号; 5、total_num:总录音文件数; 6、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_file_delete(void \*pvfile) ************************************************************************************************************************* 此函数实现文件的删除,仅FAT可使用该功能。其中参数: :: 1、pvfile:已打开的文件句柄; 2、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_select(void \*pvfs, void \**ppvfile, struct vfscan \*fs, int sel_mode, int arg) ************************************************************************************************************************* 此函数实现FAT文件系统的文件查找,支持多种查找方式,具体示例可查看fat_demo(void)接口。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3、fs:文件扫描句柄; 4、sel_mode:文件查找方式: ① FSEL_BY_NUMBER:按文件号查找; ② FSEL_BY_SCLUST:按簇号查找; ③ FSEL_BY_PATH:按路径查找; 5、arg:文件查找参数; ① 按文件号查找时传入文件号; ② 按簇号查找时传入簇号; ③ 按路径查找时传入相应路径,支持通配符查找; 6、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_ioctl(void \*pfile, int cmd, int arg) ************************************************************************************************************************* fat文件系统支持多种命令操作,CMD命令如下: :: 1. 创建文件夹 FS_IOCTL_MK_DIR 2. 获取文件夹序号和文件夹内文件数目 FS_IOCTL_GET_FOLDER_INFO_3 3. 获取录音文件信息 FS_IOCTL_GET_ENCFOLDER_INFO 4. 重置扫描句柄 FS_IOCTL_RESET_VFSCAN 5. 设置卷标 FS_IOCTL_SET_VOL 6. 获取分区信息,簇大小,容量 FS_IOCTL_GET_PARTITION_INFO 7. 获取剩余空间 FS_IOCTL_GET_FREE_SPACE 8. 获取当前文件的相对路径和绝对路径 FS_IOCTL_GET_PATH 9.获取文件系统总容量 FS_IOCTL_GET_PARTITION_INFO 10.获取文件系统剩余容量 FS_IOCTL_GET_FREE_SPACE 获取获取当前文件的相对路径和绝对路径demo: :: len = vfs_fget_path(pfile, fsn, (u8 *)name, sizeof(name), 0); //获取绝对路径 len = vfs_fget_path(pfile, fsn, (u8 *)name, sizeof(name), 1); //获取相对路径 /*如果路径里的文件夹大于16byte,获取出来的是Unicode码,小于16byte的则为utf8*/ /*返回值为路径长度,name即为获取的路径*/ 获取剩余空间demo: :: u32 cap = 0; res = vfs_ioctl(pvfs, (int)FS_IOCTL_GET_FREE_SPACE, (int)&cap); log_info("cap 0x%x\n",res,cap); //cap为获取到fat文件系统的剩余容量,单位为k 获取分区信息,簇大小,容量demo: :: u32 res = 0; FS_PARTITION_INFO part_info = {0}; res = vfs_ioctl(pvfs, (int)FS_IOCTL_GET_PARTITION_INFO, (int)&part_info); log_info("0x%x 0x%x 0x%x \n",part_info.clust_size,part_info.total_size, part_info.fs_type); /*分别对应簇大小,文件系统总容量大小,文件系统类型*/ 函数vfs_ioctl获取总容量命令 FS_IOCTL_GET_PARTITION_INFO ------------------------------------------------------------------------ 获取文件系统总容量,仅fat有效,参考代码: .. code-block:: C :linenos: :emphasize-lines: 2 FS_PARTITION_INFO f_info; u32 err = vfs_ioctl(pvfile,FS_IOCTL_GET_PARTITION_INFO,(u32)&(f_info)) if(0 != err) { // succeed } 函数vfs_ioctl获取剩余容量命令 FS_IOCTL_GET_FREE_SPACE ------------------------------------------------------------------------ 获取文件系统剩余容量,仅fat有效,参考代码: .. code-block:: C :linenos: :emphasize-lines: 2 u32 free_apacity_Kbyte;// u32 err = vfs_ioctl(pvfile,FS_IOCTL_GET_PARTITION_INFO,(u32)&free_apacity_Kbyte); if(0 != err) { // succeed } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _fat文件系统文件夹删除函数: 文件夹删除函数int vfs_delete_dir(void \*pvfs, char \*path) ************************************************************************************************************************* 此函数实现FAT文件系统的文件夹删除处理。其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、path:需要删除的文件夹的路径; 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _fat文件格式化接口函数: 格式化接口 int vfs_format(void \*\*ppvfs, const char \*dev_name, const char \*type, u32 clust_size, u8 create_new) ************************************************************************************************************************************* .. code-block:: c int vfs_format(void **ppvfs, const char *dev_name, const char *type, u32 clust_size, u8 create_new); 此函数用于格式化存储设备并创建文件系统。 .. important:: 重要警告 格式化操作会**永久删除**设备上的所有数据! 请确保已备份重要数据后再调用此函数。 参数说明 -------- ppvfs .. note:: 特殊行为 **类型**: ``void **`` **描述**: 指向VFS指针的指针 格式化操作会释放当前的VFS指针: 1. 格式化后,``*ppvfs`` 会被设置为 ``NULL`` 2. 需要重新调用 ``vfs_mount()`` 获取新的VFS指针 3. 如果传入 ``ppvfs == NULL``,必须指定有效的 ``clust_size`` **示例**: .. code-block:: c void *pvfs = NULL; // 格式化前获取VFS指针 vfs_mount(&pvfs, "sd0", "fat"); // 格式化操作 vfs_format(&pvfs, "sd0", "fat", 4*1024, 0); // 此时 pvfs == NULL,需要重新挂载 dev_name **类型**: ``const char *`` **描述**: 设备名称 **取值示例**: - ``"sd0"`` - SD卡设备 - ``"udisk0"`` - USB存储设备 - ``"ext_flsh"`` - 外部数据Flash设备 .. note:: 设备可用性 调用前需确保设备已正确连接并识别。 type **类型**: ``const char *`` **描述**: 文件系统类型 **取值范围**: - ``"fat"`` - FAT文件系统(自动识别为FAT12、FAT16、FAT32) .. caution:: 兼容性 不支持exfat。 clust_size **类型**: ``u32`` **描述**: 簇大小(字节) **取值范围**: +----------------+-------------------+--------------------------+ | 值 | 含义 | 备注 | +================+===================+==========================+ | 0 | 使用原簇大小 | ``create_new = 0`` 时使用| +----------------+-------------------+--------------------------+ | 1 * 512 | 512B簇 | 适合小文件(flash设备优选)| +----------------+-------------------+--------------------------+ | 2 * 512 | 1KB簇 | 适合小文件(flash设备优选)| +----------------+-------------------+--------------------------+ | 4 * 1024 | 4KB簇 | 适合小文件(flash设备优选)| +----------------+-------------------+--------------------------+ | 8 * 1024 | 8KB簇 | 通用选择 | +----------------+-------------------+--------------------------+ | 16 * 1024 | 16KB簇 | 适合大文件 | +----------------+-------------------+--------------------------+ | 32 * 1024 | 32KB簇 | 适合大容量存储 | +----------------+-------------------+--------------------------+ | 64 * 1024 | 64KB簇 | 适合超大容量存储 | +----------------+-------------------+--------------------------+ .. important:: 约束条件 - 当 ``create_new = 1`` 时, **不能** 填0 - 一般设备建议值:4KB、8KB、16KB、32KB、64KB - flash建议值:512B、1KB、4KB - 簇大小影响存储效率和性能 create_new **类型**: ``u8`` **描述**: 创建模式 **取值**: ===== ===================== ==================================== 值 含义 使用场景 ===== ===================== ==================================== 0 维持原文件系统类型 设备已有文件系统,仅重新格式化 1 新建文件系统类型 *设备无文件系统* 或需要更换类型 ===== ===================== ==================================== .. note:: 使用场景判断 **何时使用 create_new = 1**: 1. 新设备首次使用 2. 完全重新组织设备内文件系统的数据结构 3. 设备文件系统损坏无法识别 **何时使用 create_new = 0**: 1. 设备已有文件系统,仅需要清空数据 2. 定期维护性格式化 3. 修复文件系统错误 返回值 ------ ===================== ============ 返回值 含义 ===================== ============ 0 成功 非0(FRESULT or -1) 失败 ===================== ============ 注意事项 -------- .. warning:: 数据安全 **格式化会永久删除所有数据!** 建议的操作流程: 1. 📋 备份重要数据 2. 🔍 确认设备名称正确 3. ⚙️ 选择合适的簇大小 4. ⚡ 执行格式化 5. 🔄 重新挂载设备 .. note:: VFS指针管理 1. **输入时**: ``*ppvfs`` 指向当前的VFS结构 2. **过程中**: 函数会释放该VFS结构 3. **输出时**: ``*ppvfs`` 被设置为 ``NULL`` 4. **后续**: 必须调用 ``vfs_mount()`` 重新获取 .. caution:: 参数约束 **create_new 和 clust_size 的组合规则**: ============= ============= =========================== create_new clust_size 是否有效 ============= ============= =========================== 0 0 ✅ 有效(使用原簇大小) 0 >0 ⚠️ 可能无效(忽略新大小?) 1 0 ❌ 无效(必须指定大小) 1 >0 ✅ 有效 ============= ============= =========================== 常见问题 -------- Q: 格式化后为什么需要重新挂载? A: 格式化会创建新的文件系统结构,原有的VFS上下文已失效。 必须重新挂载以建立新的文件系统连接。 Q: 可以边使用设备边格式化吗? A: **绝对不行!** 格式化前必须确保: 1. 所有文件已关闭 2. 设备未在被其他进程使用 3. 已卸载设备(如果之前已挂载) Q: 如何确定合适的簇大小? A: 考虑以下因素: 1. **存储设备容量**:大容量设备可用较大簇 2. **文件平均大小**:小文件多用小簇 3. **性能需求**:大簇读写性能更好 4. **空间效率**:小簇空间浪费少 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _FAT文件系统简易驱动 & FAT文件系统完整驱动: FAT文件系统简易驱动 & FAT文件系统完整驱动区别 ################################################################ +--------------+-----------------------+-----------------------+ | | 简易FAT文件系统驱动 | 完整FAT文件系统驱动 | +==============+=======================+=======================+ | FAT12 读 | × | √ | +--------------+-----------------------+-----------------------+ | FAT16 读 | × | √ | +--------------+-----------------------+-----------------------+ | FAT32 读 | √ | √ | +--------------+-----------------------+-----------------------+ | EXFAT 读 | × | √ | +--------------+-----------------------+-----------------------+ | FAT12 写 | × | √ | +--------------+-----------------------+-----------------------+ | FAT16 写 | × | √ | +--------------+-----------------------+-----------------------+ | FAT32 写 | × | √ | +--------------+-----------------------+-----------------------+ | EXFAT 写 | × | √ | +--------------+-----------------------+-----------------------+ | 盘扫描 | × | √ | +--------------+-----------------------+-----------------------+ | 长文件名 | × | √ | +--------------+-----------------------+-----------------------+ | 短文件名 | √ | √ | +--------------+-----------------------+-----------------------+