返回造物工坊

工具

LittleFS Shell

通过 WS63 UART0 提供类 Linux 的 LittleFS 命令行,支持 21+ 文件系统命令,可实时操作文件和目录。

海海星社区Apache-2.0

项目介绍

概述

本示例提供一个通过WS63 UART0 的命令行交互界面来操作 LittleFS 文件系统。类似于 Linux Shell,支持 21+ 个文件系统命令,可以实时操作文件和目录。

食用方法1.

如果不想自己操作这么多步骤,可以从GitCode上拉取我修改好的SDK。

GitCode仓库链接:https://gitcode.com/hinearlink/fbb_ws63

食用方法2.

你可以更直接,下载我编译好的固件直接烧录使用。

站内固件链接:https://hinearlink.com/firmware/littlefs-shell

食用方法3.

  • 将little_lfs.patch复制到fbb_ws63根目录,执行git apply little_lfs.patch
  • 把littlefs_test和littlefs_shell两个sample复制到fbb_ws63\src\application\samples\peripheral
  • 编译、烧录

食用方法4.

按照下方【SDK 配置说明】自己动手操作。

项目结构

littlefs_shell/
├── inc/                          # 头文件目录
│   ├── shell_uart.h             # UART 接口定义
│   ├── shell_utils.h            # 工具函数定义
│   └── shell_commands.h         # 命令处理函数定义
├── src/                          # 源文件目录
│   ├── littlefs_shell_main.c    # 主程序入口
│   ├── shell_uart.c             # UART 通信实现
│   ├── shell_utils.c            # 工具函数实现
│   └── shell_commands.c         # 命令处理实现
├── CMakeLists.txt               # 编译配置
└── README.md                    # 本文档

模块说明:

  • shell_uart: 负责 UART 初始化、数据收发、命令缓冲管理
  • shell_utils: 提供路径处理、状态管理等工具函数
  • shell_commands: 实现所有文件系统命令的处理逻辑
  • littlefs_shell_main: 主任务循环,协调各模块工作

硬件连接

Shell 模式使用 UART0 进行命令交互:

信号GPIO功能
TXDS_MGPIO17发送数据
RXDS_MGPIO18接收数据

连接方式:

  • 使用 USB 转 TTL 串口模块连接到 UART0
  • 波特率:115200
  • 数据位:8
  • 停止位:1
  • 校验位:无

注意:UART0 与系统调试串口(UART2)是独立的,需要单独连接串口模块。


SDK 配置说明

步骤 0:复制 Demo 代码到 SDK

将 littlefs_shell 文件夹复制到 SDK 的 application/samples/peripheral/ 目录下:

application/samples/peripheral/
├── littlefs_shell/          <-- 复制到这里
│   ├── inc/
│   ├── src/
│   ├── CMakeLists.txt
│   ├── Kconfig
│   └── README.md
├── gpio/
├── i2c/
├── ...

注意:确保 littlefs_shell 文件夹包含以下文件:

  • CMakeLists.txt - 编译配置
  • Kconfig - menuconfig 配置选项
  • inc/ 目录 - 头文件
  • src/ 目录 - 源文件

步骤 1:添加案例配置文件

需要在 application/samples/peripheral/ 目录下的 Kconfig 和 CMakeLists.txt 中注册本 Demo。

1.1 修改 Kconfig

编辑 application/samples/peripheral/Kconfig,在文件末尾(最后一个 endif 之前)添加:

config SAMPLE_SUPPORT_LITTLEFS_SHELL
    bool
    prompt "Support LittleFS Shell (UART Command Line)."
    default n
    depends on ENABLE_PERIPHERAL_SAMPLE
    select MIDDLEWARE_SUPPORT_LFS
    help
        This option means support LittleFS Shell Demo.
        This demo provides a command-line interface via UART0 to operate LittleFS.
        Supports 21+ commands including ls, cat, write, rm, mkdir, etc.

1.2 修改 CMakeLists.txt

编辑 application/samples/peripheral/CMakeLists.txt,在 set(SOURCES "${SOURCES}" PARENT_SCOPE) 之前添加:

if(DEFINED CONFIG_SAMPLE_SUPPORT_LITTLEFS_SHELL)
    add_subdirectory_if_exist(littlefs_shell)
