Skip to content

Concepts First

  • Crash: a runaway program, illegal memory access, assert failure, etc. that pushes the chip into an exception. The CPU registers and call stack at that moment are together called a coredump.
  • Core partition: the partition table region reserved for coredumps. The example opens the partition named core via MTD and writes the crash state there, so it survives reset and can be exported later.
  • Shell (command line): serial interactive commands. The example registers a crash command to crash on purpose, making the coredump flow easy to demonstrate.
  • Analysis tool: tools/byai/coredump.py reads the coredump together with the build artifact (.elf) to reconstruct the call stack and registers, pinpointing where the crash happened.

Example Overview

This page is based on the crash example in the official Bouffalo SDK (examples/crash), which demonstrates generating, saving, and offline-analyzing a coredump:

  • Initializes MTD, opens the core partition, and prints its address and size;
  • core_partition_init configures where the coredump is written;
  • Starts a serial shell and registers the crash command, which calls assert(0) to force a crash;
  • On crash, the coredump is written to the Flash core partition while crash info is printed on the serial port;
  • After exporting the core partition, tools/byai/coredump.py reconstructs the call stack with the ELF file.
  • The example depends on FreeRTOS, shell, MTD, and partition components; the official README notes the analysis flow supports Linux.

Note

Crash debugging depends on the core partition in the partition table: without it the program prints No valid coredump partition found and no coredump is saved. Also, after the assert(0) crash you must re-enter download mode (or reset) before exporting data.

Operation Steps

1
Enter the Example Directory

No external wiring is needed for this page. Open a terminal and enter the SDK crash-debug example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/crash
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 (the example depends on FreeRTOS, shell, MTD, and partition components, enabled in its defconfig):

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 Trigger a Crash

Open a serial tool (baud rate 2000000). The program prints the core partition’s XIP address / flash address / size and starts the shell; type crash and press Enter. The shell calls assert(0) to force a crash: the serial port shows crash output and a coredump is written to the Flash core partition.

crash
5
Export and Analyze the Coredump (Linux)

After the crash, re-enter download mode and read the core partition with the SDK tools, then use coredump.py with the compiled ELF to locate the crash (use the addresses printed at startup):

./tools/bflb_tools/bouffalo_flash_cube/BLFlashCommand-ubuntu --chip bl616 --read --flash --start 0x2f8000 --len 0x80000 --file crash.bin --port /dev/ttyACM0
./tools/byai/coredump.py crash.bin examples/crash/build/build_out/crash_bl616.elf

Code Execution Flow

The complete flow from startup to crash and analysis is shown below:

APIs Used by the Example

bflb_mtd_init()

Initializes MTD (Flash-partition abstraction); required before opening partitions by name.

Parameters: none

Return: 0 on success; negative error code on failure

bflb_mtd_open("core", &handle, flags)

Opens an MTD partition by name. The example opens "core" with BFLB_MTD_OPEN_FLAG_BUSADDR; a negative return means failure.

Parameters:

  • name: partition name, "core" in the example
  • handle: returned partition handle
  • flags: open flags

Return: 0 on success; negative error code on failure

bflb_mtd_info(handle, &info)

Gets partition info (XIP address, flash offset, size); the example prints these values.

Parameters:

  • handle: partition handle
  • info: bflb_mtd_info_t with xip_addr / offset / size

Return: 0 on success; negative error code on failure

core_partition_init(flash_addr, flash_size)

Configures the coredump write location as the core partition (Flash address + size); crashes are then written there automatically.

Parameters:

  • flash_addr: core partition flash offset (info.offset in the example)
  • flash_size: core partition size (info.size in the example)

Return: none

shell_init_with_task(uart_dev)

Starts the serial shell as a dedicated task, allowing commands such as crash to be typed.

Parameters:

  • uart_dev: UART device handle (uart0 in the example)

Return: none

SHELL_CMD_EXPORT_ALIAS(func, name, desc)

Registers a C function as a shell command: the example registers shell_crash as crash, which calls assert(0) to force a crash.

Parameters:

  • func: command function
  • name: command name ("crash")
  • desc: command description

Return: none

Complete Code

The complete source below matches the official example (examples/crash) verbatim. Collapsed by default, click to expand:

📜 Click to expand crash/main.c full code
c
#include <assert.h>
#include "bflb_mtimer.h"
#include "bflb_uart.h"
#include "shell.h"
#include <FreeRTOS.h>
#include "semphr.h"
#include "board.h"

#include "bflb_mtd.h"
#include "coredump.h"

static struct bflb_device_s *uart0;

extern void shell_init_with_task(struct bflb_device_s *shell);

int main(void)
{
    bflb_mtd_info_t info;
    bflb_mtd_handle_t handle;
    int ret;

    board_init();

    bflb_mtd_init();
    ret = bflb_mtd_open("core", &handle, BFLB_MTD_OPEN_FLAG_BUSADDR);
    if (ret < 0) {
        puts("No valid coredump partition found\r\n");
    }
    memset(&info, 0, sizeof(info));
    bflb_mtd_info(handle, &info);
    printf("Found Valid coredump partition, XIP Addr %08x, flash addr %08x, size %d\r\n",
           info.xip_addr,
           info.offset,
           info.size);
    core_partition_init(info.offset, info.size);

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    vTaskStartScheduler();

    while (1) {
    }
}

int shell_crash(int argc, char **argv)
{
    printf("shell crash\r\n");
    //asm ("ebreak");
    assert(0);
    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_crash, crash, trigger crash.);

FAQ

It says No valid coredump partition found

The partition table has no core partition. Check the partition config (partition_cfg / pt file) for an entry named core, then regenerate and flash the partition table and firmware.

Typing crash does nothing

Confirm you are typing a shell command (crash + Enter) at baud 2000000; if the shell is not running, check that CONFIG_SHELL is enabled and vTaskStartScheduler executed.

How do I know the export addresses

Use the flash addr / size printed at startup (0x2f8000 and 0x80000 in the official README are examples for the default partition config). With other configs, replace --start and --len with the printed values.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

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