杰理 SDK 文档中心
首页
首页
  • 项目概览

    • AD23N SDK 概述与芯片平台
    • 工程结构与模块划分
  • 快速开始

    • 开发环境搭建与工具链
    • 编译构建指南
    • 烧录与固件升级工具
  • 应用框架与产品工作流

    • 应用入口与模式调度
    • 音乐播放应用
    • MIDI 解码与键盘演奏
    • 录音应用
    • LINEIN 与扩音应用
    • USB 从设备应用
    • 待机、软关机与空闲检测
    • 公共 UI 与 LED 显示
  • 音频子系统

    • 音频解码器框架
    • 音频编码器框架
    • 音效算法库
    • 音频管理与输出通路
  • 存储与文件系统

    • 文件系统层
    • NOR Flash 与虚拟机存储
    • 设备与设备管理
  • 系统服务与运行时

    • 消息机制与事件分发
    • 按键扫描与输入处理
    • 电源管理与低功耗控制
    • 定时器与系统任务
  • 外设驱动与平台

    • CPU 平台与启动流程
    • USB 协议栈与主机/设备驱动
    • SPI 与通用外设接口
  • 固件升级与构建工具

    • 固件升级机制
    • 编译后处理与镜像打包
    • 构建系统与命令行工具

文件系统层

AD23N GP-MCU SDK 的虚拟文件系统(VFS)抽象层,通过统一的 struct vfs_operations 操作表屏蔽 FAT、norfs、freefs 等底层文件系统的差异,为上层应用提供挂载、文件读写、目录扫描、ioctl 控制等标准文件操作接口。

Purpose and Scope

本文档讲解文件系统层的核心抽象机制与公共 API,包括:

  • VFS 操作表 struct vfs_operations 与句柄模型 struct imount 的设计
  • 文件系统驱动的注册方式(REGISTER_VFS_OPERATIONS 段注册)
  • 挂载(vfs_mount)、文件打开/读写/关闭、扫描与 ioctl 的完整流程
  • 底层驱动(FAT / norfs / freefs)如何通过操作表接入 VFS

以下主题属于兄弟页面,本文不展开:FAT 文件系统内部实现(sdk/app/bsp/common/fs/vfs_fat.c 之外的 fat/ 目录)、norfs / freefs 各自的分区与磨损均衡算法、以及上层应用(如录音、播放列表)对文件系统的具体使用。

概述

在嵌入式 MCU 上,存储介质可能是 SPI NOR Flash、SD 卡或片内 flash,不同介质上的文件系统(FAT、norfs、freefs)接口差异巨大。文件系统层的设计目标是用一张操作函数表 + 一个通用句柄把差异收敛起来:

  • 每个文件系统驱动通过 REGISTER_VFS_OPERATIONS 宏把自身的 struct vfs_operations 实例链接进 .vfs_operations 代码段;
  • vfs_init() 遍历该段逐个调用驱动的 init;
  • vfs_mount() 按 fs_type 字符串匹配驱动并调用其 mount;
  • 之后所有文件操作(open/read/write/seek/close/delete/ioctl)都经由句柄中保存的 ops 表分发到具体驱动。

这套设计让应用层可以完全与底层介质/文件系统解耦:同一份播放器、录音、升级代码既能跑在 FAT(SD 卡/U 盘)上,也能跑在内部 norfs 上,只需在挂载时指定不同的 type。

架构

flowchart TD
    subgraph sg_App["应用层"]
        App["上层应用<br/>(播放/录音/升级)"]
    end

    subgraph sg_VFS["文件系统层 (VFS)"]
        API["vfs_* 公共 API<br/>vfs_mount / vfs_openbypath / vfs_read<br/>vfs_write / vfs_seek / vfs_ioctl"]
        HDL["句柄模型<br/>struct imount {" ops; union pfs/pfile; "}"]
        OPS["操作表<br/>struct vfs_operations"]
    end

    subgraph sg_Drv["底层文件系统驱动"]
        FAT["fatfs 驱动<br/>fs_type = \"fat\""]
        NORFS["norfs 驱动<br/>fs_type = \"norfs\""]
        FREEFS["freefs 驱动<br/>fs_type = \"freefs\""]
    end

    subgraph sg_Dev["存储介质"]
        SD["SD卡 / U盘"]
        NOR["SPI NOR Flash"]
        IFLASH["片内 Flash"]
    end

    App -->|"标准文件接口"| API
    API --> HDL
    HDL -->|"ops 分发"| OPS
    OPS -->|"vfs_ops_begin..vfs_ops_end 段"| FAT
    OPS --> NORFS
    OPS --> FREEFS
    FAT --> SD
    NORFS --> NOR
    FREEFS --> IFLASH