endif()

注意:文件末尾如有 set(PUBLIC_HEADER "${PUBLIC_HEADER}" PARENT_SCOPE) 则忽略,如果没有则添加。

步骤 2:扩展 LittleFS 适配层 API(重要!)

本 Shell Demo 使用了四个原生 SDK 未提供的文件系统函数,需要手动添加到 LittleFS 适配层。

需要添加的函数:

  • fs_adapt_dir_open - 打开目录
  • fs_adapt_dir_read - 读取目录条目
  • fs_adapt_dir_close - 关闭目录
  • fs_adapt_rename - 重命名/移动文件

2.1 修改头文件

编辑 middleware/chips/ws63/littlefs/littlefs_adapt.h,在 fs_adapt_mkdir 声明后添加:

int fs_adapt_mkdir(const char *path);

// ===== 新增目录操作和重命名函数 =====
int fs_adapt_dir_open(const char *path, void **dir_handle);

int fs_adapt_dir_read(void *dir_handle, char *name, int name_size, int *type);

int fs_adapt_dir_close(void *dir_handle);

int fs_adapt_rename(const char *oldpath, const char *newpath);
// ===== 新增结束 =====

void lfs_test(void);

2.2 修改源文件

编辑 middleware/chips/ws63/littlefs/littlefs_adapt.c,在文件最后一行 #endif 之前(即 #ifdef CONFIG_LFS_SUPPORT_POSIX ... #endif 块之前,也就是第 463行 )添加以下实现。

具体位置:找到 lfs_test(void) 函数,在其后面、#ifdef CONFIG_LFS_SUPPORT_POSIX 之前添加:

int fsync(int fd)
{
    return fs_adapt_sync(fd);
}

// ===== 新增目录操作函数 =====
int fs_adapt_dir_open(const char *path, void **dir_handle)
{
    if (path == NULL || dir_handle == NULL) {
        return -1;
    }
    
    lfs_dir_t *dir = (lfs_dir_t *)malloc(sizeof(lfs_dir_t));
    if (dir == NULL) {
        lfs_debug_print_error("dir malloc failed\r\n");
        return -1;
    }
    
    const char *name = path;
    if (name[0] == '/' && name[1] == 0) {
        name = lfs_root_path;
    } else if (name[0] == '/') {
        name++;
    }
    
    int ret = lfs_dir_open(&g_lfs, dir, name);
    if (ret < LFS_ERR_OK) {
        lfs_debug_print_error("lfs_dir_open failed, ret = %d, path = %s\r\n", ret, path);
        free(dir);
        return -1;
    }
    
    *dir_handle = dir;
    return 0;
}

int fs_adapt_dir_read(void *dir_handle, char *name, int name_size, int *type)
{
    if (dir_handle == NULL || name == NULL || type == NULL) {
        return -1;
    }
    
    struct lfs_info info;
    int ret = lfs_dir_read(&g_lfs, (lfs_dir_t *)dir_handle, &info);
    if (ret <= 0) {
        return ret;  // 0 = end of directory, <0 = error
    }
    
    // Copy name
    int len = strlen(info.name);
    if (len >= name_size) {
        len = name_size - 1;
    }
    strncpy_s(name, name_size, info.name, len);
    name[len] = '\0';
    
    // Set type: 1 = file, 2 = directory
    *type = (info.type == LFS_TYPE_DIR) ? 2 : 1;
    
    return 1;  // Success
}

int fs_adapt_dir_close(void *dir_handle)
{
    if (dir_handle == NULL) {
        return -1;
    }
    
    int ret = lfs_dir_close(&g_lfs, (lfs_dir_t *)dir_handle);
    free(dir_handle);
    
    if (ret < LFS_ERR_OK) {
        lfs_debug_print_error("lfs_dir_close failed, ret = %d\r\n", ret);
        return -1;
    }
    
    return 0;
}

int fs_adapt_rename(const char *oldpath, const char *newpath)
{
    if (oldpath == NULL || newpath == NULL) {
        return -1;
    }
    
    int ret = lfs_rename(&g_lfs, oldpath, newpath);
    if (ret < LFS_ERR_OK) {
        lfs_debug_print_error("lfs_rename failed, ret = %d\r\n", ret);
        return -1;
    }
    
    return 0;
}
// ===== 新增结束 =====

