概念先知道
- 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,适合需要自己管理文件/键值的场景。
操作步骤
在终端进入 SDK 的 LittleFS 例程目录(前提:已按快速开始(Linux)或Windows搭建好环境):
cd examples/littlefs执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:
make CHIP=bl616 BOARD=bl616dk用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):
make flash CHIP=bl616 COMX=/dev/ttyUSB0打开串口助手(波特率 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 配置块大小/缓存等。
参数:
ctx:lfs_context,含分区名cfg:lfs_config(block_size、cache_size、read_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)成功;负值错误码
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 完整代码
/****************************************************************************
*
* 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/ 子目录,若你改动了目录结构需一并编译进去。

