文件系统管理 ========================================= AD16N FLASH方案支持只读sydfs、录音读写norfs以及fatfs文件系统;OTP方案只支持只读fatfs文件系统,且不使用vfs文件系统管理,直接调用fat文件系统接口,可节约代码空间;文件系统涉及的文件包括apps\app\bsp\common\fs目录下的所有c文件、include_lib\fs目录下的所有头文件以及errno-base.h文件。 支持的文件系统列表: ========== ========= =============== =============================================================== 文件系统 OTP方案 flash方案 详情 ========== ========= =============== =============================================================== sydfs 不支持 支持 只读文件系统,用于存放资源文件到norflash; norfs 不支持 支持 循环覆盖文件系统,可读写;针对norflash设计; simple_fat 无 无 简单fat文件系统驱动,占用资源少,不支持搜索;支持FAT12/16/32, EXFAT; fatfs 支持 支持 完整的fat文件系统驱动,占用资源多,支持搜索;支持FAT12/16/32, EXFAT; ========== ========= =============== =============================================================== fs有以下主要函数: :: void fs_init(void); u32 fs_mount(void **ppvfs, void *device, void *type); u32 fs_openbypath(void *pvfs, void **ppvfile, const char *path); int fs_select(void *pvfs, void **ppvfile, struct vfscan *fs, int sel_mode, int arg); u32 fs_read(void *pvfile, void *buf, u32 len); u32 fs_seek(void *pvfile, u32 offset, u32 mode); u32 fs_file_close(void **ppvfile); u32 fs_fs_close(void **ppvfs); u32 fs_file_name(void *pvfile, void *name, u32 len); int fs_get_attrs(void *pvfile, void *pvfs_attr); int fs_ioctl(void *pvfile, int cmd, int arg); int fs_ftell(void *pvfile, void *parm); int fs_get_fsize(void *pvfile, void *parm); struct vfscan *fs_fscan_new(void *pvfs, const char *path, const char *arg, u8 max_deepth, int (*callback)(void), struct vfscan *fsn, struct vfscan_reset_info *info); int fs_fscan_release(void *pvfs, struct vfscan *fs); int vs_get_folderinfo(void **pvfile, struct vfscan *fs, int *start_num, int *end_num); int fs_get_encfolder_info(void *pvfs, char *folder, char *ext, u32 *last_num, u32 *total_num); ^^^^^^^^^^^^^^^^^^^^ 文件系统介绍 ################################ SDK中支持的文件系统有:只读sydfs、录音读写norfs以及fatfs;可以在app\bsp\fs目录下查看各文件系统的文件以及支持的接口;本小节将介绍各个文件系统以及支持的ioctl对应的cmd命令,ioctl具体接口请查看《3.13函数说明》; sydfs文件系统 ********************************* Sydfs是系统数据运行的 **只读文件系统** ,可以通过sdk的download工具来下载存放资源文件,并于系统运行时读取;该文件系统能使用的接口图1.1所示: .. image:: syd_func_ops.png :alt: "syd 文件系统接口" :align: center .. centered:: 图1.1 syd 文件系统接口 其中ioctl支持的cmd命令有: ①FS_IOCTL_FILE_TOTAL:: 示例: int file_total; vfs_ioctl(pfile, FS_IOCTL_FILE_TOTAL, (int)&file_total); file_total即为pfile文件所在文件系统的总文件数; ②FS_IOCTL_FS_TOTAL:: 示例: int file_total; vfs_ioctl(pfs, FS_IOCTL_FILE_TOTAL, (int)&file_total); file_total即为pfs文件系统的总文件数; ③FS_IOCTL_FILE_ATTR:: 示例: struct vfs_attr attr; vfs_ioctl(pfile, FS_IOCTL_FILE_ATTR, (int)&attr); attr即可获取pfile文件的位置和大小; * **注意:通过ioctl获取的文件位置仅为该pfile文件在其上层目录下的相对偏移;若要获取该文件相对于flash的偏移地址,需要调用vfs_get_fsize();** norfs文件系统 ********************************* Norfs是一个循环管理的可读写文件系统,内部空间环形管理,空间不足时新写入的文件会覆盖之前的文件;norfs文件系统只通过文件号进行管理,创建新文件后文件号会累加;一般在录音时使用;该文件系统能使用的接口如图所示: .. image:: norfs_func_ops.png :alt: "norfs文件系统支持的接口" :align: center .. centered:: 图1.2 norfs文件系统支持的接口 其中ioctl支持的cmd命令有: ①FS_IOCTL_FILE_TOTAL,同上 ②FS_IOCTL_FS_TOTAL,同上 ③FS_IOCTL_FILE_ATTR,同上 ④FS_IOCTL_FILE_SYNC:: 示例: u32 flen = 0; vfs_ioctl(pfile, FS_IOCTL_FILE_SYNC, (int)&flen); 该命令一般在录音结束时调用,用于更新norfs录音文件头,flen传入时为需要舍弃的录音末尾字节数,调用结束后会flen会被赋值为录音文件的字节数; ④FS_IOCTL_FILE_INDEX:: 示例: int file_index; vfs_ioctl(pfile, FS_IOCTL_FILE_INDEX, (int)&file_index); file_index即为pfile文件所在norfs文件系统的最新文件序号; ⑤FS_IOCTL_FS_INDEX:: 示例: int file_index; vfs_ioctl(pfs, FS_IOCTL_FS_INDEX, (int)&file_index); file_index即为pfs所指的norfs文件系统的最新文件序号; fat文件系统 ********************************* FatFs是一个通用的文件系统,在本机中,支持对FAT12/16/32、exFAT文件系统进行读写操作,FAT文件系统能使用的接口如图1.3所示: .. image:: fat_func_ops.png :alt: "fat文件系统支持的接口" :align: center .. centered:: 图1.3 fat文件系统支持的接口 ^^^^^^^^^^^^^^^^^^^^ 文件系统使用一般流程 ################################ 如图,fs运行大致流程如下; .. image:: fs_process.png :alt: "fs 运行大致流程" :align: center .. centered:: 图2.1 fs 运行大致流程 文件系统的流程 :: 调用函数void fs_init(void),完成对所有文件系统驱动的初始化; 调用u32 fs_mount(void **ppvfs, void *device, void *type),传递指定设备句柄,并完成对具体文件系统的挂载,并获取文件系统的句柄; 调用u32 fs_openbypath(void *pvfs, void **ppvfile, const char *path)或u32 fs_select(void *fsn, void *pfs, int sel_mode, void **ppfile, int arg)打开文件,并获取文件句柄; 调用u32 fs_read(void *pvfile, void *buf, u32 len)对文件进行读操作; 调用int fs_ioctl(void *pvfile, int cmd, int arg)使用不同的命令进行不同的操作,如获取文件号、获取文件总数、获取文件地址、获取文件名字等; 调用u32 fs_file_close(void **ppvfile)关闭文件,并释放文件句柄。 调用u32 fs_fs_close(void **ppvfs)关闭文件系统,并释放文件系统句柄。 可以通过调用接口得到的返回值查看是否调用成功,以及失败的原因;失败原因可在include_lib/common/errno-base.h中查看。 可以通过调用接口得到的返回值查看是否调用成功,以及失败的原因;失败原因可在include_lib/common/errno-base.h中查看。 ^^^^^^^^^^^^^^^^^^^^ 通用文件系统管理函数 ################################ 通用文件系统管理函数将介绍sydfs、norfs、fatfs通用的接口,各文件系统具体能使用哪些接口请查看是上面几张图片,下一小节将介绍fatfs独有的相关文件系统接口; 函数void fs_init(void) ************************************************************************************************* 此函数实现对所有文件系统驱动的初始化;在开机第一次调用即可。 函数u32 fs_mount(void \**ppvfs, void \*device, void \*type) ************************************************************************************************* 此函数实现对指定设备挂在指定类型的文件系统,所挂载的系统必须设备自身支持;其中参数: :: 1、ppvfs:文件系统句柄指针,若句柄指向为NULL,函数会自行申请空间; 2、device:设备句柄; 3、type:文件系统类型的字符串; ① “fat”:挂载fat文件系统; 4、返回值: 成功 0; 失败 错误请查看errno-base.h。 示例1: void *device = device_open(SD0_INDEX);//获取SD卡设备句柄 void *pfs = NULL; u32 err = fs_mount(&pfs, device, “fat”); //SD卡挂载fatfs系统 if (pfs != NULL && err == 0) { //SD卡挂载fatfs成功 } 示例2: void *device = device_open(UDISK_INDEX);//获取U盘卡设备句柄 void *pfs = NULL; u32 err = vfs_mount(&pfs, device, “fat”); //U盘挂载fatfs系统 if (pfs != NULL && err == 0) { //U盘挂载fatfs成功 } 函数u32 fs_openbypath(void \*pvfs, void \**ppvfile, const char \*path) ************************************************************************************************* 此函数实现打开指定路径的文件,其中参数: :: 1、pvfs:已挂载的文件系统句柄; 2、ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3、path:路径字符串; ① 如果字符串只是包含文件夹名,那么会打开文件夹; ② 如果字符串里面包含了完成的文件名,那么会同时包含文件名! ③ 如果字符串为空,则返回错误; 4、返回值:成功 0; 失败 错误请查看errno-base.h。 示例: void *pfile = NULL; u32 err = vfs_openbypath(pfs, &pfile, “dir_song/so001.f1a”); if (pfile != NULL && err == 0) { //成功打开dir_song文件夹里的so001.f1a文件 } 函数u32 fs_read(void \*pvfile, void \*buf, u32 len) ************************************************************************************************* 此函数实现对指定文件的读操作。其中参数: :: 1、pvfile:已打开的文件句柄; 2、buf:数据buff; 3、len:需要读取的字节长度; 4、返回值: 成功 读取的字节数; 失败 0。 示例: u8 read_buf[32]; u32 read_len = fs_read(pfile, (void *)read_buf, 32); if (read_len != 0) { //成功读取pfile中read_len长度的数据到read_buf里 } 函数u32 fs_seek(void \*pvfile, u32 offset, u32 mode) ************************************************************************************************* 此函数实现改变指定文件中读写指针的偏移。其中参数: :: 1、pvfile:已打开的文件句柄; 2、offset:偏移量; 3、mode:seek模式选择。如图3.1,seek模式有3种,分别为: ① SEEK_SET:从文件起始位置开始向后偏移,首先会判断偏移量是否大于文件长度,若小于则使文件读写指针rw_p = offset; ② SEEK_CIR:从文件读写指针位置开始向后偏移,使rw_p = rw_p + offset; ③ SEEK_END:从文件末尾位置向前偏移,首先会判断偏移量是否大于文件长度,若小于则使rw_p = 文件长度 - offset; 4、返回值:0。 .. image:: vfs_seek.png :alt: "fs seek" :align: center .. centered:: 图3.1 seek模式选择 函数u32 fs_file_close(void \**ppvfile) ************************************************************************************************* 此函数实现关闭文件并释放句柄。其中参数: :: 1、ppvfile:已打开的文件句柄指针; 2、返回值:0。 示例: vfs_file_close(&pfile); if (pfile == NULL) { //成功关闭pfile文件 } 函数u32 fs_fs_close(void \**ppvfs) ************************************************************************************************* 此函数实现关闭文件系统并释放相关句柄。其中参数: :: 1、ppvfs:已挂载的文件系统句柄指针; 2、返回值:NULL。 示例: fs_fs_close(&pfs); if (pfs == NULL) { //成功关闭pfs文件系统 } 函数u32 fs_file_name(void \*pvfile, void \*name, u32 len) ************************************************************************************************* 此函数实现获取指定文件句柄的文件名。其中参数: :: 1、pvfile:已打开的文件句柄; 2、name:存放文件名的buf; 3、len:获取文件名的长度; 4、返回值:成功 返回获取文件名的长度; 函数int fs_get_attrs(void \*pvfile, void \*pvfs_attr) ************************************************************************************************* 此函数实现记录文件的属性,包括文件大小和地址,nor_fs无法使用此功能。其中参数: :: 1、pvfile:已打开的文件句柄; 2、pvfs_attr:文件系统属性,需要传入vfs_attr结构体类型的指针; 3、返回值:0。 示例: struct vfs_attr file_attr; fs_get_attrs(pfile, &file_attr); //文件地址和大小分别保存在file_attr.sclust和file_attr.fsize中 函数int fs_ioctl(void \*pvfile, int cmd, int arg) ************************************************************************************************* 此函数实现对指定文件的相关操作,各文件系统具体的cmd命令请查看《1文件系统介绍》小节。其中参数: :: 1、pvfile:已打开的文件句柄; 2、cmd:命令; 3、arg:参数; 4、返回值: 成功 0; 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^ 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 fs_file_delete(void \*pvfile) ************************************************************************************************************************************ 此函数实现文件的删除,仅FAT可使用该功能。其中参数: :: 1、 pvfile:已打开的文件句柄; 2、返回值:成功 0; 失败 错误请查看errno-base.h。 函数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_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。