Skip to content

Concepts First ​

  • PSRAM: external large memory (cheaper than SRAM, faster than Flash) for big caches/buffers.
  • Cache coherency: the CPU data cache can hide stale values when reading/writing PSRAM; the example disables/cleans the cache first so results are real.
  • What the test does: writes incrementing data at different widths and reads it back for comparison, checking memory correctness bit by bit.

Example Overview ​

This page is based on the psram example in the official Bouffalo SDK (examples/peripherals/psram), which demonstrates onboard PSRAM read/write testing:

  • Gets the PSRAM size with board_psram_size_get();
  • Writes incrementing data and reads it back at uint8 / uint16 / uint32 widths;
  • Disables/cleans the data cache first (bflb_l1c_dcache_disable + clean_all) so reads reflect the real memory.

Operation Steps ​

1
Enter the Example Directory

This page reads/writes the onboard PSRAM directly; no external wiring is needed (the board must have PSRAM). Open a terminal and enter the PSRAM example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/peripherals/psram
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 the PSRAM size, then runs 8/16/32-bit write/read checks; it prints test success when all pass, or psram check fail and stops on error.

Code Execution Flow ​

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

APIs Used by the Example ​

board_psram_size_get() ​

Gets the onboard PSRAM size in bytes (printed in MB).

Parameters: none

Return: PSRAM size in bytes

bflb_l1c_dcache_disable() ​

Disables the data cache so reads/writes go directly to memory, avoiding cache coherency issues.

Parameters: none

Return: none

bflb_l1c_dcache_clean_all() ​

Cleans the whole data cache, writing dirty data back to memory.

Parameters: none

Return: none

BFLB_PSRAM_BASE(macro) ​

PSRAM mapping base address; the example reads/writes at BFLB_PSRAM_BASE + offset.

Parameters: none

Return: PSRAM base address

Complete Code ​

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

📜 Click to expand psram/main.c full code
c
#include "bflb_core.h"
#include "bflb_l1c.h"
#include "board.h"
#if __has_include("board_flash_psram.h")
#include "board_flash_psram.h"
#else
extern uint32_t board_psram_size_get(void);
#endif

#define BFLB_PSRAM_TEST_ADDR (BFLB_PSRAM_BASE + (0 * 1024 * 1024))

uint32_t psram_test_size = 0;

void test32(void)
{
    uint32_t i, val;

    printf("============= check uint32_t ==============\r\n");

    for (i = 0; i < psram_test_size; i += 4) {
        *((volatile uint32_t *)(BFLB_PSRAM_TEST_ADDR + i)) = i / 4;
    }

    for (i = 0; i < psram_test_size; i += 4) {
        val = *((volatile uint32_t *)(BFLB_PSRAM_TEST_ADDR + i));
        if (i / 4 != val) {
            printf("addr = 0x%08X, val = 0x%08X, expect = 0x%08X\r\n", (BFLB_PSRAM_TEST_ADDR + i), val, i / 4);
            printf("psram check fail\r\n");
            while (1)
                ;
        }
    }
}

void test16(void)
{
    uint32_t i, val;

    printf("============= check uint16_t ==============\r\n");

    for (i = 0; i < psram_test_size; i += 2) {
        *((volatile uint16_t *)(BFLB_PSRAM_TEST_ADDR + i)) = i / 2;
    }
    for (i = 0; i < psram_test_size; i += 2) {
        val = *((volatile uint16_t *)(BFLB_PSRAM_TEST_ADDR + i));

        if (((i / 2) & 0xffff) != val) {
            printf("addr = 0x%08X, val = 0x%08X, expect = 0x%08X\r\n", (BFLB_PSRAM_TEST_ADDR + i), val, (i / 2) & 0xffff);
            printf("psram check fail\r\n");
            while (1) {
            }
        }
    }
}

void test8(void)
{
    uint32_t i;
    uint8_t val;

    printf("============= check uint8_t ==============\r\n");

    for (i = 0; i < psram_test_size; i++) {
        *((volatile uint8_t *)(BFLB_PSRAM_TEST_ADDR + i)) = i;
    }

    for (i = 0; i < psram_test_size; i++) {
        val = *((volatile uint8_t *)(BFLB_PSRAM_TEST_ADDR + i));

        if ((i & 0xff) != val) {
            printf("addr = 0x%08X, val = 0x%08X, expect = 0x%08X\r\n", (BFLB_PSRAM_TEST_ADDR + i), val, i & 0xff);
            printf("psram check fail\r\n");
            while (1) {
            }
        }
    }
}

int main(void)
{
    board_init();

    psram_test_size = board_psram_size_get();
    printf(" psram test size: %u MB\r\n", psram_test_size / (1024 * 1024));
    printf(" psram read write test \r\n");

    bflb_l1c_dcache_clean_all();

    bflb_l1c_dcache_disable();

    test8();
    test16();
    test32();

    printf(" test success\r\n");

    while (1) {
    }
}

FAQ ​

psram check fail

First confirm the board has PSRAM (module variant with PSRAM); verify board_psram_size_get() returns non-zero; if you changed cache handling, check that the cache is disabled/cleaned correctly before read/write.

Why start the test address at 0?

The example tests the first 1 MB from the PSRAM base. In a real project, avoid areas already used by the linker/heap.

Does disabling the cache hurt performance?

Yes. Cache is disabled only for test correctness; keep it enabled in real use and manage DMA-shared regions with bflb_l1c_dcache_clean/invalidate_range.

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-30 17:31:25