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
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_getinfoRun the build command. The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:
make CHIP=bl616 BOARD=bl616dkConnect 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/ttyUSB0Open 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
#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

