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.c

  • Driver: middleware/driver/qspi/qspi_driver.c

  • Flash helper: middleware/driver/qspi/qspi_flash.c

3. Configuration

NAME

Description

File

value

CONFIG_QSPI

Enable QSPI driver and test commands

middleware/soc/bk7258_ap/bk7258_ap.defconfig

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

QSPI CLI commands

Command

Param

Description

qspi_driver {init|deinit}

init/deinit

Initialize or release shared QSPI resources

qspi {id} init {src_clk} {src_div} {div}

id: 0–1; src_clk: 0=320M, 1=480M; src_div: clock divider; div: internal divider

Enable QSPI and configure the clock (actual_clk = src_clk / (1 + src_div) / (2 * div))

qspi_flash {id} get_id {addr} {len}

id: 0–1; addr/len: any values

Issue 0x9F to read vendor ID (also unprotects flash and sets QE)

qspi_flash {id} read {addr} {len}

id: 0–1; addr: flash offset; len: length

Read via 0xEB (quad I/O); enable QE first

qspi_flash {id} erase {addr} {len}

id: 0–1; addr: flash offset; len: length

Erase via 0x20

qspi_flash {id} write {addr} {len}

id: 0–1; addr: flash offset; len: length

Write via 0x32

qspi {id} flash_test {addr} {len}

id: 0–1; addr: flash offset; len: length

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_test for a full cycle.

7. FAQ

  • Supported bus width? 1/2/4-line half-duplex. bk_qspi_flash_read/bk_qspi_flash_write dispatch to the single/dual/quad path per CONFIG_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.