KDocs 研发资料库
  • 视频技术应用资料与文档入口汇总
  • Window下使用Makefile编译代码教程
  • AC52系列PWM使用说明文档
  • AC57系列PWM使用说明文档
  • 52 系列_串口外设的使用说明
  • 57 系列_串口外设的使用说明
  • AC52系列SPI使用说明文档
  • AC57系列SPI使用说明文档
  • AC52系列外部中断使用说明文档
  • AC57系列外部中断使用说明文档
  • AC54&56外部中断使用说明文档
  • AC52 红外捕获中断demo使用说明文档
  • 视频系列SDK汇总及获取方法
  • AC52系列软件典型问题整理文档获取
  • AC791N开发-入门到进阶开发指导文档(完善ing)
  • AC792N开发-入门到进阶开发指导文档(完善ing)
  • 792 littlefs文件系统配置
  • 792N系列 U盘单备份升级说明
  • 792x串口uart升级说明参考

792 littlefs文件系统配置

📎 原始文档:https://www.kdocs.cn/l/crgx0wgHYfWc 792 littlefs配置

在线文档

10.6. LittleFs — JL Project Documentation

配置

通过codeblock编译,请修改如下

添加littlefs源码到cbp工程
image

补充头文件搜索路径
......\common\example\third_party\littlefs
......\common\example\third_party\littlefs\bd
image

image

通过vscode编译,请修改对应makefile如下:

image

    -I../../../../apps/common/example/third_party/littlefs \
    -I../../../../apps/common/example/third_party/littlefs/bd \

image

    ../../../../apps/common/example/third_party/littlefs/lfs_test.c \
    ../../../../apps/common/example/third_party/littlefs/port/wl82/port.c \
    ../../../../apps/common/example/third_party/littlefs/lfs.c \
    ../../../../apps/common/example/third_party/littlefs/lfs_util.c \

应用层配置参考

image

imageimage

image

    // block device configuration
    .read_size = 4*1024,
    .prog_size = 4*1024,
    .block_size = 4*1024,
    .block_count = 44444444,
    .cache_size = 4*1024,
    .block_cycles = 100000,

cfg.context = (void *)((lfs_addr/(cfg.block_size)+1)*cfg.block_size);

擦写函数修改如下
否则出现文件读异常问题
image

static int lfs_flash_block_erase(const struct lfs_config *c, lfs_block_t block)
{
    //注意
    // 4K对应是IOCTL_ERASE_SECTOR
    // 64K对应IOCTL_ERASE_BLOCK

    // 断言:block_size 必须是 4K 或 64K,否则直接断言重启
    ASSERT((c->block_size == 0x1000) || (c->block_size == 0x10000), "lfs_flash_block_erase only support 4K or 64K block_size!");
 
    /*printf("lfs_flash_erase=%d\r\n",block);*/
    if(c->block_size == 0x1000){
        norflash_ioctl(NULL, IOCTL_ERASE_SECTOR, (u32)c->context + block * c->block_size);
    }else if(c->block_size == 0x10000){
        norflash_ioctl(NULL, IOCTL_ERASE_BLOCK, (u32)c->context + block * c->block_size);
    }
    return 0;
}

测试验证代码

image

从SD卡根目录读取test.txt文件,写到little fs

    FILE* fp = fopen(CONFIG_ROOT_PATH"test.txt", "r");

    if(fp){
        if(test_buf){
            fread(test_buf, flen(fp), 1, fp);
            fclose(fp);

            FILE*fp_lfs = fopen("mnt/lfs/C/test.txt", "w+");
            if (fp_lfs) {
                printf("fopen succ\n");
                fwrite(test_buf, 80*1024, 1, fp_lfs);
                printf("[msg]>>>>>>>>>>> fwrite");
                fclose(fp_lfs);
                printf("[msg]>>>>>>>>>>> fclose");
            } else {
                printf("[msg]>>>>>>>>>>> open fail");
            }

        }

    }else{
        printf("[chili]: %s %d\n",__func__, __LINE__);
    }

Windows电脑端查看lfs文件方式

10.6. LittleFs — JL Project Documentation
LittleFS Explorer软件查看lfs的文件.otl

常见问题

littlefs挂载失败

可能未注册相关littlefs操作回调函数到底层
image

image

无法用fdelete接口删除文件

需要用lfs_remove去删除

                //以删除mnt/lfs/C/eye.avi为例子
                struct lfs_info info;
                int res = lfs_stat(lfs_h, "/eye.avi", &info);//lfs_接口不需要mnt/lfs/C
                printf("[chili] %s res:%d\n", __func__, res);
                if (res == LFS_ERR_OK) {// 文件存在
                    int remove_err = lfs_remove(lfs_h, "/eye.avi");////lfs_接口不需要mnt/lfs/C
                    if(remove_err){
                        printf("[chili] %s lfs_remove %d\n", __func__, remove_err);
                    }else{
                        printf("[chili] %s lfs_remove %d\n", __func__, remove_err);
                    }
                }   

video_dec_server无法解码littlefs的AVI视频

底层video_dec_server服务会向littlefs进行fgetname操作,littlefs默认没有实现fgetname接口导致解码失败返回错误码-22。

解决:
实现littlefs的fgetname接口即可。
1、如下接口替换原本sdk的__lfs_fget_name函数接口:

