Quad/Octal SPI(QSPI/OSPI)控制器:1-4-8 线、STR/DTR 与内存映射读
更新时间:2026-09-19。前置:SPI 四种模式、SPI NOR XIP 启动。本文聚焦协议线数、双沿与控制器微架构。
本文要回答的问题
- 1-1-4、1-4-4、4-4-4 这种命令编码每一位指什么?
- Quad 和 Octal 差在哪,DTR 双沿怎么再翻倍?
- 内存映射(XIP)窗口背后控制器在每个 miss 上发什么序列?
- 模式字节、dummy、采样相位、跨页回绕有哪些坑?
一、线数与命令编码
SPI 命令分阶段:指令 opcode / 地址 address / 模式 mode / dummy / 数据 data。
「a-b-c」表示指令/地址/数据三个阶段各用几根线:
| 编码 | 指令 | 地址 | 数据 | 说明 |
|---|---|---|---|---|
| 1-1-1 | 1 | 1 | 1 | 标准 SPI |
| 1-1-4 | 1 | 1 | 4 | Quad 输出快读 6Bh |
| 1-4-4 | 1 | 4 | 4 | 地址也走 4 线(EBh 类) |
| 4-4-4 | 4 | 4 | 4 | 含 QPI/Quad 指令模式 |
| 8-8-8 | 8 | 8 | 8 | OSPI Octal 全 8 线 |
数据线:标准 SPI 用 IO0(MOSI)/IO1(MISO);Quad 加 IO2(原 WP#)/IO3(原 HOLD#);Octal 用 IO0–IO7 共 8 根,并通常带独立 DQS(数据选通)。
二、STR vs DTR
- STR(single transfer rate):只在时钟一个边沿(通常上升沿)传数据。
- DTR(double transfer rate):地址/数据在两个边沿都传,吞吐再翻倍(指令通常仍单沿)。OSPI 常用 DTR + DQS 对齐高速源同步采样。
吞吐直觉(数据阶段):1 线 STR 为基准,4 线 STR ≈4×,8 线 DTR ≈16×。实际受命令/地址/dummy 开销和最高 SCLK 限制。
三、一次 Quad IO 快读序列(1-4-4,EBh)
CS#↓
[1线] EB (opcode)
[4线] A23..A0 (地址,6 个半字节拍)
[4线] mode byte (连续读模式,可让后续读省 opcode/地址)
[4线] dummy cycles (按频率与延迟档配置)
[4线] data0 data1 ... (连续吐出,地址自增)
CS#↑- 模式字节(continuous/mode bits):EBh 序列里有一段模式位,设成约定值可让 Flash「记住」处于连续读,下一次拉低 CS# 直接给地址,省 opcode;若设错/关闭则每次都要全序列。
- dummy cycle:给 Flash 内部取数和延迟留时间,频率越高/延迟档越高 dummy 越多;和 PCB 延迟、控制器采样相位一起决定能不能采稳。
- DQS(OSPI):高速下用从器件回的 DQS 选通做源同步,控制器用它而不是 SCLK 直接采数据。
四、控制器微架构(内存映射模式)
AXI/AHB 读地址(内存窗口)
│ miss
┌─────▼─────────┐
│ 行缓存/cache │◄─ 预取整行
└─────┬─────────┘
▼
┌───────────────────────────┐
│ 命令 FSM: │
│ 组装 opcode/addr/mode/ │──IO0..7,SCLK,CS#,DQS
│ dummy/数据,位打包+相位 │
│ 写入: WREN→编程/擦除→轮询 │
└───────────────────────────┘控制器把「一次总线突发读」翻译成「一条 Quad/Octal 快读 + 连续取一整行」,用预取摊薄固定开销(见 XIP 控制器)。写路径需互斥,擦写在 RAM 里执行并刷行缓存。
五、常见的坑
- IO2/IO3 引脚没切 Quad 模式:上电默认是 WP#/HOLD#,且要发 QE(quad enable)非易失位;不开 QE 读全 FF。
- dummy cycle 数与频率/型号不匹配:少一个错位、多一个丢首字节;换频率档要同步改。
- 模式字节配错:连续读使能/关闭在主从两端不一致,第二条读就错。
- 采样相位/延迟没校:高速下 SCLK 边沿采到跳变区,需调 controller delay 或用 DQS。
- STR/DTR 与器件支持不符:在不支持 DTR 的器件开双沿,数据全错;DTR 地址拍数减半容易算错。
- 跨页/256B 边界:连续读到页边界行为需查手册,有的需重新发命令。
- OSPI 8 线/DQS 板级等长:八线偏斜大、DQS 未等长,高速眼图闭合。
- QE 与 WP# 冲突:开了 Quad 后 WP# 功能变化,硬件写保护逻辑失效需重新评估。
- XIP 下执行擦写:命令总线被占导致取指饿死,擦写代码必须放 RAM。
- 命令编码想当然:把 1-4-4 当 4-4-4,opcode 也走 4 线导致无应答(QPI 未使能)。
- 电压档(1.8V/3V)与器件不符:双电压器件选错档不收。
- 预取误触发读副作用:某些内存映射寄存器型器件不能无脑预取(NOR 随机读无副作用才安全)。
相关与延伸
启动与 XIP 全流程见 SPI NOR XIP;基础时序见 SPI CPOL/CPHA;引脚复用见 PinMux;高速串行对照 SGMII/SerDes 概念。
总结
Quad/Octal SPI 用「opcode/地址/数据」各阶段线数(1-1-4/1-4-4/4-4-4/8-8-8)和 STR/DTR 双沿把数据吞吐推到 4×~16×:Quad 复用 WP#/HOLD# 作 IO2/3(需置 QE 位),OSPI 用 IO0–7 加 DQS 做源同步;控制器在内存映射窗口的每个 miss 上发「opcode→地址→模式字节→dummy→连续数据」整行预取,dummy、模式字节和采样相位随频率档联动——忘开 QE、dummy/相位不配、DTR 误用和 IO2/3 被占用是读全 FF 的四大根因。