Skip to content

Concepts First ​

  • LittleFS: a lightweight file system designed for Flash with power-loss protection (no data loss on sudden power-off), wear leveling, and power-loss recovery — ideal for embedded use.
  • Difference from FATFS: FATFS targets SD cards/USB drives (interoperable with PCs); LittleFS targets on-chip or external Flash (more space-efficient and durable). The two are incompatible.
  • Partition: Flash is split into regions. This example mounts the partition named PSM with lfs_xip_init(&lfs_ctx, &lfs_cfg).
  • KV test: storing "key-value" pairs as small files and reading/writing them repeatedly, verifying reliability under frequent writes and power cycles.
  • Write amplification & wear leveling: Flash erases by block; repeatedly writing the same area ages it faster. LittleFS spreads writes across the device to extend its life.

Example Overview ​

This page is based on the littlefs example in the official Bouffalo SDK (examples/littlefs), which demonstrates LittleFS on on-chip Flash:

  • Initializes MTD (bflb_mtd_init) and mounts LittleFS on the PSM partition (lfs_xip_init);
  • Reads the file boot_count (created if missing), increments it, writes it back, and prints it — the counter survives restarts, proving data persistence;
  • Registers the kv_test shell command via SHELL_CMD_EXPORT_ALIAS (implementation in the kv_test/ subdirectory) for key-value read/write tests;
  • Finally starts the FreeRTOS scheduler and runs the system.

Note

The "Power-Off Saving (EasyFlash)" page in System Control also stores config into Flash; this page is lower-level and shows the LittleFS file APIs directly, suitable for managing your own files/key-values.

Operation Steps ​

1
Enter the Example Directory

Open a terminal and enter the SDK LittleFS example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/littlefs
2
Build the Project

Run the build command. The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:

make CHIP=bl616 BOARD=bl616dk
3
Flash the Firmware

Connect the board with a USB cable, hold the BOOT button (IO2 on the Ai-M61-32S-Kit), briefly press EN/RST to enter download mode, then flash (replace the serial port with the one on your computer):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
Run and Verify

Open a serial tool (baud rate 2000000). The example mounts LittleFS on the on-chip Flash PSM partition, reads the boot counter boot_count, increments it, and writes it back — the serial prints boot_count: N (increments on each restart). At the bouffalolab /> prompt, type kv_test to run the key-value read/write test.

Code Execution Flow ​

The flow from boot to running is:

APIs Used by the Example ​

lfs_xip_init(&lfs_ctx, &lfs_cfg) ​

Initializes and mounts LittleFS on a Flash partition. lfs_ctx.partition_name selects the partition (here "PSM"); lfs_cfg sets block/cache sizes.

Parameters:

  • ctx: lfs_context including the partition name
  • cfg: lfs_config (block_size, cache_size, read_size, etc.)

Returns: lfs_t * file system handle; NULL on failure (errno holds the error code)

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

Opens, reads/writes, and closes files. The example opens boot_count with LFS_O_RDWR | LFS_O_CREAT, reads 4 bytes, rewinds with lfs_file_rewind, and writes the new value back.

Parameters:

  • lfs: file system handle
  • file: file object
  • path: file name (e.g., boot_count)
  • buff / size: data buffer and byte count

Returns: LFS_ERR_OK (0) on success; negative error codes

bflb_mtd_init() ​

Initializes the Flash storage device (MTD); LittleFS accesses partitions through it.

Parameters: none

Returns: 0 on success

SHELL_CMD_EXPORT_ALIAS(cmd_kv_test, kv_test, shell kv test) ​

Registers the kv_test command in the shell (implementation in kv_test/); typing it over serial triggers the test.

Parameters: see "Shell Command Line"

Returns: none (macro)

Complete Code ​

The following is the complete source of littlefs/main.c, identical to the official example, collapsed by default (the kv_test implementation lives in kv_test/):

📜 Click to expand littlefs/main.c full code
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` does not increase after restart?

Check that you really power-cycled (an EN/RST reset works) and that flashing did not overwrite the Flash region holding the firmware. Writes only land after a successful lfs_file_close; an interrupted write may roll back — that's LittleFS power-loss protection at work.

`lfs_xip_init failed`. What now?

Usually a partition mismatch: confirm a PSM partition exists in the project partition config with enough size; if the partition is occupied, point lfs_ctx.partition_name at a free one.

LittleFS or FATFS?

If data must be readable on a PC (logs, exported images), choose FATFS + SD card. If data is only used on the device and you value power-loss reliability and Flash longevity (config, parameters, OTA flags), choose LittleFS + Flash.

The `kv_test` command does nothing.

Make sure the bouffalolab /> prompt is up and the command name is correct. The kv_test implementation and registration live in the kv_test/ subdirectory; if you changed the directory structure, it must be compiled in too.

Released under the MIT License. Build Time 2026-09-30 17:31:25