Skip to content

Concepts First

  • Shell (command line): a human-machine interface where you type text commands over serial, press Enter to execute, and see results — like a terminal on a PC. Embedded systems use it for debugging and configuration.
  • SHELL_CMD_EXPORT_ALIAS: the macro that registers a function as a command. SHELL_CMD_EXPORT_ALIAS(shell_test, test, shell test.) means typing test calls shell_test().
  • shell_os vs shell_no_os: the SDK provides two variants — shell_os runs on FreeRTOS (a dedicated shell task, input never blocks business logic), while shell_no_os is a bare-metal polling version (calls shell_handler in a while(1) loop).
  • Command entry: almost every wireless example command (wifi_sta_connect, mqtt_connect, etc.) is registered with SHELL_CMD_EXPORT_ALIAS; typing it over serial triggers the function.

Example Overview

This page is based on the shell_os example in the official Bouffalo SDK (examples/shell/shell_os), which demonstrates a FreeRTOS-based Shell:

  • Initializes serial 0 (uart0) and creates the shell task with shell_init_with_task(uart0);
  • Starts the FreeRTOS scheduler (vTaskStartScheduler); the shell task starts listening for serial input;
  • Registers a custom command test via SHELL_CMD_EXPORT_ALIAS, printing shell test when invoked;
  • Sibling example: examples/shell/shell_no_os (bare-metal polling variant without FreeRTOS).

Note

Registering your own commands in the shell is the fastest way to debug your code: flash once, then trigger functions from the serial console without rebuilding.

Operation Steps

1
Enter the Example Directory

Open a terminal and enter the SDK Shell example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/shell/shell_os
2
Build the Project

Run the build command. The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:

make CHIP=bl616 BOARD=bl616dk
3
Flash the Firmware

Connect the board with a USB cable, hold the BOOT button (IO2 on the Ai-M61-32S-Kit), briefly press EN/RST to enter download mode, then flash (replace the serial port with the one on your computer):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
Run and Verify

Open a serial tool (baud rate 2000000). At the bouffalolab /> prompt, type help to list commands (including the test command registered by this example), then type test and press Enter — the serial prints shell test.

Code Execution Flow

The flow from boot to receiving commands is:

APIs Used by the Example

shell_init_with_task(uart)

Initializes the shell and creates a dedicated shell task that reads serial input and parses commands. Typing commands does not affect other tasks.

Parameters:

  • uart: serial device handle (here bflb_device_get_by_name("uart0"))

Returns: none

SHELL_CMD_EXPORT_ALIAS(func, cmd, help)

Registers a function as a shell command at compile time. Typing the command name invokes func(argc, argv).

Parameters:

  • func: the function to call (signature int func(int argc, char **argv))
  • cmd: command name (e.g., test)
  • help: help text shown by the help command

Returns: none (macro)

vTaskStartScheduler()

Starts the FreeRTOS scheduler; the shell task begins running. main never returns after this call.

Parameters: none

Returns: none (never returns)

Complete Code

The following is the complete source of shell_os/main.c, identical to the official example, collapsed by default:

📜 Click to expand shell_os/main.c full code
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.);
📜 Click to expand shell_no_os/main.c full code (bare-metal)
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

Typing a command does nothing. What's wrong?

First check the serial baud rate is 2000000 and the terminal sends a carriage return; then verify the command name matches the registered one (e.g., test). If the prompt itself never appears, the firmware likely wasn't flashed or the wrong serial port is selected.

What is the difference between shell_os and shell_no_os?

shell_os is FreeRTOS-based: the shell is a dedicated task, ideal for OS projects. shell_no_os needs no RTOS: it polls serial input in a while(1) loop, ideal for bare-metal projects. Command registration is identical in both.

How do I list all commands supported by the firmware?

Type help at the bouffalolab /> prompt. It lists every command registered with SHELL_CMD_EXPORT_ALIAS plus its help text, including wireless commands such as wifi_sta_connect.

Can command functions take arguments?

Yes. The signature is int func(int argc, char **argv): argc is the argument count and argv the argument array. For example, after registering set_led, typing set_led 1 gives argv[1] = "1", which you can convert with atoi.

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