2026/4/8 21:33:18
网站建设
项目流程
卖源码的网站,wordpress一键搭建脚本,建立微信商城网站,vs网页制作教程CherrySH 是一个专为嵌入式应用程序而设计的微型Shell#xff0c;今天我们就来一起看下。 地址#xff1a; https://github.com/cherry-embedded/CherrySH 1. CherrySH简介 项目信息详情项目名称CherrySH定位嵌入式交互式 Shell开发语言C许可证Apache-2.0 1.1 功能 支持 TAB …CherrySH 是一个专为嵌入式应用程序而设计的微型Shell今天我们就来一起看下。地址https://github.com/cherry-embedded/CherrySH1. CherrySH简介项目信息详情项目名称CherrySH定位嵌入式交互式 Shell开发语言C许可证Apache-2.01.1 功能支持 TAB 键补全包括命令和路径补全支持历史记录通过↑↓按键支持环境变量需使用$作为前缀例如$PATH支持设定用户名、主机名、路径支持非阻塞模式支持裸机和 RTOS支持光标左右移动支持HOME、END切换光标支持组合按键包括Ctrl \key\Alt \key\F1-F12 等支持信号处理捕获和处理不同的信号例如CtrlCSIGINT和CtrlZSIGTSTP可中断当前执行的 shell 任务支持用户登录需要实现hash函数默认strcmp支持环境变量添加、修改、删除、读出支持文件系统FatFSFileXLittleFSRomFS等TODO支持 exit 函数实现终止命令执行以及现场返回并调用设定的handler利用setjmp实现(裸机)TODO支持作业控制可以在前台或后台运行命令并使用相关的控制命令如fg、bg、jobs来管理和操作作业TODO支持多用户命令权限TODO一句话说清楚CherrySH 就是让你在 MCU 上敲命令还能有方向键、历史、TAB 补全这些体验而且不用 malloc。它怎么做到的两招命令注册编译时用宏把命令塞进链接器 section运行时直接遍历这块内存行编辑单独的 readline 模块处理键盘输入全静态 buffer2. 核心原理2.1 整体架构说明CherryReadLine负责怎么把一行字编辑好方向键、删除、历史、补全CherrySH负责拿到一行后怎么执行解析参数、查命令、调函数命令表编译时自动收集运行时直接遍历2.2 关键代码注册一个命令staticintmy_cmd(int argc, char **argv) { chry_shell_t *csh (void *)argv[argc 1]; csh_printf(csh, 嵌入式大杂烩 \r\n); return0; } CSH_CMD_EXPORT(my_cmd, );这个宏展开后会在FSymTab段里放一个结构体// csh.h 里的定义 typedefstruct { constchar *path; // 命令路径如 /bin constchar *name; // 命令名 constchar *usage; // 简短说明 constchar *help; // 详细帮助 int (*func)(int argc, char **argv); // 函数指针 } chry_syscall_t;链接器把所有这种结构体收集到一起形成一个命令表。运行时怎么找命令看chry_shell_task_repl()核心逻辑// 读一行 char *line chry_readline(csh-rl, buffer, size, linesize); // 解析成 argc/argv原地切割空格变 \0 argc chry_shell_parse(line, linesize, argv, MAX_ARG); // 遍历命令表找匹配 for (call csh-cmd_tbl_beg; call csh-cmd_tbl_end; call) { if (路径名字匹配) { call-func(argc, argv); // 找到就调用 break; } }用流程图表示2.3 目录结构CherrySH/ ├── chry_shell.c/h # Shell 核心解析、执行、用户管理 ├── csh.h # 配置 导出宏 ├── cherryrl/ # ReadLine 模块行编辑、历史、补全 ├── builtin/ # 内置命令示例help、clear 等 └── samples/ # 移植示例HPM、STM323. 移植步骤以先楫半导体hpm5301evklite为例。命令查找采用的是 gcc 的 section 功能因此我们需要先修改 linkerscript 文件增加相关 section,举例 gcc ld 文件.text : { ..... . ALIGN(4); __fsymtab_start .; KEEP(*(FSymTab)) __fsymtab_end .; . ALIGN(4); __vsymtab_start .; KEEP(*(VSymTab)) __vsymtab_end .; . ALIGN(4); }实现字符输入输出函数接收推荐用中断 ringbuf的形式#includecsh.h staticchry_shell_t csh; staticuint16_tcsh_sput_cb(chry_readline_t *rl, constvoid *data, uint16_t size) { uint16_t i; (void)rl; for (i 0; i size; i) { if (status_success ! uart_send_byte(HPM_UART0, ((uint8_t *)data)[i])) { break; } } return i; } staticuint16_tcsh_sget_cb(chry_readline_t *rl, void *data, uint16_t size) { uint16_t i; (void)rl; for (i 0; i size; i) { if (status_success ! uart_receive_byte(HPM_UART0, (uint8_t *)data i)) { break; } } return i; }初始化 shell参考 samples 中实现调用chry_shell_task_exec和chry_shell_task_repl参考 samples 中实现配置系统环境变量#define __ENV_PATH /sbin:/bin constchar ENV_PATH[] __ENV_PATH; CSH_RVAR_EXPORT(ENV_PATH, PATH, sizeof(__ENV_PATH)); #define __ENV_ZERO constchar ENV_ZERO[] __ENV_ZERO; CSH_RVAR_EXPORT(ENV_ZERO, ZERO, sizeof(__ENV_ZERO));使用CSH_CMD_EXPORT导出命令staticintwrite_led(int argc, char **argv) { if (argc 2) { printf(usage: write_led status\r\n\r\n); printf( status 0 or 1\r\n\r\n); return-1; } board_led_write(atoi(argv[1]) 0); return0; } CSH_CMD_EXPORT(write_led, );4. 总结4.1 CherrySH 优缺点优点readline 独立行编辑体验好方向键、Home/End、Ctrl 组合键都支持支持多线程执行模型长耗时命令可被 CtrlC 打断命令路径机制/bin、/sbin适合命令多的场景无堆内存资源占用可预测缺点必须改链接脚本对新手不友好history buffer 必须是 2 的幂容易踩坑文档较少主要靠看 samples 学习如果觉得文章有帮助麻烦帮忙转发谢谢------------END------------单片机可以用 Python 开发吗单片机SPI也能实现单线半双工模式从汇编的角度看MCU运行机制