概念先知道
- Shell(命令行):通过串口输入文本命令、回车执行、打印结果的人机交互界面,类似电脑的终端。嵌入式里常用于调试和配置。
- SHELL_CMD_EXPORT_ALIAS:把函数注册成命令的宏,
SHELL_CMD_EXPORT_ALIAS(shell_test, test, shell test.)表示输入test就调用shell_test()。 - shell_os vs shell_no_os:SDK 提供两个版本——
shell_os跑在 FreeRTOS 上(有独立 shell 任务,输入不阻塞业务),shell_no_os是裸机轮询版(在while(1)里手动调用shell_handler)。 - 命令入口:几乎所有无线例程(
wifi_sta_connect、mqtt_connect等)都是通过SHELL_CMD_EXPORT_ALIAS注册的命令,串口输入即触发。
例程功能简介
本页对应博流官方 SDK 的 shell_os 例程(examples/shell/shell_os),演示 FreeRTOS 版 Shell 的搭建:
- 初始化串口 0(
uart0)并调用shell_init_with_task(uart0)创建 shell 任务; - 启动 FreeRTOS 调度器(
vTaskStartScheduler),shell 任务开始监听串口输入; - 用
SHELL_CMD_EXPORT_ALIAS注册自定义命令test,输入后打印shell test; - 同族例程:
examples/shell/shell_no_os(裸机轮询版,无 FreeRTOS)。
提示
把自定义命令注册进 shell,是调试自己代码最快的方式:烧录后不用重新编译,直接串口输入命令就能触发函数。
操作步骤
在终端进入 SDK 的 Shell 例程目录(前提:已按快速开始(Linux)或Windows搭建好环境):
cd examples/shell/shell_os执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:
make CHIP=bl616 BOARD=bl616dk用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):
make flash CHIP=bl616 COMX=/dev/ttyUSB0打开串口助手(波特率 2000000),看到 bouffalolab /> 提示符后输入 help 查看命令列表(能看到本页注册的 test 命令),再输入 test 回车,串口打印 shell test。
代码执行流程
例程从启动到接收命令的流程如下:
例程调用的 API 介绍
shell_init_with_task(uart)
初始化 shell 并创建一个独立 shell 任务,由该任务读取串口输入、解析命令。输入命令时不影响其他任务运行。
参数:
uart:串口设备句柄(例程bflb_device_get_by_name("uart0"))
返回值:无
SHELL_CMD_EXPORT_ALIAS(func, cmd, help)
把函数注册为 shell 命令(编译期放入命令表)。输入命令名时自动调用 func(argc, argv)。
参数:
func:被调用的函数(签名int func(int argc, char **argv))cmd:命令名(如test)help:帮助文本,help命令会显示
返回值:无(宏)
完整代码
以下为 shell_os/main.c 完整源码,与官方示例一致,默认折叠,点击展开:
📜 点击展开 shell_os/main.c 完整代码
#include "bflb_mtimer.h"
#include "bflb_uart.h"
#include "shell.h"
#include <FreeRTOS.h>
#include "semphr.h"
#include "board.h"
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
int main(void)
{
board_init();
configASSERT((configMAX_PRIORITIES > 4));
uart0 = bflb_device_get_by_name("uart0");
shell_init_with_task(uart0);
vTaskStartScheduler();
while (1) {
}
}
int shell_test(int argc, char **argv)
{
printf("shell test\r\n");
return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_test, test, shell test.);📜 点击展开 shell_no_os/main.c 完整代码(裸机版)
#include "bflb_mtimer.h"
#include "bflb_uart.h"
#include "shell.h"
#include "board.h"
static struct bflb_device_s *uart0;
int main(void)
{
int ch;
board_init();
uart0 = bflb_device_get_by_name("uart0");
shell_init();
while (1) {
if((ch = bflb_uart_getchar(uart0)) != -1)
{
shell_handler(ch);
}
}
}
int shell_test(int argc, char **argv)
{
printf("shell test\r\n");
return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_test, test, shell test.);FAQ
输入命令后没有任何反应?
先确认串口波特率是 2000000 且回车符发送正常;再确认命令名与注册名一致(如 test)。若提示符都没出现,多半是固件没烧进去或串口选错。
shell_os 和 shell_no_os 有什么区别?
shell_os 基于 FreeRTOS,shell 是独立任务,适合带系统工程的调试;shell_no_os 不依赖 RTOS,在 while(1) 里轮询串口,适合裸机工程。功能上命令注册方式完全一样。
怎么查看当前固件支持哪些命令?
在 bouffalolab /> 提示符下输入 help,会列出所有通过 SHELL_CMD_EXPORT_ALIAS 注册的命令及帮助文本。无线例程的命令(如 wifi_sta_connect)也会列出来。
命令函数能接收参数吗?
能。命令函数签名是 int func(int argc, char **argv),argc 是参数个数、argv 是参数数组。例如注册 set_led 后输入 set_led 1,argv[1] 就是字符串 "1",可用 atoi 转数字。

