Files
2026-08-13 16:50:52 +08:00

290 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Shell 组件
## 简介
LISA Shell 是一个基于 [Letter Shell](https://github.com/NevermindZZT/letter-shell) 的命令行交互组件,为 ARCS SDK 提供串口命令行界面支持。通过 UART 接口,用户可以在终端中执行自定义命令、查看系统信息、调试应用程序等。
## 主要特性
- **UART 串口通信**:基于 lisa_uart 驱动实现串口收发
- **FreeRTOS 任务集成**:独立的 shell 任务处理用户输入
- **灵活配置**:通过 Kconfig 配置任务优先级、缓冲区大小等参数
- **日志集成**:自动接管系统日志输出到串口
- **命令扩展**:支持使用 `SHELL_EXPORT_CMD` 宏注册自定义命令
- **多种回车模式**:支持 LF、CR、CRLF 等多种命令行回车触发方式
## 组件架构
```
┌─────────────────────────────────────────┐
│ 用户应用程序 │
│ ┌──────────────────────────────────┐ │
│ │ SHELL_EXPORT_CMD 宏注册命令 │ │
│ └──────────────────────────────────┘ │
└─────────────┬───────────────────────────┘
┌─────────────▼───────────────────────────┐
│ LISA Shell 组件 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ shell_task │ │ shell_write │ │
│ │ (接收处理) │ │ (输出函数) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ┌──────▼─────────────────▼───────┐ │
│ │ Letter Shell 核心库 │ │
│ │ (命令解析、命令管理、TAB补全) │ │
│ └──────────────────────────────┬─┘ │
└─────────────────────────────────┼──────┘
┌─────────────────────────────────▼──────┐
│ lisa_uart 驱动 │
│ (UART 接收/发送、缓冲区管理) │
└────────────────────────────────────────┘
```
## 配置选项
`menuconfig``prj.conf` 中可配置以下选项:
### 基本配置
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `CONFIG_LISA_SHELL` | 启用 LISA Shell 组件 | n |
### 任务配置
| 配置项 | 说明 | 默认值 | 范围 |
|--------|------|--------|------|
| `CONFIG_LISA_SHELL_TASK_STACK_SIZE` | Shell 任务栈大小 (字节) | 1024 | - |
| `CONFIG_LISA_SHELL_TASK_PRIORITY` | Shell 任务优先级 | 5 | 0-31 |
### 缓冲区配置
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `CONFIG_LISA_SHELL_BUFFER_SIZE` | Shell 命令缓冲区大小 (字节) | 512 |
| `CONFIG_LISA_SHELL_RX_BUF_SIZE` | UART 接收缓冲区大小 (字节) | 32 |
| `CONFIG_LISA_SHELL_SCAN_BUFFER` | 格式化输入缓冲区大小 (字节) | 128 |
### 行为配置
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `CONFIG_LISA_SHELL_SUPPORT_END_LINE` | 支持尾行模式 | y |
| `CONFIG_LISA_SHELL_ENTER_LF` | 使用 LF (`\n`) 作为回车触发 | y |
| `CONFIG_LISA_SHELL_ENTER_CR` | 使用 CR (`\r`) 作为回车触发 | y |
| `CONFIG_LISA_SHELL_ENTER_CRLF` | 使用 CRLF (`\r\n`) 作为回车触发 | n |
> **注意**`SHELL_ENTER_CRLF` 不能与 `SHELL_ENTER_LF` 或 `SHELL_ENTER_CR` 同时启用。
## 快速开始
### 1. 启用组件
在项目的 `prj.conf` 文件中添加:
```c
CONFIG_LISA_SHELL=y
```
### 2. 配置 UART 设备
LISA Shell 使用系统日志 UART 设备,需要配置对应的 UART
```c
# 选择 UART0 作为 Shell 串口
CONFIG_SYSLOG_UART_DEVICE_UART0=y
```
### 3. 初始化 Shell
在应用程序的 `main` 函数中调用初始化函数:
```c
#include "lisa_shell.h"
int main(int argc, char **argv)
{
// 初始化 shell
lisa_shell_init();
// 你的应用代码
while (1) {
vTaskDelay(1000);
}
return 0;
}
```
### 4. 注册自定义命令
使用 `SHELL_EXPORT_CMD` 宏注册命令:
```c
#include "shell.h"
// 简单命令示例
static int cmd_hello(int argc, char **argv)
{
printf("Hello World\n");
return 0;
}
// 带参数的命令示例
static int cmd_echo(int argc, char **argv)
{
if (argc < 1) {
printf("Usage: echo <message>\n");
return -1;
}
for (int i = 0; i < argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
// 注册命令
SHELL_EXPORT_CMD(
SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
hello,
cmd_hello,
"Print hello world"
);
SHELL_EXPORT_CMD(
SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
echo,
cmd_echo,
"Echo arguments"
);
```
### 5. 命令组示例
创建命令组来组织相关的命令:
```c
// 命令表
struct cmd_entry {
char *name;
int (*exec)(int argc, char **argv);
char *help;
};
static int subcmd_test(int argc, char **argv)
{
printf("Running test...\n");
return 0;
}
static int subcmd_info(int argc, char **argv)
{
printf("System information\n");
return 0;
}
static const struct cmd_entry my_cmds[] = {
{"test", subcmd_test, "Run test"},
{"info", subcmd_info, "Show info"},
};
// 命令组处理函数
static int cmd_group_handler(int argc, char **argv)
{
if (argc == 1) {
// 显示帮助
printf("Available subcommands:\n");
for (int i = 0; i < sizeof(my_cmds) / sizeof(my_cmds[0]); i++) {
printf(" %-10s : %s\n", my_cmds[i].name, my_cmds[i].help);
}
return 0;
}
// 查找并执行子命令
for (int i = 0; i < sizeof(my_cmds) / sizeof(my_cmds[0]); i++) {
if (strcmp(my_cmds[i].name, argv[1]) == 0) {
return my_cmds[i].exec(argc - 2, argv + 2);
}
}
printf("Unknown subcommand: %s\n", argv[1]);
return -1;
}
// 注册命令组
SHELL_EXPORT_CMD(
SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_DISABLE_RETURN,
myapp,
cmd_group_handler,
"My application command group"
);
```
## API 参考
### lisa_shell_init
```c
int lisa_shell_init(void);
```
**功能**:初始化 LISA Shell 组件
**返回值**
- `0`:初始化成功
- `-1`初始化失败UART 设备未就绪、配置失败或内存分配失败)
**说明**
- 自动配置 UART 设备(波特率、缓冲区等)
- 创建 shell 任务进行命令接收和处理
- 将系统日志输出重定向到 shell 串口
## 注意事项
1. **UART 设备共享**Shell 使用系统日志的 UART 设备,确保日志和 Shell 配置一致
2. **任务优先级**:根据系统需求调整 Shell 任务优先级,避免影响实时性要求高的任务
3. **缓冲区大小**:根据命令复杂度和长度调整 `SHELL_BUFFER_SIZE`
4. **内存分配**Shell 使用动态内存分配,确保系统有足够的堆内存
5. **命令注册**`SHELL_EXPORT_CMD` 宏必须在全局作用域使用,不能在函数内部
6. **格式化输入**`SHELL_SCAN_BUFFER` 功能会阻塞 shell 任务,仅适用于 RTOS 环境
## 常见问题
**Q: Shell 初始化失败怎么办?**
A: 检查以下几点:
- UART 设备是否正确配置并初始化
- 系统是否有足够的堆内存
- `CONFIG_SYSLOG_UART_DEVICE_UARTx` 配置是否正确
**Q: 无法输入命令?**
A: 检查:
- 串口终端配置(波特率、数据位等)是否正确
- UART 引脚连接是否正常
- 回车触发模式LF/CR/CRLF配置是否与终端匹配
**Q: 命令注册后在 help 中看不到?**
A: 确保:
- 命令正确使用了 `SHELL_EXPORT_CMD`
- 宏调用在全局作用域(不在函数内部)
- 对应的源文件已链接到最终二进制文件
## 依赖项
- `SDK_MODULE_LETTER_SHELL`Letter Shell 核心库
- `LISA_PORTING`LISA 平台移植层
- `lisa_uart`UART 驱动
- `lisa_log`:日志系统
- `lisa_mem`:内存管理
- `FreeRTOS`:实时操作系统