#endif

步骤 3:注册 LittleFS 组件到编译系统

编辑 build/config/target_config/ws63/config.py,在 ws63-liteos-app 的 ram_component 列表中添加:

'ram_component': [
    # ... 其他组件 ... 记得在"mqtt"后边加一个英文逗号','
    "little_fs",              # LittleFS 源码库
    "littlefs_adapt_ws63"     # LittleFS 适配层
],

步骤 4:关闭系统周期打印(推荐)

系统默认会周期性打印内存信息,会干扰 Shell 的视觉交互。建议注释掉 application/ws63/ws63_liteos_application/main.c 第 256-258 行:

// 注释以下三行以关闭周期性系统信息打印
//PRINT("[SYS INFO] mem: used:%u, free:%u; log: drop/all[%u/%u], at_recv %u.\r\n", status.uwTotalUsedSize,
//    status.uwTotalFreeSize, log_get_missed_messages_count(), log_get_all_messages_count(),
//    at_uart_get_rcv_cnt());

步骤 5:在 menuconfig 中启用 LittleFS 文件系统

使用 menuconfig 配置:

python build.py ws63-liteos-app menuconfig

配置路径:

Middleware Configuration
  └─> File System Configuration
      └─> [*] Support LITTLE_FS

说明:这一步启用 LittleFS 文件系统的核心功能,是运行本 Demo 的前提条件。

步骤 6:启用 Demo

使用 menuconfig 配置:

python build.py ws63-liteos-app menuconfig

配置路径:

Application Configuration
  └─> Peripheral Sample Configuration
      └─> [*] Support LittleFS Shell (UART Command Line).

步骤 7:编译

python build.py ws63-liteos-app

常见编译错误

错误:implicit declaration of function 'fs_adapt_dir_open'

error: implicit declaration of function 'fs_adapt_dir_open'; did you mean 'fs_adapt_open'?
error: implicit declaration of function 'fs_adapt_dir_close'; did you mean 'fs_adapt_close'?
error: implicit declaration of function 'fs_adapt_dir_read'; did you mean 'fs_adapt_read'?
error: implicit declaration of function 'fs_adapt_rename'; did you mean 'fs_adapt_read'?

原因:纯净 SDK 的 LittleFS 适配层不包含目录遍历和重命名函数。

解决方法:按照上述「步骤 2:扩展 LittleFS 适配层 API」添加四个函数的声明和实现。


可用命令(共 21 个)

文件系统管理

命令说明示例
mount挂载文件系统mount
unmount卸载文件系统unmount
df显示文件系统信息df

导航命令

命令说明示例
pwd显示当前工作目录pwd
cd <dir>切换目录cd /data
ls [path]列出目录内容ls 或 ls /data
tree [path]递归显示目录树tree 或 tree /

文件操作

命令说明示例
cat <file>查看文件内容cat /test.txt
hexdump <file>十六进制查看文件hexdump /data.bin
write <file> <data>写入文件(覆盖)write /test.txt Hello
append <file> <data>追加数据到文件append /test.txt World
touch <file>创建空文件touch /empty.txt
cp <src> <dst>复制文件cp /a.txt /b.txt
mv <src> <dst>移动/重命名文件mv /old.txt /new.txt
rm <file>删除文件rm /test.txt
rm -r <dir>递归删除目录及内容rm -r /data
rm *删除当前目录所有文件rm *

目录操作

命令说明示例
mkdir <dir>创建目录mkdir /mydir
rmdir <dir>删除空目录rmdir /mydir

信息查询

命令说明示例
stat <file>查看文件信息stat /test.txt

实用工具

命令说明示例
echo <text>回显文本echo Hello World
clear清屏clear
help显示帮助信息help

使用示例

基础操作示例

========================================
  LittleFS Shell for WS63
========================================
Type 'help' for available commands
lfs> mount
Mounting LittleFS...
LittleFS mounted successfully

lfs> pwd
/

lfs> mkdir /data
Directory created

