news 2026/1/12 14:48:45

基于AS32X601使用shell命令行终端详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于AS32X601使用shell命令行终端详解

一、引言

Letter shell是一个C语言编写的,可以嵌入在程序中的嵌入式shell,主要面向嵌入式设备。简单来说是一个命令行交互软件,可以读取用户输入的命令,找到并执行命令对应的函数。本文基于国科安芯AS32A601开发板,实现轻量化的shell。

二、文件概述

本项目集成了一个轻量级串口命令行 Shell,支持通过 USART0 与主机交互,以 printf 为统一输出通道。

-Shell 提供基础命令( help 、 ver 、 echo 、 led ),可按需扩展到 ADC、SPI 等外设。

目录与文件

shell.h :Shell 对外 API 与类型。

shell.c :Shell 核心实现(输入缓冲、命令解析、调度)。

shell_cmds.c :示例命令注册与实现。

print.c :将 printf 输出重定向到 USART0 。

main.c :Shell 初始化与主循环集成。

serial_cli.ps1 :Windows 交互脚本,便捷串口调试。

2.1shell.c

#include "shell.h"

#include <string.h>

#include <stdio.h>

#include <stdarg.h>

/* RX ring buffer */

staticvolatileuint8_t rx_buf[256];

staticvolatileuint16_t rx_head = 0; /* write index */

staticvolatileuint16_t rx_tail = 0; /* read index */

/* Line buffer */

staticcharline_buf[SHELL_MAX_LINE];

staticuint16_t line_len = 0;

/* Command registry */

staticconstShellCmd *cmd_table[8];

staticintcmd_table_count[8];

staticinttable_used = 0;

voidshell_init(void(*writer)(constchar*buf,intlen)) {

rx_head = rx_tail = 0;

line_len = 0;

table_used = 0;

(void)writer; /* output uses printf directly */

}

voidshell_register(constShellCmd *cmds,intcount) {

__asmvolatile("fence.i");

if(!cmds || count <= 0)return;

if(table_used < (int)(sizeof(cmd_table)/sizeof(cmd_table[0]))) {

cmd_table[table_used] = cmds;

cmd_table_count[table_used] = count;

table_used++;

}

}

voidshell_input_byte(uint8_t b) {

uint16_t next = (uint16_t)((rx_head + 1) & 0xFF);

if(next == rx_tail) {

/* overflow, drop byte */

return;

}

rx_buf[rx_head] = b;

rx_head = next;

}

staticinttokenize(char*line,char**argv,intmax_args) {

intargc = 0;

char*p = line;

while(*p && argc < max_args) {

while(*p == ' ' || *p == '\t') p++;

if(!*p)break;

argv[argc++] = p;

while(*p && *p != ' ' && *p != '\t') p++;

if(!*p)break;

*p++ = '\0';

}

returnargc;

}

staticvoidprint_prompt(void) {

printf("\r\n> ");

}

staticintdispatch(intargc,char**argv) {

if(argc <= 0)return0;

constchar*name = argv[0];

__asmvolatile("fence.i");

if(strcmp(name, "help") == 0) {

printf("Commands:\r\n");

for(intt = 0; t < table_used; ++t) {

for(inti = 0; i < cmd_table_count[t]; ++i) {

constShellCmd *c = &cmd_table[t][i];

printf(" %s - %s\r\n", c->name, c->desc ? c->desc : "");

__asmvolatile("fence.i");

}

}

return0;

}

for(intt = 0; t < table_used; ++t) {

for(inti = 0; i < cmd_table_count[t]; ++i) {

constShellCmd *c = &cmd_table[t][i];

if(strcmp(name, c->name) == 0) {

returnc->handler(argc, argv);

}

}

}

printf("Unknown command: %s\r\n", name);

return-1;

}

