Zephyr 实时系统下 W25Q128 + LittleFS 文件系统实战指南

"Flash 选型千千万,文件系统两行泪。" 在嵌入式开发中,选择一款适合 Flash 特性的文件系统至关重要。

今天,基于实际工程项目,从零开始讲解如何在 Zephyr RTOS 上使用 W25Q128 SPI Flash 搭配 LittleFS 文件系统。文章涵盖硬件接线、设备树配置、内核参数调优以及常见问题解决方案.


一、LittleFS 介绍

在嵌入式领域,常见的文件系统有 FATFS、JFFS2、YAFFS、LittleFS 等。选择 LittleFS 的核心理由:

特性 说明
掉电安全 内置磨损均衡和日志机制,写操作原子性有保障
资源占用小 典型 RAM 占用 < 2KB,适合 MCU 环境
抗意外断电 每次写入都有完整性检查,崩溃后可恢复
无需文件系统清理 无需像 FATFS 那样定期执行 fsck

Zephyr 官方将 LittleFS 作为第一方支持的文件系统,提供完整的设备驱动和配置接口。


二、硬件平台

2.1 芯片选型

本项目采用 GD32F450ZGT6(兆易创新,基于 ARM Cortex-M4),主频 200MHz,256KB SRAM,1MB Flash。

2.2 W25Q128 简介

W25Q128 是华邦电子推出的 16MB SPI NOR Flash,性能参数:

参数
容量 16MB(128Mbit)
SPI 频率 支持高达 80MHz
扇区大小 4KB
擦除方式 支持 4KB 扇区、32KB/64KB 块擦除
寿命 10万次擦写周期

三、设备树配置

设备树(Device Tree)是 Zephyr 连接硬件与应用的关键。本项目使用 boards/gd32f450z_eval.overlay 文件进行配置:

dts 复制代码
&spi5 {
    status = "okay";
    pinctrl-0 = <&spi5_default>;
    pinctrl-names = "default";
    cs-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;

    w25q128: w25q128@0 {
        compatible = "jedec,spi-nor";
        reg = <0>;
        spi-max-frequency = <4000000>;   /* 4 MHz */
        size = <0x1000000>;               /* 16 MB */
        jedec-id = [ef 40 18];            /* Winbond W25Q128 */
        status = "okay";
    };
};

&w25q128 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        boot_partition: partition@0 {
            label = "mcuboot";
            reg = <0x00000000 0x00080000>;   /* 512KB 保留区 */
            read-only;
        };

        storage_partition: partition@80000 {
            label = "storage";
            reg = <0x00080000 0x00F80000>;  /* 15.5MB LittleFS 分区 */
        };
    };
};

说明:

  • 前 512KB(0x00000 ~ 0x80000)保留给 bootloader(如 MCUboot)
  • LittleFS 分区从 512KB 开始,占用剩余 15.5MB
  • jedec-id = [ef 40 18] 是 W25Q128 的 JEDEC ID,Zephyr 据此自动匹配驱动

四、Kconfig 内核配置

prj.conf 中启用文件系统和 SPI Flash 支持:

ini 复制代码
# 文件系统支持
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y

# SPI 和 NOR Flash 驱动
CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

# 可选:强制每次重新创建文件系统(调试用)
# CONFIG_APP_WIPE_STORAGE=y

CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 指定 Flash 页大小,W25Q128 的扇区正好是 4KB。

LittleFS 关键参数(按需调优)

参数 默认值 说明
CONFIG_FS_LITTLEFS_CACHE_SIZE 64 文件缓存大小,增大可提升大文件写入性能
CONFIG_FS_LITTLEFS_PROG_SIZE 16 Flash 编程单位,必须为 2 的幂
CONFIG_FS_LITTLEFS_READ_SIZE 16 Flash 读取单位
CONFIG_FS_LITTLEFS_BLOCK_CYCLES 512 磨损均衡参数,值越小磨损越均匀但影响寿命

五、应用层代码实战

5.1 挂载文件系统

c 复制代码
static int littlefs_mount(struct fs_mount_t *mp)
{
    int rc;

    /* 擦除 Flash 存储区(可选) */
    rc = littlefs_flash_erase((uintptr_t)mp->storage_dev);
    if (rc < 0) {
        return rc;
    }

    /* 挂载文件系统 */
    rc = fs_mount(mp);
    if (rc < 0) {
        LOG_ERR("FAIL: mount at %s: %d\n", mp->mnt_point, rc);
        return rc;
    }

    LOG_PRINTK("%s mount: %d\n", mp->mnt_point, rc);
    return 0;
}

5.2 写入文件

c 复制代码
static int write_test_file(const char *fname)
{
    struct fs_file_t file;
    uint8_t buf[64];
    int rc;

    /* 填充测试数据 */
    memset(buf, 0x55, sizeof(buf));

    fs_file_t_init(&file);
    rc = fs_open(&file, fname, FS_O_CREATE | FS_O_RDWR);
    if (rc < 0) {
        LOG_ERR("FAIL: open %s: %d", fname, rc);
        return rc;
    }

    rc = fs_write(&file, buf, sizeof(buf));
    if (rc < 0) {
        LOG_ERR("FAIL: write %s: %d", fname, rc);
    }

    fs_close(&file);
    return rc;
}

六、避坑指南

坑 1:写入失败(文件过大)

症状fs_write() 返回负值,错误码 -22(EINVAL)。

原因 :LittleFS 默认 CACHE_SIZE=64,当写入数据超过缓存大小时,操作被拒绝。


如果觉得有用,别忘了点赞 + 在看 + 转发三连,让更多开发者看到!

🎯 关注、私信即可获得完整工程源码!

相关推荐
ScilogyHunter3 天前
Zephyr串口驱动开发及构建完全指南
驱动开发·uart·zephyr
ScilogyHunter3 天前
Zephyr Hello World应用开发构建完全指南
zephyr·hello world
ScilogyHunter3 天前
Zephyr Twister测试框架完全指南
zephyr·twister
ScilogyHunter4 天前
west init 命令详解
init·zephyr·west
ScilogyHunter4 天前
使用Kconfig配置Zephyr工程完全指南
kconfig·zephyr
ScilogyHunter4 天前
Zephyr设备树完全指南
zephyr
ScilogyHunter5 天前
Zephyr项目按需配置完全指南
zephyr
ScilogyHunter5 天前
Zephyr最简工程配置指南
zephyr
ScilogyHunter5 天前
Zephyr主仓库目录结构完全指南
zephyr
ScilogyHunter5 天前
Zephyr工程配置完全指南
zephyr