static char file_path[128]={0};//供外部修改
static int __lfs_fget_name(FILE *_file, u8 *name, int len)
{
    printf("\n [lfs_msg] %s -note %d\n", __FUNCTION__, __LINE__);
    strcpy(name, file_path);
    printf("[chili] name:%s %d\n", name, __LINE__);
    return strlen(name);
}

void chili_set_dec_path(char*name)
{
    printf("[chili] %s %d\n", __func__, __LINE__);
    char path[128] = {0};
    strcpy(path, name);// 注意:strtok会修改原字符串,需用可修改的数组
    char *token;
    char *filename = NULL;

    // 第一次调用strtok,传入原始字符串和分隔符'/'
    token = strtok(path, "/");
    
    // 循环获取所有分割后的子串,最后一个即为文件名
    while (token != NULL) {
        filename = token;  // 不断更新filename为当前子串
        token = strtok(NULL, "/");  // 后续调用传入NULL
    }

    if (filename != NULL) {
        printf("提取的文件名: %s\n", filename);  // 输出:eye.avi
        strcpy(file_path, filename);
    } else {
        printf("路径无效,未找到文件名!\n");
    }
    printf("[chili] %s %d\n", __func__, __LINE__);
}

2、以logo_show函数的video_dec_server解码服务为例子,解码视频路径应当提前通过chili_set_dec_path函数传递给littlefs:
image

必现Corrupted dir pair异常

littlefs\lfs.c:1275:error: Corrupted dir pair at {0x0, 0x1}

以实际使用情况为准,正确配置extflash长度:
image

如果还不行,请lfs_format一下再lfs_mount重新挂载lfs

    if (lfs_mount(&lfs, &cfg)) {
        // reformat if we can't mount the filesystem
        // this should only happen on the first boot
        lfs_format(&lfs, &cfg);
        if (lfs_mount(&lfs, &cfg)) {
            puts("lfs_mount fail! \r\n");
            return NULL;
        }

    }

littlefs写速度优化

简介:写入1MB的测试文件到littlefs,耗时15s,大概70KB/s左右。
w25q512JV 64MB flash的擦除特性:
image

修改如下:
image

    // block device configuration
    .read_size = 4*1024,
    .prog_size = 4*1024,
    .block_size = 64 *1024,
    .block_count = 44444444,//block_size*block_count大于实际flash大小即可
    .cache_size = 4 * 1024,
    .block_cycles = 100000,

    cfg.context = (void *)((lfs_addr/(cfg.block_size) + 1) * cfg.block_size);//按照cfg.block_size进行块对齐

根据w25q512JV 64MB flash的擦除特性,按照64KB块擦除进行优化,优化后写速度大概140KB/S。
其他型号flash请实际以flash用户手册为准。

lfs会损坏其后面区域的数据

起始地址对齐的问题,需要更新修改lfs_dev_mount函数,代码如下:



lfs_t *lfs_dev_mount(void)
{
    printf("lfs_dev_mount start...\n");
    u32 raw_lfs_addr, lfs_space;
    
    FILE *profile_fp = fopen("mnt/sdfile/EXT_RESERVED/extflash", "r");
    if (!profile_fp) {
        puts("Failed to open extflash config!\r\n");
        return NULL;
    }
    
    struct vfs_attr file_attr;
    fget_attrs(profile_fp, &file_attr);
    raw_lfs_addr = sdfile_cpu_addr2flash_addr(file_attr.sclust);
    lfs_space = file_attr.fsize;
    fclose(profile_fp);
    
    printf("Raw LFS region: 0x%08x, size=0x%x (%u KB)\n",
           raw_lfs_addr, lfs_space, lfs_space / 1024);

    // === Step 1: 对齐起始地址 ===
    u32 block_size = cfg.block_size;
    u32 aligned_start = (raw_lfs_addr + block_size - 1) & ~(block_size - 1);
    printf("Aligned LFS start address: 0x%08x\n", aligned_start);
    // === Step 2: 检查是否还有足够空间 ===
    if (aligned_start - raw_lfs_addr >= lfs_space) {
        printf("ERROR: Not enough space after alignment!\n");
        return NULL;
    }
    
    u32 usable_space = lfs_space - (aligned_start - raw_lfs_addr);
    u32 block_count = usable_space / block_size;
    
    if (block_count == 0) {
        printf("ERROR: No complete block available after alignment!\n");
        return NULL;
    } 
  
    // === Step 3: 配置 LFS ===
    cfg.context = (void*)aligned_start;
    cfg.block_count = block_count;
    cfg.lookahead_size = ((block_count + 31) / 32) * 4; // 保证 4-byte 对齐

    printf("Aligned LFS: start=0x%08x, blocks=%u, total=%u KB\n",
           aligned_start, block_count, (block_count * block_size) / 1024);

    // === Mount or format ===
    int err = lfs_mount(&lfs, &cfg);
    if (err) {
        printf("Mount failed (%d), formatting...\n", err);
        if (lfs_format(&lfs, &cfg) || lfs_mount(&lfs, &cfg)) {
            printf("Format or remount failed!\n");
            return NULL;
        }
    }

    return &lfs;
}



读取文件失败

设定的块大小未对应使用相应的底层擦除指令,出现擦除异常。修改如下:
image

本文档包含以下子页面

  • LittleFS Explorer软件查看lfs的文件
Prev
AC792N开发-入门到进阶开发指导文档(完善ing)
Next
792N系列 U盘单备份升级说明