2. emFile文件系统架构总览
在把 emFile 集成进一个嵌入式工程之前,先建立一张“全局地图”非常关键。emFile 并不是一个单文件库,而是一套按职责分层组织的文件系统组件:上层是面向应用的 API,中间是文件系统核心与卷管理层,下层是设备驱动与硬件抽象,旁边还有配置宏和工程目录结构把这一切粘合起来。理解这套分层,能帮助你在移植时快速定位“该改哪里、该配什么、该实现哪些函数”。
一、四层结构:从应用到介质
emFile 的架构可以概括为四层,自顶向下依次是:
- 应用层:调用
FS_FOpen、FS_FRead、FS_FWrite、FS_FClose等 API,以文件句柄方式读写数据,不关心底层是 NAND、NOR 还是 SD 卡。 - 文件系统核心层:负责文件与目录管理、FAT 表解析、簇链分配、缓存(Cache)管理、卷挂载与卸载。核心层通过“逻辑卷”抽象访问介质,不直接操作寄存器。
- 驱动层(Device Driver):把核心层的“读扇区/写扇区/擦除块”请求翻译成具体硬件的操作序列。emFile 为每种介质提供驱动模板,如
FS_NAND_HW_...、FS_NOR_HW_...、FS_MMC_HW_...等。 - 硬件抽象层(HAL):最贴近芯片的部分,包含 GPIO 控制、总线时序、DMA 配置、ECC 计算等,通常由用户根据目标 MCU 实现。
这四层之间通过明确的接口函数通信,核心层只依赖驱动层暴露的“设备操作函数表”,因此更换介质时,只需替换驱动层与 HAL,核心层和应用层代码基本不动。
二、API 层次:从通用到专用
emFile 的 API 按功能分为几个层次,集成时按需选用:
- 文件操作 API:
FS_FOpen、FS_FClose、FS_FRead、FS_FWrite、FS_FSeek、FS_FTell,对应标准 C 的fopen/fread/fwrite风格。 - 目录操作 API:
FS_FindFirstFile、FS_FindNextFile、FS_CreateDir、FS_RemoveDir。 - 卷管理 API:
FS_MountVolume、FS_UnmountVolume、FS_FormatVolume、FS_GetVolumeInfo。 - 底层设备 API:
FS_Read、FS_Write、FS_IoCtl,通常由驱动层实现,应用层不直接调用。
这种分层意味着:应用代码只依赖文件/目录 API;移植时只实现底层设备 API 和 HAL;配置时通过宏开关裁剪不需要的功能。
三、配置宏:裁剪与适配的开关
emFile 通过 FS_Config.h 中的宏控制功能裁剪和参数调整。常见的配置宏包括:
| 配置宏 | 作用 | 典型取值 |
|---|---|---|
FS_DEBUG_LEVEL |
调试输出级别 | 0(关闭)~ 3(详细) |
FS_SUPPORT_EFS |
是否支持 EFS 专有格式 | 0 / 1 |
FS_SUPPORT_FAT |
是否支持 FAT12/16/32 | 0 / 1 |
FS_CACHE_SIZE |
扇区缓存大小(字节) | 512 / 1024 / 2048 |
FS_MAX_OPEN_FILES |
最大同时打开文件数 | 4 ~ 16 |
FS_MAX_VOLUMES |
最大挂载卷数 | 1 ~ 4 |
配置宏的取值直接影响 RAM 占用和功能范围。例如 FS_CACHE_SIZE 设为 2048 时,每个卷至少占用 2 KB 缓存;FS_MAX_OPEN_FILES 设为 8 时,需要为每个文件句柄分配结构体空间。集成时应根据 MCU 的 RAM 余量和实际需求折中。
四、工程目录结构:文件该放哪里
一个典型的 emFile 集成工程目录如下:
Project/
├── App/
│ ├── main.c // 应用入口,调用 FS_Init、FS_MountVolume
│ └── app_fs.c // 文件读写业务逻辑
├── emFile/
│ ├── FS/
│ │ ├── FS_Config.h // 配置宏集中定义
│ │ ├── FS_Core.c // 核心层实现
│ │ ├── FS_FAT.c // FAT 解析
│ │ ├── FS_EFS.c // EFS 格式支持
│ │ └── FS_API.c // 对外 API 封装
│ ├── Driver/
│ │ ├── FS_NAND_HW.c // NAND 驱动模板
│ │ ├── FS_NOR_HW.c // NOR 驱动模板
│ │ └── FS_MMC_HW.c // SD/MMC 驱动模板
│ └── HAL/
│ ├── FS_HW_NAND.c // 用户实现的 NAND HAL
│ └── FS_HW_MMC.c // 用户实现的 MMC HAL
└── BSP/
├── bsp_gpio.c // GPIO 初始化
└── bsp_dma.c // DMA 配置
移植时,emFile/FS/ 下的核心文件通常不需要修改,只需在 FS_Config.h 中调整宏;emFile/Driver/ 下选择对应介质的驱动模板;emFile/HAL/ 下实现与 MCU 相关的底层函数。这种目录划分与四层架构一一对应,使工程结构清晰、职责分明。
FS_RAM_HW.c)开始,它不依赖真实硬件,可以快速验证核心层、API 和配置宏是否正确,再逐步替换为 NAND 或 SD 卡驱动。
五、数据流与调用关系
一次典型的文件读取操作,数据流如下:应用调用 FS_FRead → 核心层根据文件句柄找到对应卷和簇链 → 核心层向驱动层发出“读扇区”请求 → 驱动层通过 HAL 操作硬件总线 → 数据从介质读入缓存 → 核心层从缓存拷贝到用户缓冲区 → 返回实际读取字节数。写操作方向相反,并涉及 FAT 表更新和缓存回写。
理解这条链路后,调试时就能按层排查:API 返回错误先看参数和句柄;核心层报错看 FAT 和缓存配置;驱动层超时看 HAL 时序和硬件连接。分层架构的价值,正在于把复杂问题拆解到可独立验证的层次中。