Skip to content

Contributed by Bangbang, organized by Ai-Thinker

Adding the littlefs File System to AI-WB2

littlefs filesystem GitHub repository

<https://github.com/littlefs-project/littlefs>

Actually, I ported it from the Ai-M6X_SDK_release_AiPi_Eyes_SDK.

Attached files:

littlefs_components.zip(765.08 KB, downloads: 2)

The archive contains components and examples. Put the contents of the components folder into the components directory under the AI-WB2 SDK As shown in the figure

The examples go under

A bouffalo.mk was added to the components

Component Makefile

These include paths would be exported to project level

COMPONENT_ADD_INCLUDEDIRS += port littlefs littlefs/bd

not be exported to project level

COMPONENT_PRIV_INCLUDEDIRS :=

This component's src

COMPONENT_SRCS := port/lfs_xip_flash.c littlefs/lfs.c littlefs/lfs_util.c littlefs/bd/lfs_filebd.c littlefs/bd/lfs_rambd.c littlefs/bd/lfs_testbd.c                                  COMPONENT_OBJS := $(patsubst %.c,%.o, $(COMPONENT_SRCS))

COMPONENT_SRCDIRS := port littlefs littlefs/bd

#CPPFLAGS +=

Modified lfs_xip_flash.c

#include "lfs.h" //#include "bflb_flash.h" //#include "bflb_l1c.h" #include <hosal_flash.h>

#define CONFIG_LITTLEFS_FLASH_ADDRESS        0x210000

#ifndef CONFIG_LITTLEFS_FLASH_ADDRESS #error "must define CONFIG_LITTLEFS_FLASH_ADDRESS" #endif

/*****************************************************************************

  • @brief        Read a region in a block. Negative error codes are propagated *               to the user.
  • @param[in]    c
  • @param[in]    block
  • @param[in]    off
  • @param[out]   buffer
  • @param[in]    size
  • @retval int                *****************************************************************************/ int lfs_xip_flash_read(const struct lfs_config *c, lfs_block_t block,                        lfs_off_t off, void *buffer, lfs_size_t size) {     return hosal_flash_raw_read((uint8_t *)buffer, CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size + off, size); }

/*****************************************************************************

  • @brief        Program a region in a block. The block must have previously *               been erased. Negative error codes are propagated to the user. *               May return LFS_ERR_CORRUPT if the block should be considered bad.
  • @param[in]    c
  • @param[in]    block
  • @param[in]    off
  • @param[in]    buffer
  • @param[in]    size
  • @retval int                *****************************************************************************/ int lfs_xip_flash_prog(const struct lfs_config *c, lfs_block_t block,                        lfs_off_t off, const void *buffer, lfs_size_t size) {     return hosal_flash_raw_write((uint8_t *)buffer, CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size + off, size); }

/*****************************************************************************

  • @brief        Erase a block. A block must be erased before being programmed. *               The state of an erased block is undefined. Negative error codes *               are propagated to the user. *               May return LFS_ERR_CORRUPT if the block should be considered bad.
  • @param[in]    c
  • @param[in]    block
  • @retval int
Click to expand full code
c
*****************************************************************************/
int lfs_xip_flash_erase(const struct lfs_config *c, lfs_block_t block)
{
return hosal_flash_raw_erase(CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size, c->block_size);
}

/*****************************************************************************
  • @brief        Sync the state of the underlying block device. Negative error *               codes are propagated to the user.
  • @param[in]    c
  • @retval int
Click to expand full code
c
*****************************************************************************/
int lfs_xip_flash_sync(const struct lfs_config *c)
{
/*!< if use xip, may need to clean cache */
return 0;
}

Create the littlefs task in main()

xTaskCreate(littlefs_task, (char*)"littlefs_task", 512, NULL, 13, NULL);//任务优先级数值越小,优先级越低

The littlefs task runs a simple test

/**************************************************************************** *

  • 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 "littlefs_task.h" #include "lfs.h" #include "lfs_port.h"

#include <blog.h> /* 组件log开关 静态开关 在相应的 proj_config.mk 文件目录下,LOG_ENABLED_COMPONENTS配置上增加对应组件的名字 例如这里需要增加blog_testc组件静态开关,其他组件默认关闭 LOG_ENABLED_COMPONENTS:=blog_testc */

/* 文件log管理 //#define BLOG_HARD_DECLARE_DISABLE 1    // 关 */

/* 私有log管理 静态开关 使用就增加BLOG_DECLARE(…),不用直接不增加此行即可。 BLOG_DECLARE(blog_testc2);    // 打开,其中 "blog_testc2"为用户自定义 //BLOG_DECLARE(main); */

/* 调整等级 blog_set_level_log_component(BLOG_LEVEL_ALL, "blog_demo"); */

BLOG_DECLARE(littlefs);//必需定义???? /****************************************************************************

  • Pre-processor Definitions
Click to expand full code
c
****************************************************************************/

/*!< use memory area after 512k */
#define LITTLEFS_FLASH_SIZE        (0x28000)
#define LITTLEFS_FLASH_BLOCK_SIZE  4096
#define LITTLEFS_FLASH_BLOCK_COUNT (LITTLEFS_FLASH_SIZE / LITTLEFS_FLASH_BLOCK_SIZE)
#define LITTLEFS_FLASH_BLOCK_CYCLE 500

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

lfs_t lfs; lfs_file_t file;

Click to expand full code
c
/*!< configuration of the filesystem is provided by this struct */
const struct lfs_config cfg = {
// block device operations

.read = lfs_xip_flash_read, .prog = lfs_xip_flash_prog, .erase = lfs_xip_flash_erase, .sync = lfs_xip_flash_sync,

// block device configuration .read_size = 16, .prog_size = 16, .lookahead_size = 16, .cache_size = 16,

.block_size = LITTLEFS_FLASH_BLOCK_SIZE, .block_count = LITTLEFS_FLASH_BLOCK_COUNT, .block_cycles = LITTLEFS_FLASH_BLOCK_CYCLE, };

/****************************************************************************

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

/****************************************************************************

  • Functions
Click to expand full code
c
****************************************************************************/

void littlefs_task(void *pvParameters)
{
blog_info_user(littlefs,"mount the filesystem");
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);

// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
blog_error_user(littlefs,"try to reformat");
err = lfs_format(&lfs, &cfg);
if (err) {
blog_error_user(littlefs,"reformat fail");
vTaskDelete(NULL);
}
blog_info_user(littlefs,"reformat success");
blog_info_user(littlefs,"try mount the filesystem");
err = lfs_mount(&lfs, &cfg);
if (err) {
blog_error_user(littlefs,"try mount fail");
vTaskDelete(NULL);
}
}

blog_info_user(littlefs,"mount success");

// 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;

Click to expand full code
c
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);
vTaskDelete(NULL);
while (1) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

Thanks

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