2. 文件系统管理

支持的文件系统列表:

文件系统

详情

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

AD24N(toy)

AD24N(enhanced)

AD23N

SDK中通过vfs来集中管理各类文件系统,涉及的文件目录包括:
  • app\bsp\common\fs目录下的所有c文件;

  • include_lib\fs目录下的所有h文件;

  • errno-base.h文件;

备注

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);

备注

其中,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);


2.1. 文件系统介绍

Sdk中默认支持的文件系统有:sydfs、norfs、fatfs、simple_fatfs、freefs;

可以在app\bsp\common\fs目录下查看各文件系统的文件以及支持的接口;

本小节将介绍各个文件系统以及支持的ioctl对应的cmd命令:

2.2. 文件系统使用一般流程

如图,fs运行大致流程如下;

"fs 运行大致流程"

图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中查看。

2.3. 通用文件系统管理函数

通用文件系统管理函数将介绍sydfs、norfs、fatfs通用的接口,各文件系统具体能使用哪些接口请查看上面的几张图片,下一小节将介绍fatfs独有的相关文件系统接口;

2.3.1. 函数void vfs_init(void)

此函数实现对所有文件系统驱动的初始化;在开机第一次调用即可。


2.3.2. 函数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文件系统:

1void *device = dev_open(__SFC_NANE, 0);//获取内置flash设备句柄
2void *pfs = NULL;
3u32 err = vfs_mount(&pfs, device, "sydfile"); //内置flash挂载syd文件系统
4if (pfs != NULL && err == 0) {
5    //内置flash挂载sydfs成功
6}

示例2,在外挂flash上挂载norfs文件系统:

1void *device = dev_open(__EXT_FLASH_NANE, 0);//获取外挂flash设备句柄
2void *pfs = NULL;
3u32 err = vfs_mount(&pfs, device, "norfs"); //外置flash挂载norfs文件系统
4if (pfs != NULL && err == 0) {
5    //外置flash挂载norfs成功
6}

示例3,在SD卡上挂载fat文件系统:

1void *device = dev_open(__SD0_NANE, 0);//获取sd卡设备句柄
2void *pfs = NULL;
3u32 err = vfs_mount(&pfs, device, "fat"); //sd卡挂载fat文件系统
4if (pfs != NULL && err == 0) {
5    //sd卡挂载fat成功
6}

2.3.3. 函数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歌曲:

1void *pfile = NULL;
2u32 err = vfs_openbypath(pfs, &pfile, "dir_song/so001.f1a");
3if (pfile != NULL && err == 0) {
4    //成功打开dir_song文件夹里的so001.f1a文件
5}

2.3.4. 函数u32 vfs_openbyindex(void *pvfs, void **ppvfile, u32 index)

此函数实现打开指定文件号的文件,其中参数:

1. pvfs:已挂载的文件系统句柄;
2. ppvfile:文件句柄指针,若句柄指向为NULL,函数会自行申请空间;
3. index:文件序号;
4. 返回值:
      ① 成功 0;
      ② 失败 错误请查看errno-base.h。

2.3.5. 函数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会被赋值为最新的文件序号;
    ② fatfs:传入文件存放位置,如”/test.txt”即在根目录创建test.txt文件;;
        注意:
    ③ sydfs:不支持此功能;
4. 返回值:
    ①  0;
    ② 失败 错误请查看errno-base.h。

备注

  1. norfs 文件系统:文件创建和操作结束后,需要先调用 vfs_ioctl() 接口传入 FS_IOCTL_FILE_SYNC 命令更新文件信息,然后再关闭文件

  2. fatfs 文件路径:文件创建时,其所在路径必须完整存在。若文件夹不存在,需预先调用 vfs_mk_dir() 创建,否则会失败。

  3. fatfs 长文件名配置

    • 需传入 Unicode 编码 的路径

    • 开启 FOPEN_LONG 宏定义

    • 链接相应的函数库

    • 具体实现请参考 Demo 代码。

示例1-挂载norfs文件系统成功前提下,创建一个新的文件:

1void *pfile = NULL;
2int index;
3u32 err = vfs_createfile(pfs, &pfile, (u32)&index);
4if (pfile != NULL && err == 0) {
5    //norfs文件系统下文件创建成功,index会被赋值为所创建文件的序号
6}

示例2-挂载fat文件系统成功前提下,创建一个新的文件:

1void *pfile = NULL;
2char *path = "/abcd.txt";
3u32 err = vfs_createfile(pfs, &pfile, (u32)path);
4if (pfile != NULL && err == 0) {
5    //fat文件系统下文件abcd.txt创建成功
6}

2.3.6. 函数u32 vfs_read(void *pvfile, void *buf, u32 len)

此函数实现对指定文件的读操作。其中参数:

1. pvfile:已打开的文件句柄;
2. buf:数据buff;
3. len:需要读取的字节长度;
4. 返回值:
    ① 成功 读取的字节数;
    ② 失败 0。

示例,打开文件成功前提下,读取文件数据:

1u8 read_buf[32];
2u32 read_len = vfs_read(pfile, (void *)read_buf, 32);
3if (read_len != 0) {
4    //成功读取pfile中read_len长度的数据到read_buf里
5}