架构要点:

  • 操作表(vtable)是核心抽象:struct vfs_operations(见 vfs.h)定义了 20+ 个函数指针,覆盖挂载、打开(按路径/索引/簇)、创建、读写、定位、删除、属性、扫描、格式化等全部能力。驱动只需实现自己支持的那部分,未实现的指针保持 NULL,VFS 层会返回 E_VFS_OPS。
  • 句柄统一:struct imount(见 vfs.h)只包含 ops 指针和一个联合体 pfs/pfile——同一个结构既充当文件系统句柄(存 pfs)又充当文件句柄(存 pfile),极大简化了资源管理。
  • 段注册机制:驱动实例被链接到 .vfs_operations 段,vfs.c 通过 vfs_ops_begin/vfs_ops_end 边界遍历,实现"新增驱动不改 VFS 核心代码"的开放-封闭原则。

核心实现分析

1. 操作表与注册机制

struct vfs_operations 是文件系统层的"协议",其关键字段(节选自 vfs.h):

struct vfs_operations {
    const char *fs_type;                       // 文件系统类型名,如 "fat" / "norfs" / "freefs"
    void (*init)(void);                        // 驱动初始化
    u32(*mount)(void **ppfs, void *p_device);  // 挂载
    u32(*openbypath)(void *pfs, void **ppfile, const char *path);
    u32(*openbyindex)(void *pfs, void **ppfile, u32 index);
    u32(*createfile)(void *pfs, void **ppfile, u32 *pindex);
    u32(*read)(void *pfile, void *buff, u32 len);
    u32(*write)(void *pfile, void *buff, u32 len);
    u32(*seek)(void *pfile, u32 offset, u32 mode);
    u32(*close_fs)(void **ppfs);
    u32(*close_file)(void **ppfile);
    u32(*fdelete)(void *);
    int (*fget_attr)(void *, void *attr);
    int (*flen)(void *, u32 *parm);
    int (*ftell)(void *, u32 *parm);
    u32(*name)(void *, void *name, u32 len);
    int (*ioctl)(void *, int cmd, int arg);
    int (*fscan_interrupt)(struct vfscan *, void *, const char *path, u8 max_deepth, int (*callback)(void));
    void (*fscan_release)(struct vfscan *);
    int (*fsel)(struct vfscan *, void *, int sel_mode, void **, int);
    int (*file_crc)(void *pfile);
    int (*format)(void **p_fs_hdl, void *device, u32 clust_size, u8 create_new);
};

驱动注册使用段属性宏(vfs.h):

#define REGISTER_VFS_OPERATIONS(ops) \
	const struct vfs_operations ops SEC(.vfs_operations)

Source: vfs.h

设计意图:链接器把所有驱动的操作表按顺序排布在 .vfs_operations 段,vfs.c 用 list_for_each_vfs_operation 宏(vfs.c)在段边界间遍历。相比链表注册,这种段注册零运行时开销、不占 RAM,且天然确定初始化顺序。

2. 初始化与挂载流程

vfs_init() 遍历段内所有操作表,逐个调用 init(vfs.c):

void vfs_init(void)
{
    struct vfs_operations *ops;
    list_for_each_vfs_operation(ops) {
        if (NULL != ops->init) {
            log_info("ops_init!!!\n");
            ops->init();
        }
    }
}

vfs_mount() 是挂载的核心入口(vfs.c):

u32 vfs_mount(void **ppvfs, void *device, void *type)
{
    if ((void *)NULL == *ppvfs) {
        *ppvfs = vfs_hdl_malloc();
        if ((void *)NULL == *ppvfs) {
            return E_NO_VFS;          // 句柄资源不足
        }
    }

    struct imount *pvfs = *ppvfs;
    struct vfs_operations *ops;
    list_for_each_vfs_operation(ops) {
        if (NULL != ops->mount) {
            if (NULL != type) {
                if (0 != strcmp(ops->fs_type, type)) {
                    continue;          // 指定类型时精确匹配
                }
            } else {
                // 未指定类型时跳过 norfs / freefs,优先尝试 FAT
                if (0 == strcmp(ops->fs_type, "norfs")) { continue; }
                if (0 == strcmp(ops->fs_type, "freefs")) { continue; }
            }
            if (0 == ops->mount(&(pvfs->pfs), device)) {
                pvfs->ops = ops;       // 绑定成功,保存操作表
                return 0;
            } else {
                if (NULL != ops->close_fs) {
                    ops->close_fs(&(pvfs->pfs));   // 挂载失败需清理
                }
            }
        }
    }
    *ppvfs = vfs_fhdl_free(*ppvfs);    // 全部失败则释放句柄
    return E_NO_FS;
}