voidshell_poll(void) {

/* Read bytes from ring and build lines */

while(rx_tail != rx_head) {

uint8_t b = rx_buf[rx_tail];

rx_tail = (uint16_t)((rx_tail + 1) & 0xFF);

if(b == '\r') {

/* ignore CR */

continue;

}

if(b == '\n') {

/* complete line */

line_buf[line_len] = '\0';

char*argv[SHELL_MAX_ARGS];

intargc = tokenize(line_buf, argv, SHELL_MAX_ARGS);

if(argc > 0) {

(void)dispatch(argc, argv);

}

line_len = 0;

print_prompt();

continue;

}

if(b == '\b' || b == 0x7F) {

/* backspace */

if(line_len > 0) line_len--;

continue;

}

if(line_len < SHELL_MAX_LINE - 1) {

line_buf[line_len++] = (char)b;

}else{

/* truncate on overflow */

}

}

}

主要函数分析

1.初始化函数

void shell_init(void (*writer)(const char *buf, int len));

  • 初始化缓冲区指针

  • writer 参数当前未使用(直接使用 printf)

2.命令注册函数

void shell_register(const ShellCmd *cmds, int count);

  • 注册一组命令

  • fence.i 指令:RISC-V 内存屏障,确保指令缓存一致性

3.字节输入处理

void shell_input_byte(uint8_t b);

  • 从串口接收单个字节

  • 存入环形缓冲区

  • 处理缓冲区溢出(丢弃字节)

4.主轮询函数

void shell_poll(void);

核心处理逻辑

  • 从环形缓冲区读取字节

  • 处理特殊字符:

  • 普通字符存入行缓冲区

  • 行完成后,分词并调度执行

5.分词函数

static int tokenize(char *line, char **argv, int max_args);

  • 空格/制表符分割命令行

  • 支持最大 SHELL_MAX_ARGS 个参数

  • 原地修改字符串(添加 \0 终止符)

6.命令分发

static int dispatch(int argc, char **argv);

  • 内置 help 命令:显示所有注册命令

  • 遍历所有命令表查找匹配命令

  • 调用对应的 handler 函数

2.2shell_cmds.c

用户可在该文件中定义函数,并注册到命令列表中

#include "shell.h"

#include "led.h"

#include <string.h>

#include <stdio.h>

staticintcmd_ver(intargc,char**argv) {

(void)argc; (void)argv;

printf("AS32X601 usart_eflash shell v0.1\r\n");

return0;

}

staticintcmd_echo(intargc,char**argv) {

for(inti = 1; i < argc; ++i) {

printf("%s%s", argv[i], (i == argc - 1) ? "" : " ");

}

printf("\r\n");

return0;

}

staticintcmd_led(intargc,char**argv) {

if(argc < 3) {

printf("Usage: led <on|off|toggle> <1|2|3>\r\n");

return-1;

}

intidx = argv[2][0] - '0';

if(idx < 1 || idx > 3) {

printf("Invalid LED index: %s\r\n", argv[2]);

return-1;

}

inttoggle = (strcmp(argv[1], "toggle") == 0);

inton = (strcmp(argv[1], "on") == 0);

intoff = (strcmp(argv[1], "off") == 0);

if(!(toggle || on || off)) {

printf("Invalid action: %s\r\n", argv[1]);

return-1;

}

switch(idx) {

case1:

if(toggle) LED1_TOGGLE();elseif(on) LED1_ON();elseif(off) LED1_OFF();

break;

case2:

if(toggle) LED2_TOGGLE();elseif(on) LED2_ON();elseif(off) LED2_OFF();

break;

case3:

if(toggle) LED3_TOGGLE();elseif(on) LED3_ON();elseif(off) LED3_OFF();

break;

default:

break;

}

printf("led %s %d\r\n", argv[1], idx);

return0;

}

staticconstShellCmd default_cmds[] = {

{"ver", "Show shell version", cmd_ver},

{"echo", "Echo back arguments", cmd_echo},

{"led", "Control LEDs: led <on|off|toggle> <1|2|3>", cmd_led},

};

voidshell_cmds_init(void) {

shell_register(default_cmds, (int)(sizeof(default_cmds)/sizeof(default_cmds[0])));

}

voidshell_info()

{

printf("\r\n");

printf("\r\n");

printf (" _ _ _ _ _ _ \r\n");

printf( "| | ___| |_| |_ ___ _ __ ___| |__ ___| | |\r\n");

printf("| | / _ \\ __| __/ _ \\ '__| / __| '_ \\ / _ \\ | |\r\n");

printf("| |__| __/ |_| || __/ | \\__ \\ | | | __/ | |\r\n");

printf("|_____\\___|\\__|\\__\\___|_| |___/_| |_|\\___|_|_|\r\n");

printf ("\r\n");

printf("\r\n");

printf("Version: 0.1\n");

printf("Board: AS32X601\n");

printf("Build: " __DATE__ " " __TIME__ "\n");

printf("\n");

}

  1. 版本信息命令

