QSPI
1. Overview
QSPI operates as a master to read/write slave devices (flash, PSRAM, LCD, etc.) using 1-, 2-, or 4-data-line SPI. BK7258 provides two QSPI controllers and supports:
Indirect mode – all operations through QSPI registers.
Memory-mapped mode – external device mapped into the MCU address space.
See the driver guide: QSPI Working Principles
2. Code Path
Demo:
components/bk_cli/cli_qspi.cDriver:
middleware/driver/qspi/qspi_driver.cFlash helper:
middleware/driver/qspi/qspi_flash.c
3. Configuration
NAME |
Description |
File |
value |
|---|---|---|---|
CONFIG_QSPI |
Enable QSPI driver and test commands |
|
y |
CONFIG_QSPI_MST_FLASH |
Enable QSPI flash driver |
same as above |
y |
CONFIG_QSPI_FLASH_GD |
Distinguish flash vendor/command coverage |
same as above |
y |
CONFIG_QSPI_LINE_MODE |
Flash R/W bus width: 1=single 2=dual 4=quad |
same as above |
4 |
4. Pins
QSPI0 (group 0):
Signal |
GPIO |
|---|---|
QSPI0_SCK QSPI0_CS QSPI0_DAT[0] QSPI0_DAT[1] QSPI0_DAT[2] QSPI0_DAT[3] |
GPIO22 GPIO23 GPIO24 GPIO25 GPIO26 GPIO27 |
QSPI1 (group 0): GPIO2–GPIO7 (SCK/CS/D0–D3).
5. CLI Commands
Command |
Param |
Description |
|---|---|---|
|
|
Initialize or release shared QSPI resources |
|
|
Enable QSPI and configure the clock (actual_clk = src_clk / (1 + src_div) / (2 * div)) |
|
|
Issue 0x9F to read vendor ID (also unprotects flash and sets QE) |
|
|
Read via 0xEB (quad I/O); enable QE first |
|
|
Erase via 0x20 |
|
|
Write via 0x32 |
|
|
Run self-test (ID/erase/write/read) |
Note
qspi {id} init {src_clk} {src_div} {div} above sets the dividers manually. When using the
flash APIs, bk_qspi_flash_init() initializes the clock internally via
bk_qspi_init_by_freq(id, QSPI_FLASH_MAX_SCK_HZ), where QSPI_FLASH_MAX_SCK_HZ = 80 MHz (the
max configurable QSPI SCK). bk_qspi_init_by_freq auto-searches the divider combination closest
to the target frequency without exceeding it.
Clock formula (SCK is the actual QSPI output clock):
SCK = src_clk / ((1 + src_clk_div) * (clk_div == 0 ? 1 : 2 * clk_div))
- src_clk : source clock, 480 MHz or 320 MHz
- src_clk_div : first-stage divider, hardware requires >= 4
- clk_div : second-stage divider; 0 bypasses the stage (/1), otherwise 2 * clk_div
Examples:
480 MHz / ((1 + 5) * 1) = 80 MHz (picked by bk_qspi_init_by_freq(id, 80 MHz): src_clk_div=5, clk_div=0)
480 MHz / ((1 + 4) * (2 * 2)) = 24 MHz (default fallback: src_clk_div=4, clk_div=2)
480 MHz / ((1 + 5) * (2 * 5)) = 8 MHz (matches demo cmd: qspi 1 init 1 5 5)
6. Demo Walkthrough
Connect the BK7258 board to an external flash (3.3 V) as shown.
Initialize and set clock dividers, e.g.
cpu1 qspi 1 init 1 5 5.Read vendor ID:
cpu1 qspi_flash 1 get_id 0 100.Erase sector:
cpu1 qspi_flash 1 erase 0 4096.Read/verify erased data, write data, re-read, or run
flash_testfor a full cycle.
7. FAQ
Supported bus width? 1/2/4-line half-duplex.
bk_qspi_flash_read/bk_qspi_flash_writedispatch to the single/dual/quad path perCONFIG_QSPI_LINE_MODE(1/2/4, default 4).Why does ID read fail? Check power (3.3 V) and QSPI clock (≤80 MHz).
ID OK, but erase/write fails? Ensure flash is unprotected and QE (quad enable) is set. Status register commands vary by vendor; the driver provides both S0–7/S8–15 variants.