Source: vfs.c

值得注意的设计细节:

  • type 为 NULL 的默认行为:遍历时会跳过 norfs 和 freefs,即默认挂载优先尝试 FAT——因为 FAT 通常用于可移动介质(SD/U 盘),而内部 flash 文件系统需要显式指定类型。这避免了在无外部介质时误挂内部文件系统。
  • 失败回滚:单个驱动 mount 失败会调用其 close_fs 做清理;所有驱动都失败后释放 VFS 句柄并返回 E_NO_FS,不留悬挂资源。
  • 挂载成功后 pvfs->ops 被保存,后续所有文件操作都从这个句柄取操作表。

3. 文件打开与读写分发

vfs_openbypath() 展示了一致的分发模式(vfs.c):

u32 vfs_openbypath(void *pvfs, void **ppvfile, const char *path)
{
    if ((void *)NULL == *ppvfile) {
        *ppvfile = vfs_hdl_malloc();
        if ((void *)NULL == *ppvfile) {
            return E_NO_VFS;
        }
    }
    ...
    p_vfile->ops = p_vfs->ops;              // 文件句柄继承文件系统句柄的 ops
    ops = p_vfs->ops;

    if (NULL != ops->openbypath) {
        err = ops->openbypath(p_vfs->pfs, &p_vfile->pfile, path);
    } else {
        err = E_VFS_OPS;                    // 驱动未实现该操作
    }
__vfs_openbypath:
    if (0 != err) {
        vfs_file_close(ppvfile);            // 失败自动回收文件句柄
    }
    return err;
}

Source: vfs.c

要点:

  • 句柄继承:文件句柄的 ops 直接从文件系统句柄复制,因此一次挂载后,打开/读/写/关闭都无需再传文件系统句柄——struct imount 的联合体设计让 pfile 与 pfs 共用同一内存布局,vfs_read/write/seek/close 等接口的入参类型可以完全统一。
  • 懒分配与自动回收:句柄在首次使用时才从 vfs_hdl_malloc() 资源池分配;任何失败路径都会把已分配的句柄释放掉,上层无需关心清理。
  • 同一模式还用于 vfs_openbyindex(按文件序号打开)、vfs_openbyfile(按扩展名匹配打开)和 vfs_createfile(新建文件)。

4. 文件属性 / 删除 / 扫描适配层

vfs_fat.c 中的 vfs_get_fsize()、vfs_ftell()、vfs_file_delete() 是 VFS 公共 API 的薄封装,统一通过 ops 分发(vfs_fat.c):

u32 vfs_file_delete(void *pvfile)
{
    struct imount *p_vfile = pvfile;
    if ((void *)NULL == p_vfile) {
        return E_FS_PFILE;                // 非法句柄
    }
    struct vfs_operations *ops;
    ops = p_vfile->ops;
    if (((void *)NULL != ops)  && ((void *)NULL !=  ops->fdelete)) {
        u32 res = E_VFS_OPS;
        if (NULL != (p_vfile->pfile)) {
            res = ops->fdelete(p_vfile->pfile);
            if (0 != res) {
                return E_FS_PFILE;
            }
        }
        return res;
    }
    return  E_VFS_OPS;                    // 驱动未实现删除
}

Source: vfs_fat.c

文件扫描是文件系统层最复杂的部分,参数解析器 __fscan_arg_handler() 支持类似命令行风格的扫描选项(vfs_fat.c):

/*
 * -t  文件类型
 * -r  包含子目录
 * -d  扫描文件夹
 * -a  文件属性 r: 读, /: 非
 * -s  排序方式, t:按时间排序, n:按文件号排序
 */