static int cmd_ver(int argc, char **argv)

  • 显示固件版本信息

2.回显命令

static int cmd_echo(int argc, char **argv)

  • 打印所有参数(argv[0] 是命令名本身)

  • 正确处理参数间的空格

3.LED控制命令

static int cmd_led(int argc, char **argv)

  • 完整的参数验证:参数数量、范围、合法性

  • 清晰的错误提示

  • 执行反馈:操作成功后打印确认信息

4.命令表定义

static const ShellCmd default_cmds

  • 结构清晰:命令名、描述、处理函数

  • 包含使用示例(led命令)

5.初始化函数

void shell_cmds_init(void)

  • 自动计算命令数量,避免硬编码

  • 提供清晰的模块初始化接口

2.3 main.c部分流程

shell_init(NULL);

shell_cmds_init();

shell_info();

printf("AS32X601 shell ready\r\nType 'help' to list commands.\r\n> ");

while(1)

{

if(SET == USART_GetFlagStatus(USART0, USART_FLAG_RXFNE))

{

usart_data = USART_ReceiveData(USART0);

ClearCache();

/* feed incoming byte to shell */

shell_input_byte(usart_data);

}

/* process any pending input and run commands */

shell_poll();

}

输入路径:串口接收中断或轮询将字节喂给 shell_input_byte ,Shell维护环形缓冲与状态机。

解析执行:按行解析命令,匹配已注册的命令表或函数指针,执行对应处理例程。

主循环:周期性调用 shell_poll 以处理缓冲区中的数据与命令

三、开发板验证:

该项目实现通过串口分别控制led 1,2,3翻转和回显功能

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/26 15:53:40

【大模型平民化革命】:Open-AutoGLM本地部署可行性深度解析

第一章&#xff1a;Open-AutoGLM开源部署操作电脑可以吗 Open-AutoGLM 是一个基于 AutoGLM 架构的开源项目&#xff0c;旨在为本地化大模型推理与自动化任务提供轻量级部署方案。得益于其模块化设计和对消费级硬件的优化支持&#xff0c;用户完全可以在普通个人电脑上完成部署与…

作者头像 李华
网站建设 2026/1/7 12:55:43

Open-AutoGLM与云手机的关系大解析(99%的人都理解错了的技术细节)

第一章&#xff1a;Open-AutoGLM 操作的是云手机么Open-AutoGLM 并非直接操作传统意义上的“云手机”&#xff0c;而是一个基于自动化大语言模型&#xff08;AutoGLM&#xff09;的开源框架&#xff0c;旨在实现跨平台智能交互任务的编排与执行。其核心能力在于通过自然语言理解…

作者头像 李华
网站建设 2025/12/26 15:49:25

一篇文章讲透:网络安全为何关乎企业存亡与个人隐私

目录 一、什么是网络安全 二、网络安全为何重要&#xff1f; 1、数据安全 2、保护财务信息 3、遵守法律法规 4、防止网络攻击 三、网络安全常见问题隐患 1、弱密码 2、恶意软件 3、网络钓鱼 4、扫码领礼品 四、预防信息泄露普及 1、加强密码管理 2、保护个人信息…

作者头像 李华
网站建设 2026/1/12 9:53:53

【限时解密】:Open-AutoGLM Phone底层架构首次公开,3大技术黑箱震撼业界

第一章&#xff1a;Open-AutoGLM Phone底层架构首次解密Open-AutoGLM Phone作为首款集成自主大模型推理能力的移动终端设备&#xff0c;其底层架构融合了异构计算、边缘AI调度与安全隔离机制。该系统采用分层式设计&#xff0c;确保高性能推理与低功耗运行之间的平衡。核心模块…

作者头像 李华
网站建设 2025/12/26 15:46:58

【Java毕设源码分享】基于springboot+vue的企业客源关系管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华