3. 存储介质与硬件接口选型
在 emFile 集成工程中,存储介质选型不是“随便挑一个能读写的器件”,而是决定驱动层结构、挂载方式、性能上限和可靠性的第一步。emFile 通过 FS_DEV_INFO 描述设备能力,通过 驱动 API(如 FS_Read、FS_Write、FS_IoCtl)与底层介质交互,因此不同介质的电气接口、访问粒度、擦除特性和寿命管理方式,会直接映射到驱动实现和配置参数上。
四类介质的电气与访问特性对比
NOR Flash 通常提供并行或 SPI 接口。并行 NOR 有独立的地址线和数据线,支持 XIP(片内执行),随机读取延迟低,适合存放启动代码和小容量参数区;SPI NOR 引脚少、封装小,但命令开销大,适合配置存储。NOR 的擦除单位一般是 4 KB 扇区,写入前必须擦除,且擦除次数约 10 万次量级。在 emFile 中,NOR 常配合 日志型或块型驱动,若直接映射为块设备,需要处理“写前擦除”和写放大问题。
NAND Flash 分为 SLC、MLC、TLC,接口有并行和 SPI。它的特点是容量大、单位成本低,但存在坏块、位翻转和需要 ECC 的问题。NAND 的页大小常见为 2 KB 或 4 KB,擦除块为 128 KB 或更大。emFile 对 NAND 的支持通常依赖 FTL(Flash Translation Layer) 或控制器内置的坏块管理。若使用裸 NAND,驱动必须实现坏块表、ECC 校验和磨损均衡,否则文件系统在长期写入后会出现不可恢复错误。
SD 卡和 eMMC 都属于块设备,接口分别为 SD 总线和 MMC 总线。SD 卡通过 SDIO 或 SPI 访问,eMMC 则直接焊接在板卡上,使用 8 位并行数据线,支持 HS200/HS400 高速模式。两者内部都集成了控制器和 FTL,对外表现为固定扇区(通常 512 B)的块设备。emFile 对这类介质通常使用 FS_DEV_INFO 中的块设备接口,驱动只需实现读块、写块和获取容量,不需要关心擦除和坏块。但要注意:SD 卡在掉电时可能丢失内部映射表,eMMC 的可靠性和寿命通常优于消费级 SD 卡。
RAM Disk 是内存中的块设备,读写速度极快,无擦除限制,但掉电即失。它适合存放临时文件、日志缓冲或作为文件系统性能基准。在 emFile 中,RAM Disk 驱动只需提供一块连续内存和读写函数,配置最简单,常用于验证文件系统逻辑或做高速缓存层。
emFile 驱动适配的关键参数与配置
在 emFile 中,每种介质都需要在 FS_DEV_INFO 结构体中填写关键参数。以块设备为例,典型字段包括:NumSectors(总扇区数)、BytesPerSector(每扇区字节数,通常 512)、pfRead 和 pfWrite 函数指针。对于 NOR 和 NAND,还需要通过 FS_IoCtl 提供擦除命令或坏块查询接口。
下面是一个简化的 SD 卡块设备驱动配置示例,展示 emFile 如何获取设备信息并挂载:
static FS_DEV_INFO _DevInfo;
static U8 _acBuffer[512];
static int _ReadBlock(U32 Sector, void *pBuffer, U32 NumSectors) {
// 调用 SD 卡底层读函数,按 512 字节扇区读取
return SD_ReadBlocks(Sector, pBuffer, NumSectors);
}
static int _WriteBlock(U32 Sector, const void *pBuffer, U32 NumSectors) {
return SD_WriteBlocks(Sector, pBuffer, NumSectors);
}
void MountSDCard(void) {
_DevInfo.NumSectors = SD_GetSectorCount();
_DevInfo.BytesPerSector = 512;
_DevInfo.pfRead = _ReadBlock;
_DevInfo.pfWrite = _WriteBlock;
FS_Mount("sd:", &_DevInfo, 0, 0);
}
对于 NAND Flash,驱动层通常需要额外实现 FS_IoCtl 中的 FS_CMD_ERASE_SECTOR 或 FS_CMD_GET_BAD_BLOCK。如果使用带 FTL 的 NAND 控制器,则驱动可以像 SD 卡一样只实现块读写,由控制器完成坏块管理和磨损均衡。此时 emFile 的配置与块设备一致,但需要确认控制器的扇区大小与 emFile 期望的 512 字节是否匹配,若不匹配需在驱动中做转换。
电气特性对硬件设计的影响
NOR Flash 的并行接口需要地址线和数据线,PCB 布线较多,但访问时序简单;SPI NOR 只需 4 根线,适合引脚受限的 MCU。NAND 的并行接口有 8 位或 16 位数据线,外加 CLE、ALE、CE、RE、WE 等控制线,布线复杂度高,且需要上拉电阻保证空闲状态。SD 卡通过 SDIO 接口时,需要 4 位数据线、时钟和命令线,注意上拉电阻和走线等长;eMMC 则直接焊接,数据线更多,但省去了连接器可靠性问题。
电源方面,NOR 和 NAND 通常使用 3.3 V 或 1.8 V,SD 卡支持 3.3 V 和 1.8 V 双电压,eMMC 多为 1.8 V 或 3.3 V。RAM Disk 不涉及外部电源,但需要确保内存区域不被其他任务覆盖。在掉电保护上,SD 卡和 eMMC 内部有缓存,突然断电可能导致数据丢失或文件系统损坏,建议在 emFile 中启用 日志或写保护机制,或在硬件上增加掉电检测电路,在电压跌落时及时刷新缓存。
选型决策与验证方法
实际选型时,可以按以下顺序判断:第一,是否需要 XIP 或极小容量参数存储,若是则选 NOR;第二,是否需要大容量且成本敏感,且能接受 FTL 管理,则选 NAND;第三,是否需要可插拔或大容量通用存储,则选 SD 卡;第四,是否需要高可靠、抗振动、长寿命的嵌入式存储,则选 eMMC;第五,是否只需要临时高速缓存或性能基准,则选 RAM Disk。
验证时,建议在目标硬件上执行以下测试:连续写入大文件并测量吞吐量;随机读写小文件并观察延迟;反复掉电重启,检查文件系统是否仍可挂载;对于 NAND,还需检查坏块增长和 ECC 纠错计数。emFile 提供了 FS_GetVolumeInfo 等接口,可以读取剩余空间和簇大小,帮助判断驱动配置是否正确。若挂载失败,优先检查 NumSectors 是否与实际容量一致、扇区大小是否为 512、读写函数是否返回正确错误码。