文件系统管理 ========================================= 支持的文件系统列表: ========== =============================================================== 文件系统 详情 ========== =============================================================== sydfs 只读文件系统,用于存放资源文件到norflash; norfs 循环覆盖文件系统,可读写;针对norflash设计; simple_fat 简单fat文件系统驱动,占用资源少,不支持搜索和多文件同时打开;支持FAT12/16/32, EXFAT; fatfs 完整的fat文件系统驱动,占用资源多,支持搜索;支持FAT12/16/32, EXFAT; ========== =============================================================== 各芯片SDK支持的文件系统类型如下: ============== ========== ======= ============ ===== 芯片支持的设备 sydfs norfs simple_fat fatfs ============== ========== ======= ============ ===== AD14N √ √ √ AC104N √ √ √ AD15N √ AD17N √ AD18N √ √ √ ============== ========== ======= ============ ===== SDK中通过vfs来集中管理各类文件系统,涉及的文件目录包括: - app\\bsp\\common\\fs目录下的所有c文件; - include_lib\\fs目录下的所有h文件; - errno-base.h文件; .. note:: vfs有以下主要函数: 1. void vfs_init(void); 2. u32 vfs_mount(void \**ppvfs, void \*device, void \*type); 3. u32 vfs_openbypath(void \*pvfs, void \**ppvfile, const char \*path); 4. u32 vfs_openbyindex(void \*pvfs, void \**ppvfile, u32 index); 5. u32 vfs_createfile(void \*pvfs, void \**ppvfile, u32 \*pindex); 6. u32 vfs_read(void \*pvfile, void \*buf, u32 len); 7. u32 vfs_write(void \*pvfile, void \*buf, u32 len); 8. u32 vfs_seek(void \*pvfile, u32 offset, u32 mode); 9. u32 vfs_file_close(void \**ppvfile); 10. u32 vfs_fs_close(void \**ppvfs); 11. u32 vfs_file_name(void \*pvfile, void \*name, u32 len); 12. int vfs_get_attrs(void \*pvfile, void \*pvfs_attr); 13. int vfs_ioctl(void \*pvfile, int cmd, int arg); .. note:: **其中,fatfs中独有的函数:** 1、获取文件读写指针 int vfs_ftell(void \*pvfile, void \*parm); 2、获取文件大小 int vfs_get_fsize(void \*pvfile, void \*parm); 3、fat文件系统文件扫描 struct vfscan \*vfs_fscan_new(void \*pvfs, const char \*path, const char \*arg, u8 max_deepth, int (\*callback)(void), struct vfscan \*fsn, struct vfscan_reset_info \*info); 4、释放fat文件系统扫描句柄 int vfs_fscan_release(void \*pvfs, struct vfscan \*fs); 5、实现fat文件系统的文件选取 int vfs_select(void \*pvfs, void \**ppvfile, struct vfscan \*fs, int sel_mode, int arg); 6、实获取at文件系统扫描后的相关文件号 int vfs_get_folderinfo(void \**pvfile, struct vfscan \*fs, int \*start_num, int \*end_num); 7、实现fat文件系统创建文件夹 int vfs_mk_dir(void \*pvfs, char \*folder, u8 mode); 8、获取录音文件的相关信息 int vfs_get_encfolder_info(void \*pvfs, char \*folder, char \*ext, u32 \*last_num, u32 \*total_num); 9、删除文件 int vfs_file_delete(void \*pvfile); ^^^^^^^^^^^^^^^^^^^^ .. _文件系统介绍: 文件系统介绍 ################################ Sdk中默认支持的文件系统有:sydfs、norfs、fatfs(AC104,AD17,AD18)、simple_fatfs(AD14N); 可以在app\\bsp\\common\\fs目录下查看各文件系统的文件以及支持的接口; 本小节将介绍各个文件系统以及支持的ioctl对应的cmd命令: 文件系统使用一般流程 ################################ 如图,fs运行大致流程如下; .. image:: fs_process.png :alt: "fs 运行大致流程" :align: center .. centered:: 图2.1 fs 运行大致流程 通用的文件系统使用流程 :: 1、文件系统初始化: 调用函数void fs_init(void),完成对所有文件系统驱动的初始化; 2、mount挂载: 调用u32 fs_mount(void **ppvfs, void *device, void *type),传递指定设备句柄,并完成对具体文件系统的挂载,并获取文件系统的句柄; 3、打开文件: 调用u32 fs_openbypath(void *pvfs, void **ppvfile, const char *path)或u32 fs_select(void *fsn, void *pfs, int sel_mode, void **ppfile, int arg)打开文件,并获取文件句柄; 4、读取文件数据: 调用u32 fs_read(void *pvfile, void *buf, u32 len)对文件进行读操作; 5、对文件进行不同的命令操作: 调用int fs_ioctl(void *pvfile, int cmd, int arg)使用不同的命令进行不同的操作,如获取文件号、获取文件总数、获取文件地址、获取文件名字等; 6、关闭文件: 调用u32 fs_file_close(void **ppvfile)关闭文件,并释放文件句柄。 7、关闭文件系统: 调用u32 fs_fs_close(void **ppvfs)关闭文件系统,并释放文件系统句柄。 可以通过调用接口得到的返回值查看是否调用成功,以及失败的原因;失败原因可在include_lib/common/errno-base.h中查看。 ^^^^^^^^^^^^^^^^^^^^ 通用文件系统管理函数 ################################ 通用文件系统管理函数将介绍sydfs、norfs、fatfs通用的接口,各文件系统具体能使用哪些接口请查看上面的几张图片,下一小节将介绍fatfs独有的相关文件系统接口; 函数void vfs_init(void) ********************************* 此函数实现对所有文件系统驱动的初始化;在开机第一次调用即可。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_mount(void \*\*ppvfs, void \*device, void \*type) ************************************************************************************************************************************************************************************************************************** 此函数实现对指定设备挂在指定类型的文件系统,所挂载的系统必须设备自身支持;其中参数: :: 1. ppvfs:文件系统句柄指针,若句柄指向为NULL,函数会自行申请空间; 2. device:设备句柄; ① 需要打开sydfs时,若句柄为空,则会使用内置flash; ② 需要打开norfs等其他文件系统时,句柄不能为空; 3. type:文件系统类型的字符串; ① 可选择”sydfile”、”norfs”、”fat”或0,若该值为0,则会剔除norfs文件系统,在剩余文件系统里轮询各个挂载,直至挂载成功退出; ② 注:norfs文件系统仅为录音到内置FLASH的应用使用!! 4. 返回值: ① 成功 0; ② 失败 错误请查看errno-base.h。 示例1 :: 在内置flash挂载syd文件系统 void *device = dev_open(__SFC_NANE, 0);//获取内置flash设备句柄 void *pfs = NULL; u32 err = vfs_mount(&pfs, device, “sydfile”); //内置flash挂载syd文件系统 if (pfs != NULL && err == 0) { //内置flash挂载sydfs成功 } 示例2 :: 在外挂flash上挂载norfs文件系统 void *device = dev_open(__EXT_FLASH_NANE, 0);//获取外挂flash设备句柄 void *pfs = NULL; u32 err = vfs_mount(&pfs, device, “norfs”); //外置flash挂载norfs文件系统 if (pfs != NULL && err == 0) { //外置flash挂载norfs成功 } 示例3 :: 在SD卡上挂载fat文件系统 void *device = dev_open(__SD0_NANE, 0);//获取sd卡设备句柄 void *pfs = NULL; u32 err = vfs_mount(&pfs, device, “fat”); //sd卡挂载fat文件系统 if (pfs != NULL && err == 0) { //sd卡挂载fat成功 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_openbypath(void \*pvfs, void \*\*ppvfile, const char \*path) ************************************************************************************************************************************* 此函数实现打开指定路径的文件,norfs文件系统无法使用此功能。其中参数: :: 1. pvfs:已挂载的文件系统句柄; 2. ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3. path:路径字符串; ① 如果字符串只是包含文件夹名,那么会打开文件夹,打开的文件夹仅可用于校验CRC16; ② 如果字符串里面包含了完成的文件名,那么会同时包含文件名! ③ 如果字符串为空,则返回错误; 4. 返回值: ① 成功 0; ② 失败 错误请查看errno-base.h。 示例: :: 在挂载(vfs_mount)成功的前提下,打开dir_song里的so001.f1a歌曲 void *pfile = NULL; u32 err = vfs_openbypath(pfs, &pfile, “dir_song/so001.f1a”); if (pfile != NULL && err == 0) { //成功打开dir_song文件夹里的so001.f1a文件 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_openbyindex(void \*pvfs, void \**ppvfile, u32 index) *************************************************************************************************** 此函数实现打开指定文件号的文件,其中参数: :: 1. pvfs:已挂载的文件系统句柄; 2. ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3. index:文件序号; 4. 返回值: ① 成功 0; ② 失败 错误请查看errno-base.h。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_createfile(void \*pvfs, void \**ppvfile, u32 \*pindex) ****************************************************************************************** 此函数实现norfs、fatfs创建一个新的文件,syd_fs无法使用此功能。文件创建和操作结束后,需要调用vfs_file_close()关闭文件,其中参数: :: 1. pvfs:已挂载的文件系统句柄; 2. ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间; 3. pindex:文件序号; ① norfs:传入的pindex会被赋值为最新的文件序号; 注意:norfs文件创建和操作结束后,需要先调用vfs_ioctl()接口传入FS_IOCTL_FILE_SYNC命令更新文件信息后再关闭文件; ② fatfs:传入文件存放位置,如”/test.txt”即在根目录创建test.txt文件;; 注意:路径有文件夹时文件夹必须存在,否则创建失败。可先调用vfs_mk_dir()创建文件夹;创建文件时支持长文件名,长文件名路径需传入Unicode码进去并开启FOPEN_LONG宏定义和相应的库(详情见demo代码); ③ sydfs:不支持此功能; 4. 返回值: ①  0; ② 失败 错误请查看errno-base.h。 示例1: :: 挂载norfs文件系统成功前提下,创建一个新的文件 void *pfile = NULL; int index; u32 err = vfs_createfile(pfs, &pfile, (u32)&index); if (pfile != NULL && err == 0) { //norfs文件系统下文件创建成功,index会被赋值为所创建文件的序号 } 示例2: :: 挂载fat文件系统成功前提下,创建一个新的文件 void *pfile = NULL; char *path = “/abcd.txt”; u32 err = vfs_createfile(pfs, &pfile, (u32)path); if (pfile != NULL && err == 0) { //fat文件系统下文件abcd.txt创建成功 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_read(void \*pvfile, void \*buf, u32 len) ********************************************************************** 此函数实现对指定文件的读操作。其中参数: :: 1. pvfile:已打开的文件句柄; 2. buf:数据buff; 3. len:需要读取的字节长度; 4. 返回值: ① 成功 读取的字节数; ② 失败 0。 示例: :: 打开文件成功前提下,读取文件数据 u8 read_buf[32]; u32 read_len = vfs_read(pfile, (void \*)read_buf, 32); if (read_len != 0) { //成功读取pfile中read_len长度的数据到read_buf里 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_write(void \*pvfile, void \*buf, u32 len) ********************************************************************** 此函数实现对指定文件的写操作,syd_fs无法使用此功能,其中参数: :: 1. pvfile:已打开的文件句柄; 2. buf:数据buf; 3. len:需要写入的字节长度; 4. 返回值: 成功 写入的字节数; 失败 错误请查看errno-base.h。 示例: :: 打开文件成功前提下,往文件写入数据 u8 write_buf[32] = {0, 1, 2, 3 ... 31}; u32 write_len = vfs_write(pfile, (void *)write_buf, 32); if (write_len != 0) { //成功将write_buf中write_len长度的数据写入到pfile } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_seek(void \*pvfile, u32 offset, u32 mode) ********************************************************************** 此函数实现改变指定文件中读写指针的偏移,其中参数: :: 1. pvfile:已打开的文件句柄; 2. offset:偏移量; 3. mode:seek模式选择。如图4.2,seek模式有3种,分别为: ① SEEK_SET:从文件起始位置开始向后偏移,首先会判断偏移量是否大于文件长度,若小于则使文件读写指针rw_p = offset; ② SEEK_CIR:从文件读写指针位置开始向后偏移,使rw_p = rw_p + offset; ③ SEEK_END:从文件末尾位置向前偏移,首先会判断偏移量是否大于文件长度,若小于则使rw_p = 文件长度 - offset; 4. 返回值:0。 下图为seek模式的选择: .. image:: vfs_seek.png :alt: "fs seek" :align: center ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_file_close(void \**ppvfile) ********************************************************************** 此函数实现关闭文件并释放句柄,其中参数: :: 1. ppvfile:已打开的文件句柄指针; 2. 返回值:0。 示例: :: vfs_file_close(&pfile); if (pfile == NULL) { //成功关闭pfile文件 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_fs_close(void \**ppvfs) ********************************************************************** 此函数实现关闭文件系统并释放相关句柄,nor_fs无法使用此功能,其中参数: :: 1. ppvfs:已挂载的文件系统句柄指针; 2. 返回值:NULL。 示例: :: vfs_fs_close(&pfs); if (pfs == NULL) { //成功关闭pfs文件系统 } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数u32 vfs_file_name(void \*pvfile, void \*name, u32 len) ********************************************************************** 此函数实现获取指定文件句柄的文件名,其中参数: :: 1. pvfile:已打开的文件句柄; 2. name:存放文件名的buf; 3. len:获取文件名的长度; 4. 返回值:成功 返回获取文件名的长度; .. note:: | syd文件系统 和 norfs文件系统 都只支持小于等于16字符的文件名。 | fat文件系统默认支持的也是小于等于16字符的文件名,v1.9.0版本过后fat文件系统才支持超过16字符的长名功能。 | 若需要在v.1.9.0版本前fat文件系统使用长名功能,可查看下方链接: | `FAQ:FAT文件系统下如何获取函数文件名(短文件名 / 长文件名) `_ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_get_attrs(void \*pvfile, void \*pvfs_attr) ********************************************************************** 此函数实现记录文件的属性,包括文件大小和地址,nor_fs无法使用此功能,其中参数: :: 1. pvfile:已打开的文件句柄; 2. pvfs_attr:文件系统属性,需要传入vfs_attr结构体类型的指针; 3. 返回值:0。 示例: :: struct vfs_attr file_attr; vfs_get_attrs(pfile, &file_attr); //文件地址和大小分别保存在file_attr.sclust和file_attr.fsize中 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数int vfs_ioctl(void \*pvfile, int cmd, int arg) ********************************************************************** 此函数实现对指定文件的相关操作,各文件系统具体的cmd命令请查看《:ref:`文件系统介绍`》小节,其中参数: :: 1. pvfile:已打开的文件句柄; 2. cmd:命令; 3. arg:参数; 4. 返回值: 成功 0; 失败 错误请查看errno-base.h。 cmd:命令主要有7种: ============================== ================================================================================================================================================================== vfs_ioctl cmd命令 命令含义 ============================== ================================================================================================================================================================== FS_IOCTL_DIR_FILE_TOTAL 获取文件所在文件系统下的文件数。该命令会将arg的值作为地址,并把文件句柄所在文件系统下的所有文件数赋给arg指向的值;若arg参数为0,返回错误E_PAGE_NULL; FS_IOCTL_FILE_TOTAL 同上; FS_IOCTL_FS_TOTAL 获取文件系统下的文件数。该命令会将arg的值作为地址,并将特定情况下传入的文件系统句柄下的所有文件数赋值给arg指向的值;若arg参数为0,返回错误E_PAGE_NULL; FS_IOCTL_FILE_ATTR 获取文件地址参数。该命令会将arg的值作为地址并指向vfs地址参数,并把文件长度以及地址赋值给vfs地址参数;若arg参数为0或文件句柄为NULL,返回错误E_PAGE_NULL或E_PFILE_NULL; FS_IOCTL_FILE_SYNC 同步文件。该命令会将录音文件同步并将arg的值作为末尾裁切的字节长度;若arg参数为0则不进行裁切; FS_IOCTL_FILE_INDEX 通过文件指针获取文件索引号。该命令会将arg的值作为地址,并把文件的索引号赋值给arg指向的值。 FS_IOCTL_FS_INDEX 通过文件系统指针获取文件索引号。该命令会将arg的值作为地址,并把文件的索引号赋值给arg指向的值。 ============================== ==================================================================================================================================================================