Skip to content

概念先知道

  • LittleFS:为 Flash 设计的轻量文件系统,支持掉电保护(突然断电不丢数据)、磨损均衡与断电恢复,非常适合嵌入式。
  • 与 FATFS 的区别:FATFS 面向 SD 卡/U 盘(与电脑互认),LittleFS 面向片内/外挂 Flash(更省空间、更耐用),二者互不兼容。
  • 分区(Partition):Flash 被分成多个区域。例程用 lfs_xip_init(&lfs_ctx, &lfs_cfg) 挂载名为 PSM 的分区。
  • KV 测试:把“键-值”存成小文件反复读写,验证文件系统在频繁写、断电重启场景下的可靠性。
  • 写放大与磨损均衡:Flash 按块擦除,反复写同一区域会加速老化;LittleFS 通过均衡分布写入位置延长寿命。

例程功能简介

本页对应博流官方 SDK 的 littlefs 例程(examples/littlefs),演示 片内 Flash 上的 LittleFS 用法:

  • 初始化 MTD(bflb_mtd_init)并在 PSM 分区上挂载 LittleFS(lfs_xip_init);
  • 读取文件 boot_count(不存在则创建),值 +1 后写回并打印——每次重启计数加一,验证数据掉电不丢;
  • 通过 SHELL_CMD_EXPORT_ALIAS 注册 kv_test 命令(实现位于 kv_test/ 子目录),串口输入 kv_test 可跑键值读写测试;
  • 最后启动 FreeRTOS 调度器,进入系统运行。

提示

「系统控制」栏目的「掉电保存(EasyFlash)」页也是把配置存进 Flash;本页更底层,直接演示 LittleFS 文件 API,适合需要自己管理文件/键值的场景。

操作步骤

1
进入例程目录

在终端进入 SDK 的 LittleFS 例程目录(前提:已按快速开始(Linux)Windows搭建好环境):

cd examples/littlefs
2
编译工程

执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:

make CHIP=bl616 BOARD=bl616dk
3
烧录固件

用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
运行验证

打开串口助手(波特率 2000000)。例程在片内 Flash 的 PSM 分区上挂载 LittleFS,把“启动次数 boot_count”读出 +1 再写回,串口打印 boot_count: N(重启一次数字加一)。在 bouffalolab /> 提示符输入 kv_test 可运行键值读写测试。

代码执行流程

例程从启动到运行的流程如下:

例程调用的 API 介绍

lfs_xip_init(&lfs_ctx, &lfs_cfg)

在指定 Flash 分区上初始化并挂载 LittleFS。lfs_ctx.partition_name 决定分区名(例程 "PSM"),lfs_cfg 配置块大小/缓存等。

参数

  • ctxlfs_context,含分区名
  • cfglfs_configblock_sizecache_sizeread_size 等)

返回值lfs_t * 文件系统句柄;NULL 表示失败(errno 含错误码)

lfs_file_open / lfs_file_read / lfs_file_write / lfs_file_close(...)

打开/读写/关闭文件。例程用 LFS_O_RDWR | LFS_O_CREAT 打开 boot_count,读回 4 字节计数、lfs_file_rewind 回卷后写回。

参数

  • lfs:文件系统句柄
  • file:文件对象
  • path:文件名(如 boot_count
  • buff / size:数据缓冲与字节数

返回值LFS_ERR_OK(0)成功;负值错误码

bflb_mtd_init()

初始化 Flash 存储设备(MTD),LittleFS 通过它访问分区。

参数:无

返回值0 成功

SHELL_CMD_EXPORT_ALIAS(cmd_kv_test, kv_test, shell kv test)

kv_test 命令注册进 shell(实现见 kv_test/ 子目录),串口输入即触发。

参数:见「Shell 串口命令行」页

返回值:无(宏)

完整代码

以下为 littlefs/main.c 完整源码,与官方示例一致,默认折叠,点击展开(kv_test 实现位于 kv_test/ 子目录):

📜 点击展开 littlefs/main.c 完整代码
c
/****************************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "shell.h"

#include "bflb_mtimer.h"
#include "bflb_flash.h"
#include "bflb_l1c.h"
#include "bflb_uart.h"
#include "board.h"
#include "bflb_mtd.h"

#include "log.h"
#include "lfs.h"
#include "lfs_port.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/****************************************************************************
 * Private Data
 ****************************************************************************/

static struct bflb_device_s *uart0;
static struct lfs_context lfs_ctx = { .partition_name = "PSM" };
static struct lfs_config lfs_cfg = { .read_size = 256,
                                     .prog_size = 256,
                                     .lookahead_size = 256,
                                     .cache_size = 512,
                                     .block_size = 4096,
                                     .block_cycles = 500
                                   };
static lfs_file_t file;
lfs_t *lfs;

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

extern void shell_init_with_task(struct bflb_device_s *shell);
extern void cmd_kv_test(int argc, char **argv);
SHELL_CMD_EXPORT_ALIAS(cmd_kv_test, kv_test, shell kv test);

/****************************************************************************
 * Functions
 ****************************************************************************/

int main(void)
{
    board_init();
    bflb_mtd_init();

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    lfs = lfs_xip_init(&lfs_ctx, &lfs_cfg);
    if (lfs == NULL) {
        LOG_F("lfs_xip_init failed. errno: %d\r\n", errno);
        while (1)
            ;
    }

    // read current count
    uint32_t boot_count = 0;
    lfs_file_open(lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
    lfs_file_read(lfs, &file, &boot_count, sizeof(boot_count));

    // update boot count
    boot_count += 1;
    lfs_file_rewind(lfs, &file);
    lfs_file_write(lfs, &file, &boot_count, sizeof(boot_count));

    // remember the storage is not updated until the file is closed successfully
    lfs_file_close(lfs, &file);

    // release any resources we were using
    // lfs_unmount(&lfs);

    // print the boot count
    printf("boot_count: %d\n", boot_count);

    vTaskStartScheduler();

    while (1) {
    }
}

FAQ

重启后 boot_count 没有增加?

检查是否真的断电重启(EN/RST 复位即可),以及是否烧录覆盖了固件所在 Flash 区域。文件只有正常 lfs_file_close 后写入才算落盘,中途断电可能回滚到旧值——这正是 LittleFS 掉电保护的体现。

`lfs_xip_init failed` 怎么办?

多半是分区配置与固件分区表不匹配:确认工程 partition_cfg 中存在 PSM 分区且大小足够;若分区已被其他功能占用,改 lfs_ctx.partition_name 指向空闲分区。

LittleFS 和 FATFS 怎么选?

数据要拿到电脑上看(日志、图片导出)选 FATFS + SD 卡;数据只在设备上用、看重掉电可靠与寿命(配置、参数、OTA 标志)选 LittleFS + Flash。

`kv_test` 命令没反应?

确认串口提示符已出现(bouffalolab />)且命令名正确;kv_test 的实现与命令注册在 kv_test/ 子目录,若你改动了目录结构需一并编译进去。

Released under the MIT License. Build Time 2026-09-11 14:52:23