chore: migrate project into clean repository

This commit is contained in:
yuuux
2026-08-13 16:50:52 +08:00
commit d1d25a09e7
27405 changed files with 9422808 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# LISA Shell
#
# Copyright (c) 2025, LISTENAI
# SPDX-License-Identifier: Apache-2.0
if(CONFIG_LISA_SHELL)
listenai_library_named(lisa_shell)
listenai_library_sources(
lisa_shell.c
)
listenai_include_directories(.)
endif() # CONFIG_LISA_SHELL

View File

@@ -0,0 +1,87 @@
# LISA Shell Configuration
#
# Copyright (c) 2025, LISTENAI
# SPDX-License-Identifier: Apache-2.0
menuconfig LISA_SHELL
bool "Enable LISA Shell"
default n
select SDK_MODULE_LETTER_SHELL
select LISA_PORTING
depends on SYSLOG_UART_BACKEND
help
Enable LISA Shell component for command line interface support.
if LISA_SHELL
config SDK_MODULE_LETTER_SHELL_CONFIG_FILE
string
default "shell_cfg_user.h"
config LISA_SHELL_TASK_STACK_SIZE
int "Shell task stack size"
default 1024
help
Stack size for the shell task in bytes.
config LISA_SHELL_TASK_PRIORITY
int "Shell task priority"
default 5
range 0 31
help
Priority for the shell task. Higher values mean higher priority.
Range: 0 (lowest) to configMAX_PRIORITIES-1 (highest).
config LISA_SHELL_BUFFER_SIZE
int "Shell command buffer size"
default 512
help
Size of the shell command buffer in bytes.
config LISA_SHELL_RX_BUF_SIZE
int "UART receive buffer size"
default 128
help
Size of the UART receive buffer for shell input in bytes.
config LISA_SHELL_SUPPORT_END_LINE
bool "Support shell end line mode"
default y
help
Enable shell end line mode support.
config LISA_SHELL_ENTER_LF
bool "Use LF as command line enter trigger"
default y
help
Use LF (Line Feed, '\n') as command line enter trigger.
Can be enabled together with SHELL_ENTER_CR.
config LISA_SHELL_ENTER_CR
bool "Use CR as command line enter trigger"
default y
help
Use CR (Carriage Return, '\r') as command line enter trigger.
Can be enabled together with SHELL_ENTER_LF.
config LISA_SHELL_ENTER_CRLF
bool "Use CRLF as command line enter trigger"
default n
help
Use CRLF ('\r\n') as command line enter trigger.
Cannot be enabled together with SHELL_ENTER_LF or SHELL_ENTER_CR.
config LISA_SHELL_SCAN_BUFFER
int "Shell formatted input buffer size"
default 128
help
Buffer size for shell formatted input. Set to 0 to disable.
Note: Formatted input will block shellTask, only suitable for RTOS.
config LISA_SHELL_CLS_WHEN_LOGIN
bool "Clear screen when logging in"
default n
help
Clear the screen when logging in.
endif # LISA_SHELL

View File

@@ -0,0 +1,289 @@
# 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`:实时操作系统

View File

@@ -0,0 +1,121 @@
/**
* @file lisa_shell.c
* @brief LISA Shell 组件实现
* @copyright Copyright (c) 2025, LISTENAI
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_TAG "lisa_shell"
#include <lisa_log.h>
#include <string.h>
#include <stdlib.h>
#include "shell.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lisa_device.h"
#include "lisa_uart.h"
#include "lisa_mem.h"
#define TAG "lisa_shell"
#include "lisa_log.h"
/* Shell实例和UART设备句柄 */
static Shell *g_shell;
static lisa_device_t *shell_dev;
/* UART接收缓冲区 */
static uint8_t rx_buffer[CONFIG_LISA_SHELL_RX_BUF_SIZE];
static signed short shell_write(char *data, unsigned short size)
{
for (size_t i = 0; i < size; i++) {
lisa_uart_poll_out(shell_dev, data[i]);
}
return size;
}
static signed short shell_read(char *data, unsigned short len)
{
int ret = lisa_uart_read_sync(shell_dev, (uint8_t *)data, len);
if(ret == LISA_DEVICE_ERR_OVERFLOW){
lisa_uart_rx_disable(shell_dev);
if (lisa_uart_rx_enable(shell_dev) == 0) {
LISA_LOGI(TAG, "Reception restarted");
} else {
LISA_LOGE(TAG, "Failed to restart reception");
}
}
return (ret > 0) ? ret : 0;
}
void log_shell_backend_output(const uint8_t *log, uint32_t len, void *data)
{
if (g_shell) {
shellWriteEndLine(g_shell, (uint8_t *)log, len);
}
}
int lisa_shell_init(void)
{
#if defined(CONFIG_SYSLOG_UART_DEVICE_UART0)
shell_dev = lisa_device_get("uart0");
#elif defined(CONFIG_SYSLOG_UART_DEVICE_UART1)
shell_dev = lisa_device_get("uart1");
#elif defined(CONFIG_SYSLOG_UART_DEVICE_UART2)
shell_dev = lisa_device_get("uart2");
#endif
if (!lisa_device_ready(shell_dev)) {
LISA_LOGE(LOG_TAG, "UART device not ready");
return -1;
}
lisa_uart_config_t config = LISA_UART_CONFIG_DEFAULT();
config.baudrate = CONFIG_SYSLOG_UART_BAUDRATE;
config.rx_buf_config.buffer_count = 2;
config.rx_buf_config.buffer_size = CONFIG_LISA_SHELL_RX_BUF_SIZE;
if (lisa_uart_configure(shell_dev, &config) != 0) {
LISA_LOGE(LOG_TAG, "Failed to configure UART");
return -1;
}
if (lisa_uart_rx_enable(shell_dev) != 0) {
LISA_LOGE(LOG_TAG, "Failed to enable UART RX");
return -1;
}
Shell *sh = lisa_mem_alloc(sizeof(Shell));
if (sh == NULL) {
LISA_LOGE(LOG_TAG, "Failed to allocate memory for Shell");
return -1;
}
memset(sh, 0, sizeof(Shell));
uint8_t *shell_buf = lisa_mem_alloc(CONFIG_LISA_SHELL_BUFFER_SIZE);
if (shell_buf == NULL) {
LISA_LOGE(LOG_TAG, "Failed to allocate shell buffer");
lisa_mem_free(sh);
return -1;
}
sh->write = shell_write;
sh->read = shell_read;
g_shell = sh;
shellInit(sh, (char *)shell_buf, CONFIG_LISA_SHELL_BUFFER_SIZE);
lisa_log_backend_pause("sys.log");
lisa_log_backend_add("user.shell", log_shell_backend_output, NULL);
xTaskCreate(shellTask, "shell",
CONFIG_LISA_SHELL_TASK_STACK_SIZE,
sh,
CONFIG_LISA_SHELL_TASK_PRIORITY,
NULL);
return 0;
}

