Skip to content

Concepts First

  • EFUSE: the chip's factory-burned "ID card" storing package, Flash/PSRAM config, chip ID, and secure-boot info — normally read-only.
  • OTP: one-time programmable — reading is fine, but writes are irreversible; be careful in production.
  • CHIP_ID: a unique per-chip ID, useful for device registration, anti-counterfeiting, and license binding.

Example Overview

This page is based on the efuse_getinfo example in the official Bouffalo SDK (examples/peripherals/efuse/efuse_getinfo), which demonstrates reading the chip's EFUSE factory info:

  • Reads device info: package, PSRAM/Flash config, chip version;
  • Reads the 64-bit CHIP_ID (unique chip ID);
  • Reads the secure-boot signature state and AES key mode (none/128/192/256);
  • On BL616 it also prints the processor process corner.
  • Sibling examples (examples/peripherals/efuse/): efuse_rw (read/write), efuse_trim (trimming).

These values are programmed at the factory and are usually read-only; they can be used for device identification and security feature checks.

Operation Steps

1
Enter the Example Directory

No external wiring is needed — this reads the chip’s factory info. Open a terminal and enter the EFUSE example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/peripherals/efuse/efuse_getinfo
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). The example prints DEVICE_INFO (package/PSRAM/Flash/version), CHIP_ID, SIGNATURE (secure boot), AES_MODE, and on BL616 the processor corner.

Code Execution Flow

The complete execution flow from startup to running is shown below (loop arrows mean repeated execution):

APIs Used by the Example

bflb_device_get_by_name("ef_ctrl")

Gets the EFUSE control device handle.

Parameters:

  • name: device name, always "ef_ctrl"

Return: struct bflb_device_s * handle; NULL if the driver is not loaded

bflb_efuse_get_device_info(&device_info)

Reads factory device info into bflb_efuse_device_info_type (package, PSRAM/Flash, version).

Parameters:

  • info: output struct pointer

Return: 0 on success; negative error code on failure

bflb_efuse_get_chipid(chip_id)

Reads the unique chip ID (8 bytes; the example drops the last 2 bytes when printing).

Parameters:

  • chip_id: uint8_t[8] output buffer

Return: 0 on success; negative error code on failure

bflb_efuse_read_secure_boot(&sign, &aes)

Reads the secure-boot signature state and AES key mode.

Parameters:

  • sign: uint8_t * signature state (1 = enabled)
  • aes: uint8_t * AES mode (0 none / 1 128 / 2 192 / 3 256)

Return: 0 on success; negative error code on failure

Complete Code

The complete source below matches the effect described on this page. It is based on the official example (examples/peripherals/efuse/efuse_getinfo); the LED pins are adapted to the Ai-M61/62-32S-Kit onboard RGB LED. Collapsed by default, click to expand:

📜 Click to expand efuse_getinfo/main.c full code
c
#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_efuse.h"

bflb_efuse_device_info_type device_info;
uint8_t chip_id[8];
uint8_t sign;
uint8_t aes;

const char *aes_mode[] = {"AES-NO", "AES-128", "AES-192", "AES-256"};

int main(void)
{
    struct bflb_device_s *efuse_dev;

    board_init();
    efuse_dev = bflb_device_get_by_name("ef_ctrl");
    if (NULL == efuse_dev) {
        printf("efuse device driver not found!\r\n");
        while (1);
    }

    bflb_efuse_get_device_info(&device_info);
    bflb_efuse_get_chipid(chip_id);
    bflb_efuse_read_secure_boot(&sign, &aes);

    /* printf device_info */
    printf("DEVICE_INFO:\r\n");
    printf("    PACKAGE: %s\r\n", device_info.package_name);
#if !defined(BL602)
    printf("    PSRAM:   %s\r\n", device_info.psram_info_name);
#endif
    printf("    FLASH:   %s\r\n", device_info.flash_info_name);
#if !defined(BL702) && !defined(BL702L)
    printf("    VERSION: %d\r\n", device_info.version);
#endif
    printf("CHIP_ID:\r\n   ");
    for (int i = 0; i < sizeof(chip_id) / sizeof(chip_id[0]) - 2; i++) {
        printf(" %02X", chip_id[i]);
    }
    printf("\r\n");

    printf("SIGNATURE:\r\n    ");
    if (sign) {
        printf("ENABLE\r\n");
    } else {
        printf("DISABLE\r\n");
    }
    printf("AES_MODE:\r\n    %s\r\n", aes_mode[aes]);

#if defined(BL616)
    /* process corner */
    printf("processor corner = %d, %s\n", device_info.process_corner, device_info.process_corner_name);
#endif

    while (1) {
        bflb_mtimer_delay_ms(1000);
    }
}

FAQ

efuse device driver not found

The EFUSE driver is not enabled in the board config. Check board.h/Kconfig for the peripheral or confirm the CHIP used to build.

What is CHIP_ID used for?

CHIP_ID is unique per chip and can be used for device registration, anti-counterfeiting, and license binding; note the example drops the last 2 bytes when printing.

Can EFUSE be written?

EFUSE is one-time programmable (OTP) storage — writes are irreversible. This example is read-only; for writing EFUSE in production, follow the official security docs and operate carefully.

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