static void __fscan_arg_handler(struct vfscan *fs, const char *arg)
{
    int step = 0;
    char *p;

    /*
     * fs->attr = F_ATTR_RO: 搜索只读文件
     * fs->attr = F_ATTR_ARC: 搜索非读文件
     * fs->attr = F_ATTR_ARC | F_ATTR_RO: 搜索所有文件
     */
    fs->attr = F_ATTR_ARC | F_ATTR_RO;      // 默认扫描所有属性

    while (*arg) {
        switch (step) {
        case 0:
            if (*arg == '-') { step = 1; }
            break;
        case 1:
            if (*arg == 't') { step = 2; p = fs->ftype; fs->scan_file = 1; }
            ...
        }
    }
}

Source: vfs_fat.c

设计意图:扫描接口 fscan_interrupt 支持中断回调(int (*callback)(void)),便于在扫描大量文件时让出 CPU 或响应按键/低电量事件;fscan_release 负责释放扫描过程中动态分配的资源(如长文件名缓冲),避免长时间扫描导致的内存泄漏。

5. ioctl 命令集

VFS 通过 FS_IOCTL_* 枚举向应用暴露底层能力(vfs.h),常用命令包括:

命令用途
FS_IOCTL_GET_FILE_NUM获取文件总数
FS_IOCTL_FILE_CHECK文件完整性检查
FS_IOCTL_FREE_CACHE释放文件系统缓存
FS_IOCTL_SET_NAME_FILTER设置文件名过滤规则
FS_IOCTL_GET_FOLDER_INFO获取文件夹序号与文件数
FS_IOCTL_SET_LFN_BUF / FS_IOCTL_SET_LDN_BUF设置长文件名/长目录名缓冲(512B)
FS_IOCTL_SET_EXT_TYPE设置后缀类型过滤
FS_IOCTL_OPEN_DIR / FS_IOCTL_ENTER_DIR / FS_IOCTL_EXIT_DIR目录导航
FS_IOCTL_MK_DIR创建文件夹
FS_IOCTL_FILE_SYNC文件同步落盘
FS_IOCTL_GET_PARTITION_INFO获取分区信息(簇大小、容量)
FS_IOCTL_GET_FREE_SPACE获取剩余空间
FS_IOCTL_RESET_VFSCAN重置扫描状态

ioctl 的入参 cmd 直接透传给驱动操作表的 ioctl 函数,因此各文件系统可以在此基础上扩展私有命令,VFS 层无需为每个新能力新增接口。

核心流程

下图展示了从系统启动到一次完整文件读写操作的真实调用链:

sequenceDiagram
    participant App as 应用
    participant VFS as vfs.c 公共层
    participant OPS as struct vfs_operations
    participant FAT as fat/norfs/freefs 驱动
    participant DEV as 存储设备

    App->>VFS: vfs_init()
    VFS->>OPS: 遍历 .vfs_operations 段
    OPS-->>VFS: 逐个调用 init()
    App->>VFS: vfs_mount(&pfs, dev, "fat")
    VFS->>VFS: vfs_hdl_malloc() 分配 imount
    VFS->>OPS: strcmp(fs_type, "fat") 匹配
    OPS->>FAT: mount(&pfs, dev)
    FAT->>DEV: 读取分区/目录表
    FAT-->>VFS: 成功,绑定 pvfs->ops
    App->>VFS: vfs_openbypath(pfs, &pf, "REC/A001.MP3")
    VFS->>VFS: vfs_hdl_malloc() 分配文件句柄
    VFS->>OPS: pfile->ops = pfs->ops(继承)
    OPS->>FAT: openbypath(pfs, &pfile, path)
    FAT-->>VFS: 打开成功
    App->>VFS: vfs_read(pf, buf, len)
    VFS->>OPS: ops->read(pfile, buf, len)
    OPS->>FAT: read 数据
    FAT->>DEV: 读取扇区/页
    FAT-->>VFS: 返回实际读取长度
    VFS-->>App: 字节数
    App->>VFS: vfs_seek(pf, offset, SEEK_SET)
    App->>VFS: vfs_file_close(&pf)
    VFS->>OPS: ops->close_file(&pfile)
    OPS->>FAT: 关闭并释放资源