lfs> cd /data
Changed to /data

lfs> pwd
/data

lfs> write file.txt Hello LittleFS!
Write successful

lfs> cat file.txt
File content:
Hello LittleFS!

lfs> stat file.txt
File: file.txt
Size: 15 bytes

lfs> ls
Directory: /data
  [FILE] file.txt

lfs> cd /
Changed to /

lfs> tree
Tree: /
[DIR]  data
  [FILE] file.txt

高级操作示例

lfs> write /test.txt Line1
Write successful

lfs> append /test.txt Line2
Append successful

lfs> cat /test.txt
File content:
Line1Line2

lfs> cp /test.txt /backup.txt
Copied 10 bytes

lfs> mv /backup.txt /test_backup.txt
File moved/renamed

lfs> ls /
Directory: /
  [DIR]  data
  [FILE] test.txt
  [FILE] test_backup.txt

lfs> hexdump /test.txt
00000000: 4c 69 6e 65 31 4c 69 6e  65 32                   |Line1Line2|

lfs> rm /test.txt
File deleted

lfs> rm /data/file.txt
File deleted

lfs> rmdir /data
Directory removed

lfs> echo Test message
Test message

lfs> clear
(清屏)

lfs> unmount
Unmounting LittleFS...
LittleFS unmounted

删除操作说明

rm 命令支持三种用法:

  1. 删除单个文件:rm <file>

    • 示例:rm /test.txt
    • 只能删除文件,不能删除目录
  2. 递归删除目录:rm -r <dir>

    • 示例:rm -r /data
    • 删除目录及其所有内容(包括子目录和文件)
    • 谨慎使用,无法恢复
  3. 删除当前目录所有文件:rm *

    • 示例:rm *
    • 只删除当前目录下的文件,不删除子目录
    • 不会删除 . 和 ..
    • 显示删除的文件数量

Shell 模式特点

  1. 完整的文件系统操作:支持 21 个常用命令,覆盖所有基本文件操作
  2. 目录导航:支持 cd、pwd,可以像 Linux Shell 一样操作
  3. 相对路径和绝对路径:智能路径处理,支持两种路径格式
  4. 目录树显示:tree 命令递归显示完整目录结构
  5. 十六进制查看:hexdump 命令查看二进制文件内容
  6. 文件复制和移动:cp 和 mv 命令支持文件管理
  7. 交互式操作:通过串口终端手动输入命令
  8. 实时反馈:每个操作都有即时的成功/失败提示
  9. 灵活测试:可以自由组合各种文件操作
  10. 调试友好:方便验证文件系统功能和排查问题

注意事项

  1. 必须先挂载:使用文件操作命令前必须先执行 mount

  2. 关闭系统周期打印(推荐):系统默认会周期性打印内存信息,会干扰 Shell 交互。建议注释掉 application/ws63/ws63_liteos_application/main.c 第 256-258 行:

    // 注释以下三行以关闭周期性系统信息打印
    //PRINT("[SYS INFO] mem: used:%u, free:%u; log: drop/all[%u/%u], at_recv %u.\r\n", status.uwTotalUsedSize,
    //    status.uwTotalFreeSize, log_get_missed_messages_count(), log_get_all_messages_count(),
    //    at_uart_get_rcv_cnt());
    
  3. 路径格式:

    • 绝对路径:以 / 开头,如 /test.txt
    • 相对路径:相对于当前目录,如 file.txt 或 subdir/file.txt
  4. 当前目录:使用 cd 切换目录后,相对路径基于当前目录

  5. 数据限制:单次写入数据不超过 512 字节

  6. 命令长度:命令总长度不超过 128 字符

  7. 退格支持:支持使用退格键(Backspace)修改输入

  8. 目录删除:

    • rmdir 只能删除空目录
    • rm -r 可以递归删除非空目录
    • rm * 只删除文件,不删除目录
  9. 清屏功能:clear 命令需要终端支持 VT100 控制码

  10. 删除操作不可恢复:删除的文件无法恢复,请谨慎操作


相关文档


作者: GaoXiaolong

邮箱: gaoxiaolon@gmail.com

日期: 2025.12.12

评论

0 条评论

还没有评论,来说两句。