2.3.7. 函数u32 vfs_write(void *pvfile, void *buf, u32 len)

此函数实现对指定文件的写操作,syd_fs无法使用此功能,其中参数:

1. pvfile:已打开的文件句柄;
2. buf:数据buf;
3. len:需要写入的字节长度;
4. 返回值:
    成功 写入的字节数;
    失败 错误请查看errno-base.h。

示例,打开文件成功前提下,往文件写入数据:

1u8 write_buf[32] = {0, 1, 2, 3 ... 31};
2u32 write_len = vfs_write(pfile, (void *)write_buf, 32);
3if (write_len != 0) {
4    //成功将write_buf中write_len长度的数据写入到pfile
5}

2.3.8. 函数u32 vfs_seek(void *pvfile, u32 offset, u32 mode)

此函数实现改变指定文件中读写指针的偏移,其中参数:

1. pvfile:已打开的文件句柄;
2. offset:偏移量;
3. mode:seek模式选择。如图4.2,seek模式有3种,分别为:
    ① SEEK_SET:从文件起始位置开始向后偏移
    ② SEEK_CIR:从文件读写指针位置开始向后偏移
    ③ SEEK_END:从文件末尾位置向前偏移
4. 返回值:0。

备注

mode参数,seek 方式详解:
1. SEEK_SET:从文件起始位置开始向后偏移,首先会判断偏移量是否大于文件长度,若小于则使文件读写指针rw_p = offset;
2. SEEK_CIR:从文件读写指针位置开始向后偏移,使rw_p = rw_p + offset;
3. SEEK_END:从文件末尾位置向前偏移,首先会判断偏移量是否大于文件长度,若小于则使rw_p = 文件长度 - offset;

备注

fat文件系统默认支持的也是小于等于16字符的文件名,v1.9.0版本过后fat文件系统才支持超过16字符的长名功能。
若需要在v.1.9.0版本前fat文件系统使用长名功能,可查看下方链接:

下图为seek模式的选择:

"fs seek"

2.3.9. 函数u32 vfs_file_close(void **ppvfile)

此函数实现关闭文件并释放句柄,其中参数:

1. ppvfile:已打开的文件句柄指针;
2. 返回值:0。

示例:

1vfs_file_close(&pfile);
2if (pfile == NULL) {
3    //成功关闭pfile文件
4}

2.3.10. 函数u32 vfs_fs_close(void **ppvfs)

此函数实现关闭文件系统并释放相关句柄,nor_fs无法使用此功能,其中参数:

1. ppvfs:已挂载的文件系统句柄指针;
2. 返回值:NULL。

示例:

1vfs_fs_close(&pfs);
2if (pfs == NULL) {
3    //成功关闭pfs文件系统
4}

2.3.11. 函数u32 vfs_file_name(void *pvfile, void *name, u32 len)

此函数实现获取指定文件句柄的文件名,其中参数:

1. pvfile:已打开的文件句柄;
2. name:存放文件名的buf;
3. len:获取文件名的长度;
4. 返回值:成功 返回获取文件名的长度;

备注

syd文件系统 和 norfs文件系统 都只支持小于等于16字符的文件名。
fat文件系统默认支持的也是小于等于16字符的文件名,v1.9.0版本过后fat文件系统才支持超过16字符的长名功能。
若需要在v.1.9.0版本前fat文件系统使用长名功能,可查看下方链接:

2.3.12. 函数int vfs_get_attrs(void *pvfile, void *pvfs_attr)

此函数实现记录文件的属性,包括文件大小和地址,nor_fs无法使用此功能,其中参数: ::
  1. pvfile:已打开的文件句柄;

  2. pvfs_attr:文件系统属性,需要传入vfs_attr结构体类型的指针;

  3. 返回值:0。

示例:

1struct vfs_attr file_attr;
2vfs_get_attrs(pfile, &file_attr);
3//文件地址和大小分别保存在file_attr.sclust和file_attr.fsize中

2.3.13. 函数int vfs_ioctl(void *pvfile, int cmd, int arg)

此函数实现对指定文件的相关操作,各文件系统具体的cmd命令请查看《文件系统介绍》小节,其中参数:

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指向的值。

FS_IOCTL_GET_PARTITION_INFO

获取文件系统总容量

FS_IOCTL_GET_FREE_SPACE

获取文件系统剩余容量

2.3.13.1. 函数vfs_ioctl获取总容量命令 FS_IOCTL_GET_PARTITION_INFO

获取文件系统总容量,仅fat有效,参考代码:

1FS_PARTITION_INFO f_info;
2u32 err = vfs_ioctl(pvfile,FS_IOCTL_GET_PARTITION_INFO,(u32)&(f_info))
3if(0 != err)
4{
5    // succeed
6}

2.3.13.2. 函数vfs_ioctl获取剩余容量命令 FS_IOCTL_GET_FREE_SPACE

获取文件系统剩余容量,仅fat有效,参考代码:

1u32 free_apacity_Kbyte;//
2u32 err = vfs_ioctl(pvfile,FS_IOCTL_GET_PARTITION_INFO,(u32)&free_apacity_Kbyte);
3if(0 != err)
4{
5    // succeed
6}