流程关键点:

  1. 初始化阶段:vfs_init() 只做驱动级初始化(如注册设备、准备资源池),不挂载任何文件系统;挂载是应用按需发起的。
  2. 挂载阶段:vfs_mount 内部完成句柄分配 → 类型匹配 → 驱动挂载 → 绑定 ops 四步;类型不匹配或挂载失败都会继续尝试下一个驱动。
  3. 打开阶段:文件句柄的 ops 从文件系统句柄复制,此后读写调用不再携带文件系统句柄,这是 struct imount 联合体设计的直接收益。
  4. 读写阶段:所有读写最终落到驱动实现,VFS 层不做数据缓冲(缓存策略由各驱动决定,如 FAT 的扇区缓存),保证抽象层开销极低。
  5. 关闭阶段:vfs_file_close 释放文件句柄;句柄资源不足时返回 E_NO_VFS,驱动未实现时返回 E_VFS_OPS。

使用示例

示例 1:挂载并遍历驱动

应用可通过 vfs_type_name 查询已挂载文件系统的类型名(vfs.c):

void *vfs_type_name(void *p_vfs)
{
    if (NULL == p_vfs) {
        return NULL;
    }
    log_info("p_vfs 0x%x", (u32)p_vfs);
    struct imount *pvfs = p_vfs;
    struct vfs_operations *ops = pvfs->ops;
    log_info("ops 0x%x", (u32)ops);
    if (NULL == ops) {
        return NULL;
    }
    return (void *)ops->fs_type;
}

Source: vfs.c

示例 2:注册一个新文件系统驱动

驱动只需定义操作表并用段注册宏挂入系统,即可被 vfs_init / vfs_mount 自动发现:

const struct vfs_operations my_fs_ops SEC(.vfs_operations) = {
    .fs_type = "myfs",
    .init = my_fs_init,
    .mount = my_fs_mount,
    .openbypath = my_fs_open,
    .read = my_fs_read,
    .write = my_fs_write,
    .close_file = my_fs_close,
};

段注册宏定义见 Source: vfs.h;操作表完整字段见 vfs.h

示例 3:读取文件大小与删除文件

u32 fsize = 0;
vfs_get_fsize(pfile, &fsize);       // 经 ops->flen 分发

u32 err = vfs_file_delete(pfile);    // 经 ops->fdelete 分发,删除失败返回 E_FS_PFILE

实现见 Source: vfs_fat.c 与 vfs_fat.c

API 参考

公共 API 声明见 vfs.h,实现位于 vfs.c 与 vfs_fat.c。

函数签名说明典型返回
vfs_initvoid vfs_init(void)遍历 .vfs_operations 段调用所有驱动的 init—
vfs_mountu32 vfs_mount(void **ppvfs, void *device, void *type)分配句柄、按 fs_type 匹配驱动并挂载;type=NULL 时跳过 norfs/freefs 优先尝试 FAT0 成功;E_NO_VFS 句柄不足;E_NO_FS 无可用文件系统
vfs_openbypathu32 vfs_openbypath(void *pvfs, void **ppvfile, const char *path)按路径打开文件,句柄继承 pfs 的 ops0 成功;E_VFS_HDL 文件系统句柄为空;E_VFS_OPS 未实现
vfs_openbyindexu32 vfs_openbyindex(void *pvfs, void **ppvfile, u32 index)按文件序号打开(配合 FS_IOCTL_GET_FILE_NUM 使用)同上
vfs_openbyfileu32 vfs_openbyfile(void *pcvfile, void **ppvfile, void *ext_name)按扩展名/类型匹配打开(歌词等关联文件)同上
vfs_createfileu32 vfs_createfile(void *pvfs, void **ppvfile, u32 *pindex)新建文件并返回索引同上
vfs_readu32 vfs_read(void *pvfile, void *buf, u32 len)读文件,经 ops->read 分发实际读取字节数
vfs_writeu32 vfs_write(void *pvfile, void *buf, u32 len)写文件,经 ops->write 分发实际写入字节数
vfs_seeku32 vfs_seek(void *pvfile, u32 offset, u32 mode)定位,mode 取 SEEK_SET/SEEK_CUR/SEEK_END0 成功
vfs_file_closeu32 vfs_file_close(void **ppvfile)关闭文件并释放句柄0 成功
vfs_fs_closeu32 vfs_fs_close(void **ppvfs)卸载文件系统0 成功
vfs_file_nameu32 vfs_file_name(void *pvfile, void *name, u32 len)取文件名长度
vfs_get_attrsint vfs_get_attrs(void *pvfile, void *pvfs_attr)取 struct vfs_attr(attr/fsize/sclust)0 成功
vfs_get_fsizeint vfs_get_fsize(void *pvfile, void *parm)取文件大小大小;句柄为空返回 0
vfs_ftellint vfs_ftell(void *pvfile, void *parm)取当前读写位置偏移;句柄为空返回 0
vfs_file_deleteu32 vfs_file_delete(void *pvfile)删除文件(关闭由上层负责)0 成功;E_FS_PFILE 删除失败
vfs_ioctlint vfs_ioctl(void *pvfile, int cmd, int arg)透传 FS_IOCTL_* 命令到驱动驱动定义
vfs_delete_dirint vfs_delete_dir(void *pvfs, char *path)删除目录0 成功
vfs_file_crcint vfs_file_crc(void *pvfile)计算文件 CRC校验值
vfs_type_namevoid *vfs_type_name(void *p_vfs)返回已挂载文件系统的 fs_type 字符串类型名;无效句柄返回 NULL

