QSPI 基础:什么是 QSPI,与 SPI 的区别及优势

1.1 什么是 QSPI?

QSPI 的全称是 Quad SPI,说白了就是传统 SPI 的「四通道加强版」。它保留了 SPI 的主从架构、时钟线(CLK)、片选线(CS),但数据线从原来的两条(MOSI / MISO)扩展到了四条(IO0 ~ IO3)。

我最初接触 QSPI 是在一个需要高速读取外部 Flash 的项目里。当时传统的 SPI Flash 读取速度撑死几十兆字节每秒,但系统需要实时加载字库和波形数据,瓶颈非常明显。改用 QSPI 后,同样的时钟频率下带宽直接翻了两番 —— 嗯,这个数字让我印象很深。

1.2 SPI 与 QSPI 关键区别

很多人以为 QSPI 只是把引脚数翻倍,其实没那么简单。你想想看,传统 SPI 每条数据线是单向的(发送或接收),而 QSPI 的 4 条数据线是 双向 的 —— 根据命令字的不同,可以同时用来发送地址和数据。这背后涉及 多点复用 和 命令-地址-数据 的时序分层。

对比项传统 SPIQSPI(四线)
数据线数量2 条(MOSI, MISO)4 条(IO0~IO3)
最大带宽(@60MHz)60 Mbps240 Mbps
双向传输否(单向固定)是(根据命令切换方向)
命令集复杂度简单需要扩展命令(如 FAST_READ_QUAD)
XIP 支持极少见原生支持(内存映射模式)
引脚复用通常独立可与 GPIO 或 JTAG 复用

我个人习惯在选型表里把 QSPI 的“四线模式”和“双倍数据率(DDR)模式”分开看。很多芯片支持 QSPI 但只支持 SDR(单数据率),这时候带宽其实只比普通 SPI 快一倍,而非四倍。

提示: 区分“四通道模式”与“DDR 模式”。四通道在 SDR 下带宽翻四倍,DDR 再翻倍到八倍。实际芯片往往只能二选一或组合支持,建议仔细阅读手册的表 6-1。

1.3 QSPI 的核心优势

为什么我们要从 SPI 迁移到 QSPI?核心原因只有一个:带宽瓶颈。我曾经在调试一个 LCD 驱动时,SPI 的速率已经顶到 80MHz,但刷一帧 480×272 的图片仍然要 30 多毫秒。换成 QSPI 后,同样的时钟频率下刷新时间直接压到 8 毫秒以内 —— 这个差距在实时性要求高的场景里是决定性的。

  • 更高的吞吐量:四倍数据线,配合流水线命令,持续读取速度接近理论极限。
  • 更少的引脚:相比于并行 Flash(需要 24 条以上引脚),QSPI 只用了 6 条核心引脚(CLK, CS, IO0~IO3)。
  • 支持 XIP:这是 QSPI 最实用的延伸。XIP(Execute in Place)允许 CPU 直接像访问内部 RAM 一样读取 QSPI Flash 中的代码,不用先把代码复制到 SRAM。这一点在内存受限的 MCU 上至关重要。
实战价值: 我遇到过几个团队在评估芯片时只对比了 SPI 的速率,没有考虑 QSPI 的 DDR + 流水线能力。结果在跑图像解码时 CPU 因为等待 Flash 数据而频繁 stall,最终不得不降频。所以我的建议是 —— 如果你要做代码量大于 256KB 且需要快速启动的项目,直接上 QSPI + XIP。

1.4 QSPI 与 XIP 的关系

XIP 并不是 QSPI 强制拥有的功能,而是 QSPI 控制器提供的 内存映射模式。当 QSPI 配置成内存映射后,CPU 发出读地址,控制器自动解析成 QSPI 命令序列(发送命令→地址→dummy cycles→读数据),整个过程对 CPU 透明。换句话说,你直接用指针访问外部 Flash 就行。

我记得第一次看到 QSPI 内存映射成功时,用调试器查看那个 0x90000000 地址段,里面直接显示了 Flash 里的数据,那种感觉就像把外部存储器「挂载」到了系统总线上一样。当然,这里有个坑 —— 我曾经因为没有配置 dummy cycles 导致高位数据总是错位,逻辑分析仪抓了半天才意识到 Flash 需要额外的等待周期才能切换方向。

避坑: 很多 QSPI Flash 在四通道读命令(如 0xEB)中要求 至少 4 个 dummy cycles(双倍数据率下则为 2 个)。如果你的控制器只配了 1 个 dummy,读出来的第一个字节往往全是乱码。建议先用慢时钟加长 dummy 验证,再优化。
QSPI vs SPI 对比图 传统 SPI 主设备(MCU) CLK, CS, MOSI, MISO 从设备(Flash) 单向数据通路 最大带宽:60 Mbps 不支持 XIP 命令集简单 QSPI(四线) 主设备(MCU) CLK, CS, IO0~IO3 从设备(Flash) 双向数据通路 最大带宽:240 Mbps 内存映射 / XIP 扩展命令(0xEB 等) 演进

1.5 一个简单的 QSPI 读命令序列

下面是一个针对 W25Q64(QSPI Flash)的四通道快速读命令(0xEB)的时序伪代码。实际编程中需要配置控制器的 FIFO 和 dummy 周期数。

// 伪代码:QSPI 四通道读模式(SDR)
// 配置 QSPI 控制器为四线模式
QSPI_Config(QuadMode, SDR, DummyCycles = 4);

// 发送命令字节 0xEB
QSPI_Write(0xEB);      // 占用 IO0(单线)
// 发送 24 位地址(MSB 先)
QSPI_Write(0x00);      // 地址高位
QSPI_Write(0x10);      // 地址中位
QSPI_Write(0x00);      // 地址低位
// 4 个 dummy 周期(用于方向切换)
QSPI_Dummy(4);
// 开始读取数据(从 IO0~IO3 同时接收)
for (i = 0; i < 256; i++) {
    buffer[i] = QSPI_Read(); // 每次读取 4 字节
}

看到这段代码你可能想问:为什么地址传输还是单线?嗯,这里有个设计细节 —— 命令和地址阶段通常保持单线或双线模式,目的是兼容更老的 Flash 芯片。只有后面的数据阶段才切换到四线。我最早就是在这个阶段栽过跟头:我以为整个序列都是四线,结果 Flash 根本不响应。后来用逻辑分析仪一量,才发现地址字节只出现在了 IO0 上。

调试技巧: 用逻辑分析仪捕获 CLK、CS 和 IO0~IO3 的波形。重点关注 dummy 周期之后数据线是否同时切换。如果只看到 IO0 有数据变化,说明控制器没有切换到四线模式。