View File

@@ -0,0 +1,32 @@
/**
* @file lisa_shell.h
* @brief LISA Shell 组件对外接口
* @copyright Copyright (c) 2025, LISTENAI
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __LISA_SHELL_H__
#define __LISA_SHELL_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 初始化LISA Shell
*
* 该函数初始化shell组件配置UART通信并创建shell任务。
* shell任务的堆栈大小和优先级可以通过Kconfig配置。
*
* @return int 初始化结果
* @retval 0 成功
* @retval -1 失败
*/
int lisa_shell_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __LISA_SHELL_H__ */

View File

@@ -0,0 +1,115 @@
/**
* @file shell_cfg_user.h
* @author Letter (nevermindzzt@gmail.com)
* @brief shell config
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_CFG_USER_H__
#define __SHELL_CFG_USER_H__
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#define SHELL_SHOW_INFO 1
#define SHELL_TASK_WHILE 1
/**
* @brief 是否使用shell伴生对象
* 一些扩展的组件(文件系统支持,日志工具等)需要使用伴生对象
*/
#define SHELL_USING_COMPANION 0
/**
* @brief 是否在登录后清除命令行
*/
#ifdef CONFIG_LISA_SHELL_CLS_WHEN_LOGIN
#define SHELL_CLS_WHEN_LOGIN 1
#else
#define SHELL_CLS_WHEN_LOGIN 0
#endif
/**
* @brief 支持shell尾行模式
*/
#ifdef CONFIG_LISA_SHELL_SUPPORT_END_LINE
#define SHELL_SUPPORT_END_LINE 1
#else
#define SHELL_SUPPORT_END_LINE 0
#endif
/**
* @brief 使用LF作为命令行回车触发
* 可以和SHELL_ENTER_CR同时开启
*/
#ifdef CONFIG_LISA_SHELL_ENTER_LF
#define SHELL_ENTER_LF 1
#else
#define SHELL_ENTER_LF 0
#endif
/**
* @brief 使用CR作为命令行回车触发
* 可以和SHELL_ENTER_LF同时开启
*/
#ifdef CONFIG_LISA_SHELL_ENTER_CR
#define SHELL_ENTER_CR 1
#else
#define SHELL_ENTER_CR 0
#endif
/**
* @brief 使用CRLF作为命令行回车触发
* 不可以和SHELL_ENTER_LF或SHELL_ENTER_CR同时开启
*/
#ifdef CONFIG_LISA_SHELL_ENTER_CRLF
#define SHELL_ENTER_CRLF 1
#else
#define SHELL_ENTER_CRLF 0
#endif
/**
* @brief shell格式化输入的缓冲大小
* 为0时不使用shell格式化输入
* @note shell格式化输入会阻塞shellTask, 仅适用于在有操作系统的情况下使用
*/
#ifdef CONFIG_LISA_SHELL_SCAN_BUFFER
#define SHELL_SCAN_BUFFER CONFIG_LISA_SHELL_SCAN_BUFFER
#else
#define SHELL_SCAN_BUFFER 0
#endif
/**
* @brief 获取系统时间(ms)
* 定义此宏为获取系统Tick如`HAL_GetTick()`
* @note 此宏不定义时无法使用双击tab补全命令help无法使用shell超时锁定
*/
#define SHELL_GET_TICK() xTaskGetTickCount()
/**
* @brief 使用锁
* @note 使用shell锁时需要对加锁和解锁进行实现
*/
#define SHELL_USING_LOCK 0
/**
* @brief shell内存分配
* shell本身不需要此接口若使用shell伴生对象需要进行定义
*/
#define SHELL_MALLOC(size) 0
/**
* @brief shell内存释放
* shell本身不需要此接口若使用shell伴生对象需要进行定义
*/
#define SHELL_FREE(obj) 0
#endif