Skip to content

Concepts First

  • Partition table: a "map" telling the chip what each Flash region is named and used for (firmware, the partition tables themselves, PSM power-off storage, OTA backup, etc.), with each region's address and size.
  • Dual-table mechanism: two partition tables (table 0 / table 1) live in Flash; at startup the valid one is selected, protecting the "map" from being corrupted by an interrupted erase/write.
  • Active partition: the partition table actually in use; the example fetches and prints it with pt_table_get_active_partition_need_lock.
  • Entry fields: each entry records type, device, active_index, name, start_address[2] / max_len[2] (two backup addresses and lengths), and age (aging counter for dual-table switching).

Example Overview

This page is based on the partition example in the official Bouffalo SDK (examples/partition), which demonstrates reading and printing the active partition table:

  • Registers Flash erase/write/read callbacks (pt_table_set_flash_operation) used by the partition-table component;
  • Calls pt_table_get_active_partition_need_lock to read the active table (dual-table validation and switching are handled internally);
  • _dump_partition prints the header and every entry: magicCode, version, entryCnt, age, crc32, and each entry's addresses/lengths/name.
  • The output corresponds to the partition*.bin flashed into Flash (generated from the partition config), useful for verifying the actual layout.

Note

The actual layout is decided by the build-time partition config (partition_cfg / pt file); this example only reads and prints it. Changing the layout is risky — a wrong table can make the bootloader fail to find the firmware — so keep the official default unless you know what you are doing.

Operation Steps

1
Enter the Example Directory

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

cd examples/partition
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 CONFIG_PARTITION, 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 Verify

Open a serial tool (baud rate 2000000). The program reads the active partition table and prints it: header info (magicCode, version, entryCnt, age, crc32) and one line per entry (index, type, device, active_index, name, two addresses, two lengths, age).

Code Execution Flow

The complete flow from startup to printing the partition table is shown below:

APIs Used by the Example

pt_table_set_flash_operation(erase, write, read)

Registers the partition-table component's Flash access functions as the SDK's bflb_flash_erase / bflb_flash_write / bflb_flash_read.

Parameters:

  • erase: erase callback
  • write: write callback
  • read: read callback

Return: none

pt_table_get_active_partition_need_lock(ptStuff[2])

Reads the active partition table (internally locked, thread-safe). Both tables are validated and the valid one is returned.

Parameters:

  • ptStuff: pt_table_stuff_config array (space for 2 tables)

Return: pt_table_id_type (PT_TABLE_ID_0 / PT_TABLE_ID_1; PT_TABLE_ID_INVALID on failure)

pt_table_get_active_entries_by_name(pt_stuff, name, pt_entry)

Finds an entry by name (not used by the example, but common in real projects), e.g. "PSM" or "FW", returning its address and size.

Parameters:

  • pt_stuff: partition-table contents
  • name: partition name
  • pt_entry: receives the entry info

Return: pt_table_error_type (PT_SUCCESS on success)

Complete Code

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

📜 Click to expand partition/main.c full code
c
#include "bflb_flash.h"
#include "partition.h"
#include "board.h"

#define DBG_TAG "MAIN"
#include "log.h"

#define USER_UNUSED(a) ((void)(a))

static void _dump_partition(pt_table_stuff_config *part)
{
    int i;

    USER_UNUSED(i);
    USER_UNUSED(part);

    printf("======= PtTable_Config @%p=======\r\n", part);
    printf("magicCode 0x%08X;", (unsigned int)(part->pt_table.magicCode));
    printf(" version 0x%04X;", part->pt_table.version);
    printf(" entryCnt %u;", part->pt_table.entryCnt);
    printf(" age %lu;", part->pt_table.age);
    printf(" crc32 0x%08X\r\n", (unsigned int)part->pt_table.crc32);

    printf("idx  type device active_index     name   Address[0]  Address[1]  Length[0]   Length[1]   age\r\n");
    for (i = 0; i < part->pt_table.entryCnt; i++) {
        printf("[%02d] ", i);
        printf(" %02u", part->pt_entries[i].type);
        printf("     %u", part->pt_entries[i].device);
        printf("         %u", part->pt_entries[i].active_index);
        printf("     %8s", part->pt_entries[i].name);
        printf("  0x%08lx", (part->pt_entries[i].start_address[0]));
        printf("  0x%08lx", (part->pt_entries[i].start_address[1]));
        printf("  0x%08lx", (part->pt_entries[i].max_len[0]));
        printf("  0x%08lx", (part->pt_entries[i].max_len[1]));
        printf("  %lu\r\n", (part->pt_entries[i].age));
    }
}

int main(void)
{
    board_init();

    pt_table_set_flash_operation(bflb_flash_erase, bflb_flash_write, bflb_flash_read);

    pt_table_stuff_config ptstuff[2];
    pt_table_id_type active_id;

    active_id = pt_table_get_active_partition_need_lock(ptstuff);

    if (active_id < PT_TABLE_ID_INVALID) {
        _dump_partition(&ptstuff[active_id]);
    } else {
        printf("partition init fail!\r\n");
    }

    while (1) {
    }
}

FAQ

It prints partition init fail

Reading the partition table failed. Common causes: both tables in Flash are invalid, the table address does not match the firmware, or CONFIG_PARTITION is not enabled. Re-flash the full image (including partition*.bin) to recover.

The printed entries do not match the expected layout

The output reflects the table actually flashed into Flash. Check that the build-time partition config (partition_cfg / pt file) and the flashed partition*.bin agree; after changing the config, regenerate and flash the partition table.

How to find a partition by name

Use pt_table_get_active_entries_by_name(pt_stuff, "PSM", &entry) and read start_address / max_len from the returned pt_entry, then access that partition with the MTD interface.

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