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,当写入数据超过缓存大小时,操作被拒绝。


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

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

相关推荐
mftang10 小时前
Zephyr RTOS 下 BLE 主动扫描和被动扫描详解
被动扫描·蓝牙协议栈·zephyr·主动扫描
mftang1 天前
Zephyr RTOS中bt_conn_le_create 函数用法详细介绍
zephyr·ble central
mftang11 天前
Zephyr RTOS 中 BT_CONN_CB_DEFINE 详解
zephyr·central·peripheral·注册回调
mftang1 个月前
Nordic nRF52805 Zephyr OS下低功耗模式应用详细介绍-D
watchdog·低功耗·zephyr
硬汉嵌入式1 个月前
Zephyr 十周年报告:开源嵌入式创新的十年历程
zephyr
fitpolo1 个月前
串行通讯(I2C)
zephyr
mftang3 个月前
Zephyr RTOS中的k_stack相关函数
zephyr·k_stack
fitpolo3 个月前
向控制台打印消息并进行日志记录
zephyr
智驾3 个月前
【瑞萨RA8D1 LVGL/LWIP评测】二、CPKCOR-RA8D1B Zephyr工程适配
瑞萨·zephyr·ra8d1 lvgl/lwip