错误码(errno-base.h 定义):

错误码含义触发场景
E_NO_VFSVFS 句柄资源不足vfs_hdl_malloc() 返回 NULL
E_NO_FS无可用文件系统所有驱动 mount 均失败
E_VFS_HDL无效文件系统句柄vfs_openbypath 传入 NULL pfs
E_VFS_OPS驱动未实现该操作对应 ops 函数指针为 NULL
E_FS_PFILE文件操作失败删除/读写时 pfile 无效

失败模式与边界情况

  • 挂载失败回滚:vfs_mount 中单个驱动挂载失败会调用其 close_fs;全部失败后释放句柄返回 E_NO_FS(vfs.c)。上层应据此决定是重试还是切换存储介质。
  • 打开失败自动回收:vfs_openbypath 在错误路径调用 vfs_file_close 释放句柄,防止文件描述符泄漏(vfs.c)。
  • 未实现操作:驱动可以只实现部分函数,VFS 层统一返回 E_VFS_OPS。新增能力(如格式化)不会破坏老驱动。
  • 删除与关闭分离:vfs_file_delete 只删数据不关句柄(注释明确"SH系列文件关闭在外面应用"),若上层先关闭再删除,驱动内部会处理 pfile 为空的场景。
  • 并发与重入:VFS 层本身无锁,句柄分配与释放依赖 vfs_resource 的资源池;FAT 驱动内部的缓存/目录表访问互斥由驱动实现保证。扫描接口提供 callback 中断钩子,避免长扫描阻塞中断上下文(vfs_fat.c)。
  • 长文件名内存:LFN/LDN 缓冲需通过 FS_IOCTL_SET_LFN_BUF / FS_IOCTL_SET_LDN_BUF(各 512B)显式配置,扫描长文件名目录前必须设置,否则可能截断(vfs.h)。

性能与运维

  • 零拷贝抽象:VFS 层只是函数指针分发,读写数据直接传入驱动,无中间缓冲,适合音频流等大数据量场景。
  • 段注册零 RAM 开销:操作表保存在 Flash 的 .vfs_operations 段,运行时仅遍历指针,启动初始化耗时与驱动数量线性相关且极小。
  • 缓存管理:FS_IOCTL_FREE_CACHE 可在低内存场景(如录音开始前)主动释放 FAT 缓存;FS_IOCTL_FILE_SYNC 用于关键数据落盘。
  • 句柄资源:vfs_hdl_malloc / vfs_fhdl_free(vfs.h)基于静态资源池,句柄数量有限,应用应配对使用 open/close,防止 E_NO_VFS。

扩展点

  1. 新增文件系统:实现 struct vfs_operations 并用 REGISTER_VFS_OPERATIONS 注册即可,fs_type 需唯一;挂载时通过 type 参数选择。
  2. 私有 ioctl:在 FS_IOCTL_* 基础上,驱动可扩展自定义 cmd 编号,应用经 vfs_ioctl 透传。
  3. 扫描策略:通过 __fscan_arg_handler 支持的 -t/-r/-d/-a/-s 选项组合,可实现按类型、递归、属性、排序等定制扫描。
  4. 格式化:驱动实现 format 函数指针后,应用可对设备执行格式化(指定簇大小与是否新建)。

相关链接

  • vfs.h 头文件(操作表与 API 声明)
  • vfs.c 核心实现(init/mount/openbypath)
  • vfs_fat.c FAT 适配层(fsize/ftell/delete/扫描参数解析)
  • free_fs 内部文件系统实现
  • nor_fs 资源表
  • VFS 资源分配(vfs_resource.c)
Next
NOR Flash 与虚拟机存储