Skip to content

概念先知道

  • 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_connectmqtt_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,是调试自己代码最快的方式:烧录后不用重新编译,直接串口输入命令就能触发函数。

操作步骤

1
进入例程目录

在终端进入 SDK 的 Shell 例程目录(前提:已按快速开始(Linux)Windows搭建好环境):

cd examples/shell/shell_os
2
编译工程

执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:

make CHIP=bl616 BOARD=bl616dk
3
烧录固件

用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
运行验证

打开串口助手(波特率 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 命令会显示

返回值:无(宏)

vTaskStartScheduler()

启动 FreeRTOS 调度器,shell 任务从此开始运行。调用后主函数不再返回。

参数:无

返回值:无(永不返回)

完整代码

以下为 shell_os/main.c 完整源码,与官方示例一致,默认折叠,点击展开:

📜 点击展开 shell_os/main.c 完整代码
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 完整代码(裸机版)
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 1argv[1] 就是字符串 "1",可用 atoi 转数字。

Released under the MIT License. Build Time 2026-09-11 14:52:23