1. Zephyr存储系统概述

大家好,我是你们这堂课的主讲工程师。今天咱们聊聊Zephyr RTOS里的存储系统。说实话,嵌入式开发里存储这块儿,看着不起眼,但坑是真不少。我这些年做项目,光是文件系统选型翻车就遇到过好几次。所以这章,咱们把地基打牢。

1.1 Zephyr RTOS存储架构

Zephyr的存储架构,说白了就是三层结构。底层是硬件,中间是抽象层,上层是给应用用的API。你想想看,这样设计的好处是什么?对,解耦。换块Flash芯片,上层代码基本不用动。

我个人的习惯是,先看这张架构图(虽然这里没图,但我用文字给你画出来):

+-------------------+
|   应用层 (POSIX)   |
+-------------------+
|   文件系统层       |
| (FS/LittleFS/FAT) |
+-------------------+
|   存储设备抽象层   |
| (Flash/SD卡/RAM)  |
+-------------------+
|   硬件驱动层       |
+-------------------+

嗯,这里要注意:Zephyr的存储架构不是一上来就给你定死的。它允许你灵活组合。比如你可以在同一个芯片上,同时跑LittleFS和FAT32,一个管日志,一个管配置。我在一个物联网网关项目里就这么干过,效果不错。

1.2 文件系统选型

选文件系统,说白了就是选「妥协方案」。没有完美的文件系统,只有适合你场景的。我列个表,你一看就明白:

文件系统 适用场景 我踩过的坑
LittleFS 小容量Flash、掉电安全要求高 曾经在4MB Flash上跑,忘了调擦写块大小,结果写速度慢得离谱
FAT32 需要与PC交换数据、SD卡/U盘 记得有一次,客户要求日志文件能在Windows上直接打开,那只能上FAT32
NVS (非易失性存储) 键值对存储、配置参数 这个不是文件系统,但很多人搞混。我习惯用它存WiFi密码、设备ID这类小数据

怎么选?我给你三个判断标准:

  • 容量:小于16MB?LittleFS优先。大于16MB且需要兼容PC?FAT32。
  • 掉电安全:设备可能随时断电?LittleFS的日志结构设计天生抗造。FAT32掉电容易丢文件,我吃过这个亏。
  • 性能要求:频繁小文件写入?LittleFS有磨损均衡。大文件连续读写?FAT32反而更快。

核心建议:别在项目中期换文件系统。我见过一个团队,一开始用FAT32,后来发现掉电丢数据,硬着头皮改LittleFS,结果底层驱动全得重写。选型阶段多花一小时,后期省一周。

1.3 存储设备抽象层介绍

存储设备抽象层,英文叫Storage Device Abstraction Layer,简称SDAL。名字挺唬人,其实就干一件事:让上层文件系统不用关心底层硬件是啥。

举个例子。你写代码时调用fs_open(),底层可能是SPI Flash,也可能是SD卡,甚至是RAM模拟的磁盘。抽象层帮你把这些差异抹平了。

Zephyr里怎么配?看这个配置示例:

# 在prj.conf里启用
CONFIG_FILE_SYSTEM=y
CONFIG_FLASH_MAP=y
CONFIG_STORAGE_FLASH_MAP=y

# 选择文件系统
CONFIG_FILE_SYSTEM_LITTLEFS=y

然后在设备树里指定分区:

&storage_partition {
    compatible = "fixed-partitions";
    #address-cells = <1>;
    #size-cells = <1>;
    partition@0 {
        label = "storage";
        reg = <0x00000000 0x00100000>;  // 1MB
    };
};

嗯,这里有个坑。我曾经在STM32F4上配这个,忘了在设备树里把Flash的擦写块大小设对。结果LittleFS一写就报错,查了两天才发现是erase-size没匹配硬件。你配置时一定要确认:

  • Flash的擦除块大小(通常是4KB或64KB)
  • 文件系统的读写块大小(LittleFS默认是512字节)
  • 分区起始地址要对齐到擦除块边界

我的小技巧:调试存储问题时,先用fs_mkfs()格式化分区,然后用fs_statvfs()看总容量和可用空间。如果这两个值对不上,八成是分区配置有问题。

1.4 实际项目中的选择思路

讲个真实案例。去年我做了一个智能家居网关,需要存三样东西:

  1. 设备配置(几十个键值对)—— 用NVS
  2. 运行日志(循环覆盖,每条几百字节)—— 用LittleFS
  3. 固件升级包(几百KB到几MB)—— 用FAT32,因为需要从SD卡拷贝

你看,一个项目用了三种存储方案。Zephyr完全支持这种混合使用。我当时的做法是:

  • NVS放在内部Flash的一个小分区
  • LittleFS放在外部SPI Flash
  • FAT32放在SD卡槽

这样各司其职,互不干扰。如果你也遇到类似需求,别犹豫,大胆用混合方案。

警告:千万别把NVS和文件系统放在同一个Flash分区里。NVS的写入方式会频繁擦写,而文件系统也有自己的磨损均衡。两者打架,Flash寿命会急剧下降。我曾经在一个原型机上这么干过,三个月后Flash就挂了。

好了,这章就聊到这儿。下一章咱们深入LittleFS,讲讲它的内部结构和配置技巧。有什么问题,欢迎在课程群里讨论。