Concepts First
- Flash: non-volatile storage whose contents survive power loss; firmware and user data live here. This page demonstrates basic data-area read/write.
- Erase before write: Flash can only turn 1 into 0 (write); turning 0 back to 1 requires erasing first, and erase happens per sector (4 KB in the example).
- Erased state: after erase every bit is 1, so every byte reads back as
0xFF; the example uses that to verify erasure. - Be careful: before writing Flash, confirm the target address is not inside the firmware, partition table, or OTA regions, or you may corrupt the program.
Example Overview
This page is based on the flash_read_write example in the official Bouffalo SDK (examples/peripherals/flash/flash_read_write), which demonstrates the most basic erase, write, and read-back verification of internal Flash:
- Starting at offset
0x10000, erases 4 KB (one page) at a time for 10 pages (40 KB); - After erasing, reads back and confirms every byte is
0xFF; - Writes a repeating 0–255 pattern, reads it back, and compares byte by byte; any mismatch prints an error and stops;
- Each page prints
check success; after all 10 pages it printsflash read write success. - Sibling examples (
examples/peripherals/flash/):flash_dma(DMA read, see "Basic Peripherals → Flash Internal Storage"),flash_xip_read(XIP read),flash_iomode(IO modes),flash_get_image_hash(image hash),flash_secreg/flash_secreg_lock(secure registers),flash_secure_read_write(secure read/write).
Note
The example operates on Flash at offset 0x10000, the test area reserved by the official example. In real projects, always confirm the target address is outside the firmware, partition table, and OTA regions before writing.
Operation Steps
No external wiring is needed for this page. Open a terminal and enter the SDK flash read/write example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):
cd examples/peripherals/flash/flash_read_writeRun 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). Starting at offset 0x10000, the program processes 10 pages of 4 KB each (40 KB total): erase, read back to verify all bytes are 0xFF, write the 0–255 pattern, read back and compare byte by byte. Each page prints check success; after all pages it prints flash read write success.
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_flash_erase(addr, len)
Erases a Flash region. Erase happens per sector; a len smaller than one sector is rounded up. After erasing, the region reads back as 0xFF.
Parameters:
addr: Flash address (starts at0x10000, advances by 4 KB)len: erase length (4096 in the example)
Return: 0 on success; negative error code on failure
bflb_flash_write(addr, data, len)
Writes data to Flash. The corresponding sector must be erased first, and the address should be aligned to the Flash programming granularity.
Parameters:
addr: Flash addressdata: source bufferlen: number of bytes
Return: 0 on success; negative error code on failure
bflb_flash_read(addr, data, len)
Reads Flash data into a memory buffer.
Parameters:
addr: Flash addressdata: destination bufferlen: number of bytes
Return: 0 on success; negative error code on failure
Complete Code
The complete source below matches the official example (examples/peripherals/flash/flash_read_write) verbatim. Collapsed by default, click to expand:
📜 Click to expand flash_read_write/main.c full code
#include "bflb_flash.h"
#include "board.h"
#define FLASH_RW_TOTAL_SIZE (10 * 4096)
#define FLASH_RW_START_ADDR 0x10000
static uint8_t write_buf[4096];
static uint8_t read_buf[4096];
int main(void)
{
uint32_t i, j;
uint32_t flash_addr;
board_init();
for (i = 0; i < sizeof(write_buf); i++) {
write_buf[i] = i;
}
for (uint32_t offset = 0; offset < FLASH_RW_TOTAL_SIZE; offset += sizeof(write_buf)) {
flash_addr = FLASH_RW_START_ADDR + offset;
printf("erase addr:%08x\r\n", flash_addr);
/* erase flash */
bflb_flash_erase(flash_addr, sizeof(write_buf));
memset(read_buf, 0, sizeof(read_buf));
/* read flash data */
bflb_flash_read(flash_addr, read_buf, sizeof(read_buf));
for (j = 0; j < sizeof(read_buf); j++) {
if (read_buf[j] != 0xff) {
printf("flash erase fail at %d, expect:%d but get %d\r\n", j, 0xff, read_buf[j]);
while (1) {
}
}
}
/* write flash data */
bflb_flash_write(flash_addr, write_buf, sizeof(write_buf));
memset(read_buf, 0, sizeof(read_buf));
/* read flash data */
bflb_flash_read(flash_addr, read_buf, sizeof(read_buf));
for (j = 0; j < sizeof(read_buf); j++) {
if (read_buf[j] != write_buf[j]) {
printf("flash read fail at %d, expect:%d but get %d\r\n", j, write_buf[j], read_buf[j]);
while (1) {
}
}
}
printf("check success\r\n");
}
printf("flash read write success\r\n");
while (1) {
}
}FAQ
It prints flash erase fail
After erase, data is not 0xFF. Common causes: the address is not an idle region (e.g. firmware/partition table), or the Flash part/sector size differs from the example's assumption. Try the official reserved test address instead.
It prints flash read fail
Data read back differs from what was written. Confirm the sector was erased before writing, and that the address alignment and length fit the Flash part.
The program crashes or keeps resetting after flashing
The example likely corrupted the firmware region. Re-enter download mode and flash the full image to recover; for future experiments keep addresses inside the official reserved test area.
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

