只读分享解决方案文档原理方案设计📅 2026-10-14🔖 Rev 1.0⏳ 还有3日到期
🔧解决方案&应用市场分析 -> 原理方案设计 -> 电子设计&技术探讨 -> SPI_NOR_XIP与执行性能_技术探讨

SPI_NOR_XIP与执行性能_技术探讨

同系列 · 原理方案设计
扫码打开本页
微信扫码

SPI_NOR XIP 与执行性能 技术探讨

从 XIP 三条路线到有效带宽天花板 —— 一份给电路设计指南「选型章节」用的性能论证材料 | 编制日期 2026-10-14 | 版本号 Rev 1.0

3 ×
随机小读与顺序大读的有效带宽差
固定事务开销主导
×2
DTR 双沿带来的带宽倍数
引脚与时序约束同步加倍
3 段
启动耗时的可拆解结构
时钟 / 初始化 / 首次读
16 ~ 18
本文覆盖的带宽算例档位
x1 / x4 / x8 DTR
报告总结

《SPI_NOR_Flash_电路设计指南》里「选型章节」最容易被写成一句口号:「支持 XIP,最高 200 MHz」。口号无法支撑评审,因为评审真正会问的是三件事:XIP 到底是怎么实现的、要付出什么代价、我的板子上能不能达到宣传带宽。

本文把这三件事拆开讲透:先把 XIP 的三条实现路线摆在一起做取舍,再把「一次读指令」拆到 SCK 级别算清固定开销,然后逐层叠加连续读、DTR/Octal、器件 cache,最后落到一个可以自己复算的有效带宽公式与一张瓶颈判别树上。读完你应该能独立写出:我们的启动镜像多大、走哪条 XIP 路线、总线配到多少、实测应该落在哪个区间、达不到时先查哪一级。

结论: XIP 不是器件特性,而是主控内存映射 + 器件随机取指延迟 + 一条足够快的总线三者的合成结果。 决定启动性能的从来不是峰值带宽,而是固定事务开销——指令帧、器件首字节延迟、主控发起一次读事务的软件成本。 连续读、DTR、器件 cache 这三项技术,本质上都在摊薄同一个固定开销; 而当总线快到固定开销占比超过三成时,再往上加频率只会让曲线变平,此时该做的是换总线宽度,而不是换主控频率。

读者路径

  • 写电路设计指南的选型章节:直接看第 1、6、7 章(路线取舍 + 带宽公式 + 启动拆解),这三章是性能论证的全部骨架;再配第 8 章做跨介质对照。
  • 做硬件 / SI 评审:第 4、5、9 章,重点是 DQS 相位裕度、串阻拓扑与电源跌落对读时序置信度的影响。
  • 做软件与 BSP:第 2、3 章最有用——dummy 周期为什么各家不同、连续读什么时候必须退出、模式位切换的顺序约束。
  • 遇到测出来的带宽不对:第 6.4 节的瓶颈判别树,按图索骥逐级排除,不要凭感觉换料号。
  • 被现象卡住:第 11 章的现象排查表与误区表,按现象反查。
  • 需要量级数字:附录 B(代际带宽与时序)与附录 C(模式位组合与 dummy 周期)是两张速查大表。

定位说明:本文是《SPI_NOR_Flash_电路设计指南》与《SPI_NOR_Flash_软件设计规范》的技术支撑篇,只讲性能论证,不复述那两份文档的接口定义、寄存器职责与软件流程。

1. XIP 是什么:三条实现路线的取舍

XIP(eXecute In Place executing in Place)经常被当成「器件支持内存映射」这一句话来用。实际上它是三段能力的合成:主控把一段地址空间映射到串行总线、器件能在极短时间内吐出任意地址的数据、取指链路不需要软件搬运。缺任何一段,都不是真 XIP。

1.1 XIP 的定义与三个必要条件

先把它拆成可验证的三个条件,后面所有性能讨论都挂在这三个条件上:

必要条件具体含义由谁提供不满足时的表现
随机取指CPU 可以在任意顺序、任意地址上取到指令字节,且这个顺序由程序的跳转决定器件阵列结构(NOR 的优势)表现为「只能顺序读」,代码必须线性排列并整段搬走
地址连续映射Flash 被映射进主控地址空间的一段,主控的取指访问被硬件翻译成总线事务主控的存储控制器 / MMU表现为每次取指要走中断或函数指针,软件复杂度爆炸
无需搬运没有「先把 Flash 内容拷进 SRAM」这一步,CPU 直接对映射地址取指软件 + 硬件共同保证表现为启动时间被搬运耗时线性支配

这个拆法的工程价值:当项目抱怨 XIP 性能差时,可以先定位是哪一条没满足。第三条不满足(其实在做搬运),瓶颈在总线带宽;第一条不满足(其实在做顺序读),瓶颈在器件访问模型;第二条不满足(每次取指要走软件),瓶颈在主控配置而不是 Flash 本身。这三种情况的处置方向完全不同,混在一起谈「换颗快一点的 Flash」是最常见的误判。

还要先说清一件事:NOR 与 NAND 的差别不在「谁更快」,而在「访问模型不同」。NOR 的阵列结构允许任意地址独立读出,取指代价与地址是否连续无关;NAND 的读取以页为单位,页内可随机、页间必须按序把页内容搬进片内缓存。这条差别直接决定了 XIP 只有 NOR 能做。

维度路线一 直接内存映射路线二 搬运到 SRAM路线三 边搬边执行
取指是否来自 Flash是,CPU 直接对映射地址取指否,取指来自 SRAM部分来自 SRAM,按块切换
对主控的硬件要求必须有支持串行总线取指的存储控制器只需普通 SPI/QSPI 从机控制器只需普通控制器,但要能并行做 DMA 搬运
对 Flash 容量与速度的敏感度极高:带宽不够直接表现为取指停顿低:只影响搬运时间中:影响搬运窗口内的执行供给
SRAM 用量可以极小(仅栈与少量数据)必须大于等于镜像大小只需一个块大小(常见 8 ~ 32 KB)
代码是否必须重定位必须做绝对地址编译或链接脚本重定向可以按固定 SRAM 地址编译必须可重定位,但可按块链接
启动时间量级最低,受总线带宽支配最高,等于搬运时间 + 执行时间介于两者之间,接近搬运时间
代码加密 / 保密性Flash 明文暴露在总线上,可被读出Flash 可加密,加密后执行的是明文 SRAMFlash 可加密,暴露窗口小
典型适用场景有 QSPI/OPI 取指能力的主控 + 中小镜像所有 MCU(最低门槛的通用做法)镜像较大但 SRAM 又不够的中等场景
三条 XIP 实现路线的取指链路对照:数据从哪里来、瓶颈在哪一级路线一 · 直接内存映射主控 MMUFlash 起始地址映射到窗口取指事务串行总线x1 / x4 / x8SPI NOR任意地址直接取指瓶颈:总线带宽与单次事务固定开销路线二 · 搬运到 SRAM主控 CPUbootloader只做搬运整块搬运串行总线x1 / x4 / x8SPI NORSRAM 满后才跳转瓶颈:搬运时间 = 镜像大小 / 有效带宽路线三 · 边搬边执行主控 CPUbootloader建立搬运窗口DMA / 中断 双线程推进串行总线仅搬运未执行段SPI NOR取指与搬运重叠瓶颈:搬运窗口内的供给是否跟得上三条路线的差别,一句话各自说清① 路线一:Flash 就是指令内存。硬件最省,软件最贵——重定位、加密、镜像布局全都落在链接脚本与 bootloader 上。② 路线二:Flash 只是数据源。硬件零门槛,代价是启动时间被完整搬运一遍,且 SRAM 容量必须够。③ 路线三:用一块 SRAM 窗口把「搬运」与「执行」重叠起来,是 SRAM 不够时的折中,工程复杂度最高。本文后续所有带宽公式都按路线一的取指链路建立——它是唯一把总线性能直接暴露给 CPU 的路线,也是最需要性能论证的一条。
图 1 · XIP 三条实现路线的取指链路对照

1.2 路线一:控制器直接内存映射

这条路线的硬件特征很明确:主控的存储控制器知道「这段地址对应一颗串行 Flash」,CPU 的取指与数据访问会被硬件翻译成串行总线事务,软件完全看不见这条总线。它的性能上限由三件事决定:总线宽度与时钟、器件的首字节延迟、主控发起一次读事务的固定开销。

映射要素工程含义设计时必须确认的点
窗口起点与大小Flash 在主控地址空间里的位置与长度是否与 SRAM、 peripherals 冲突;镜像变大后是否需要重划窗口
地址对齐粒度CPU 一次访问被翻译成多大粒度的总线事务过小则事务数爆炸,过大则浪费带宽;常见粒度为 16 ~ 64 B
读事务的发出方式每次取指单独发起,还是由硬件预取合并有无预取缓冲决定随机小读与顺序读的差距有多大
cache 属性映射区是否可缓存、是否写回可缓存则随机取指几乎无感;不可缓存则每个 cache line 都走总线
时序寄存器组的配置顺序模式位、dummy 周期、连续读开关的生效次序顺序错误会表现为「偶发首字节错」,见第 3.4 节与第 11 章
不可读区间的行为未映射或超范围地址的响应是返回全 1、返回总线错误,还是挂死——决定故障可诊断性
「支持 XIP」这句话必须落到三行字上

在设计指南与料号文档里,凡是写「支持 XIP」,都必须同时写清三件事:① 映射窗口的对齐粒度与 cache 属性;② 初始化必须写入的模式位与 dummy 周期(写「按 datasheet 建议值配置」等于没写);③ 在该主控上实测的首次取指延迟与顺序读有效带宽。

只写频率不写这三项,读者无法判断自己的系统能不能用;评审时也拿不出可复算的依据。

同一镜像、同一主控:三条路线到「第一条有效指令执行完成」的耗时分解(算例)0481216累计耗时 →(单位:毫秒)路线一 直接 XIP2.91.14.0 msFlash 取指栈与数据路线二 全量搬运10.72.112.8 ms读 Flash写 SRAM路线三 边搬边执行2.28.51.011.7 ms首块就绪后续块搬运尾部执行算例前提(全部为可改的行业经验值,以实测为准)镜像 512 KB · 总线 x4 @ 104 MHz SDR · 按第 6.3 节公式得顺序读有效带宽 49.7 MB/s · SRAM 写带宽按 240 MB/s 估读 Flash 10.7 ms = 512 KB / 49.7 MB/s · 写 SRAM 2.1 ms = 512 KB / 240 MB/s · 两者串行相加即为路线二路线三没有把搬运与执行完全藏起来:CPU 在窗口外的取指仍会短暂停顿,所以它不是「免费」的并行,只是把停顿压到了首块之后的几微秒量级。这条曲线在不同主控上差异极大,务必在自己板子上实测。结论方向:路线一的时间由「执行的代码量」决定,路线二/三的时间由「镜像大小」决定——镜像越大,差距越明显。
图 2 · 三条 XIP 路线的启动时间分解对照(512 KB 镜像算例)

1.3 路线二:bootloader 搬运到 SRAM 再跳转

这条路线的唯一优势是硬件门槛为零:任何 MCU 都能做,代价是启动时间被完整搬运一遍支配。它的性能公式非常直白:

搬运路线启动时间 约等于 固定开销(初始化 + 校验) + 镜像字节数 / 有效读带宽 + 镜像字节数 / SRAM 写带宽

约束项典型量级工程含义
SRAM 容量门槛必须 ≥ 镜像大小 + 栈 + 数据 + 缓冲常见 512 KB 镜像需要 512 KB 以上 SRAM,嵌入式 MCU 常常给不起
分块搬运的块大小8 ~ 64 KB(取决于 SRAM 余量与中断延迟要求)块越小则中断/搬运切换越频繁,块越大则首字节等待越长
校验开销CRC32 约 1 ~ 3 GB/s,SHA-256 约 0.1 ~ 0.5 GB/s需要安全启动时,哈希校验的耗时可能与搬运本身同量级
解密开销AES-CTR 约 0.1 ~ 1 GB/s(依主控是否有硬件加速)无硬件加速时,解密会成为新的第一瓶颈
首字节就绪时间首个块搬完即可跳转,典型 50 ~ 300 µs这条路线的「快速启动」能力只体现在首块上
路线二什么时候仍然是对的

三种情况下继续用全量搬运是明智的:① 主控没有串行总线取指能力,方案里本来就没有第二条路;② 镜像很小(几十 KB)且 SRAM 充裕,搬运时间被固定开销主导,差距不明显;③ 需要在执行前完整校验并解密整段镜像——安全启动通常要求「验证通过才执行」,这天然要求整段落地。

反过来,如果镜像已经涨到几百 KB 而 SRAM 只有一两百 KB,路线二就变成了必须分块的分时搬运,此时应当认真评估路线三。

1.4 路线三:bootloader 边搬边执行(XIP-like)

路线三的核心思想是:用一块小窗口 SRAM 做「当前执行区」,搬完一块就跳过去执行,同时在后台搬下一块。它把路线二的「搬运时间」与路线一的「执行时间」重叠起来,理想情况下总耗时接近两者中的较大值。

设计要素取值 / 做法踩坑点
窗口大小一个链接单元的大小,常见 8 ~ 32 KB窗口太小则跳转与中断开销占比上升;太大则首字节等待变长
搬运与执行的互斥手段双 bank 交替、双缓冲、或者单 bank 内做前后指针同一 bank 边写边读会破坏正在执行的代码,必须做区域隔离
跳转前的地址重定位每个链接单元内相对寻址,单元入口做绝对跳转跨单元的函数调用与中断向量需要特殊处理
中断处理中断向量表放在常驻区,且不依赖被覆盖的窗口向量表被覆盖会表现为「跑一阵就崩」,且难以复现
搬运失败的处理校验失败时停在当前单元并给出可诊断状态最常见的现场问题是「不校验、失败就跳」,最后变成偶发死机
并行度搬运用 DMA / 硬件传输,执行用 CPU若主控只有单总线且 DMA 与取指抢同一控制器,并行度会低于预期
路线三最危险的失败模式

典型症状是「大部分时候正常,偶发死机,且死机点不固定」。根因几乎总是同一个:搬运覆盖了正在执行的代码区或它依赖的数据。三个必查项:

① 单元边界与链接脚本是否严格一致(链接单元大小必须与窗口步进严格相等);② 中断向量与常驻数据是否真的放在永不覆盖的区域;③ 跳转前是否校验了当前单元、且校验覆盖的是「跳转目标地址」而不是「拷贝源地址」。

1.5 三条路线的启动时间对照

把三条路线放在同一张表上对照,结论列已经足够写进设计指南:

对比项路线一 直接 XIP路线二 全量搬运路线三 边搬边执行
启动时间支配项执行的代码量与总线带宽镜像大小 / 有效带宽max(搬运时间, 执行时间) + 窗口切换开销
512 KB 镜像算例约 4 ms 量级约 13 ms 量级约 12 ms 量级
镜像增大到 2 MB几乎不变(只随执行量略增)线性增长到 50 ms 量级线性增长到 45 ms 量级
SRAM 需求几百字节 ~ 数 KB≥ 镜像大小一个窗口大小
硬件门槛高(需总线取指能力)无低(需 DMA)
对总线宽度的敏感度极高:x1→x8 接近 8 倍较高:x1→x8 接近 8 倍较高但被窗口切换摊薄
对 dummy 周期的敏感度高(直接影响每次取指的固定开销)中(每次事务的 dummy 被平均到 256 B 数据上)中
代码可重定位要求必须不需要必须(按窗口)
选型结论怎么写

把三条路线写进设计指南时,建议直接给决策规则而不是给描述:

① 主控有 QSPI/OPI 取指能力且镜像 ≤ 512 KB → 优先路线一,因为此时 SRAM 搬运带来的时间收益远小于实现复杂度收益。② 主控无取指能力或需要先完整校验解密 → 路线二,这是唯一稳妥选择。③ 镜像 > 512 KB 且 SRAM 不足 25% 镜像 → 路线三,并且必须按 1.4 节的三个必查项逐条验证。

无论选哪条,都必须在同一块板子上把「镜像大小 / 有效带宽」这个除法算一遍并实测验证——这是唯一能在评审会上站得住的性能论证。

2. SPI NOR 基础读时序与延迟构成

第 1 章把路线定下来了,接下来要看清「一次读指令到底贵在哪」。本章把一次 Read 命令拆到 SCK 级别,得到的结论会贯穿全文:随机小读慢的原因不在带宽,而在固定开销。

2.1 一次 Read 命令的完整开销拆解

一次普通的 Read 事务由四段组成,缺一不可:指令(1 B)、地址(3 B 或 4 B)、dummy 周期(0 ~ 16 个 SCK,随代际变化)、数据(可编程长度)。前三段与数据量无关,在带宽账里必须单独扣出来。

一次读事务的帧结构与固定开销:前四段里只有第四段与数据量有关帧结构(以 4 字节地址的 Fast Read 为例,x4 模式)MOSI指令 8 bitMOSI地址 32 bitMOSIdummy 4~16 SCKMISO数据 N × 8 bitCS# 有效窗口 = 指令 + 地址 + dummy + 数据固定开销与有效载荷的比例:N 越小,浪费越大固定开销 3.6 µs 的构成:指令 + 地址 + dummy 共 48 SCK 约等于 0.46 µs + 器件首字节延迟 约等于 0.6 µs + 主控发起一次读事务 约等于 2.5 µs。
图 3 · 一次读事务的帧结构与固定开销拆解

把这三段折算成时间(x4 @ 104 MHz 算例,见 6.3 节完整代入过程):

分段占多少 SCK折算时间随数据量变化吗谁能优化它
指令8 个 SCK / 1 B约 77 ns否不能改,是协议固定成本
地址32 个 SCK / 4 B约 308 ns否(只随地址位数变)地址由 3 B 改 4 B 只在 >128 Mb 才必要
dummy 周期4 ~ 16 个 SCK(随代际/模式)约 38 ~ 154 ns否换代际器件、或在器件允许范围内取最小值
器件首字节延迟不含 SCK约 0.4 ~ 1.0 µs否换器件(阵列访问与输出启动更快)
主控发起一次读事务不含 SCK约 1 ~ 5 µs否换主控 / 改用连续读 / 用 DMA 链式搬运
数据传输N × 8 SCKN / 有效线速是(正比于 N)唯一能靠加带宽改善的一段
整个文档最重要的一句结论

在一次事务只搬几十字节的场合,前五项合计 1 ~ 5 µs,而搬 64 字节本身只要 64 × 8 / (104e6 × 4) 约等于 1.2 µs。也就是说一半以上的时间花在了「什么都不传」的开销上。

这解释了第 2.3 节要回答的问题,也解释了为什么连续读、DTR、器件 cache 三项技术全部指向同一个目标:把固定开销摊到更多字节上。

2.2 各类延迟的量级表

把启动与运行期间会遇到的延迟归成六类。设计指南里的性能章节,建议直接引用这张表的「量级」列。

延迟类别典型量级(经验区间)出现在哪个阶段对启动的影响
CE# 建立到 SCK 启动数十 ns ~ 数百 ns每次事务可忽略,但频繁翻转会累积
指令 + 地址 SCK 时间0.1 ~ 1 µs(随频率与模式)每次事务频率越高,这一段的绝对时间越短
dummy 周期数十 ns ~ 1 µs每次事务同上;DTR 下按双沿计,SCK 数可能翻倍而时间不变
器件首字节延迟0.4 ~ 1.5 µs每次事务随机取指的固有代价,连续读可摊薄
片内页切换 / bank 切换数十 ns ~ 数百 ns跨页或跨 bank 时大容量多 bank 器件上更明显
主控总线周转数十 ns ~ 数百 ns事务之间GPIO 复用切换或控制器重新配置时出现
主控发起一次读事务1 ~ 5 µs(软件/寄存器/DMA 配置)每次事务本轮讨论中最大的单项,常被低估
主控 cache 未命中时的整条取指链2 ~ 10 µs每个 cache line决定「慢启动」是不是总线问题
时钟准备(PLL 锁定 + 稳压环)100 µs ~ 数 ms上电到第一条指令之前常是启动时间的真正大头
器件上电延时(POR)数十 µs ~ 数百 ms(依器件与温度)上电低温时显著变长,必须按最大值设计
模式切换(切回读模式、dummy 重配)数十 µs写操作之后写后紧跟读的代码段会吃到这段延迟
这张表怎么用

把三类延迟分开对待,是本章的核心方法:

① 与总线频率成正比、可被频率优化掉的:SCK 时间、总线周转;② 与频率无关、只能靠「减少次数」摊薄的:指令与地址、dummy、首字节延迟、主控发起开销;③ 只在上电时出现一次的:时钟准备与器件 POR。

第 3 步的判定尤其重要:如果启动时间的实测值主要落在第三类上,那么再换快的 Flash 也不会有任何改善,这是设计评审上一个非常值得先问的问题。

2.3 为什么「随机小读」比「顺序大读」慢一个量级

现在可以正面回答这个问题了。设一次事务的固定开销为 T_fix,数据量为 N,理论线速为 B_th(单位 B/s),则有效带宽为:

有效带宽 B_eff = N / ( T_fix + N / B_th )  折算效率 eta = B_eff / B_th = 1 / ( 1 + T_fix · B_th / N )

数据量 N数据传输时间固定开销占比有效带宽 B_eff相对顺序读的效率
16 B0.31 µs92%约 4.1 MB/s8%
64 B1.23 µs75%约 13.2 MB/s27%
256 B4.92 µs42%约 30.0 MB/s60%
1 KB19.7 µs15%约 44.0 MB/s88%
4 KB78.8 µs4.3%约 49.7 MB/s99.6%
4 KB 连续读(一次事务)78.8 µs4.5%约 49.5 MB/s99.5%

这张表用同一组参数算出三件事:

  • 16 B 的随机读只有 4.1 MB/s,是 4 KB 顺序读的 1/12——这就是「慢一个量级」的准确出处,它不是带宽不够,是事务太小。
  • 数据量每翻四倍,效率就上一个台阶;从 256 B 到 4 KB 只差 1.66 倍,但从 16 B 到 4 KB 差 12 倍。所以「提升有效带宽」的第一杠杆是「把事务做大」,第二杠杆才是「把总线做快」。
  • 连续读在这一档几乎没有额外收益(49.5 对 49.7 MB/s)。这是常见误解的来源:连续读的收益主要出现在更小的总线配置上,下一节给出它真正起作用的条件。
有效带宽随事务长度的变化:横轴为对数刻度,固定开销占比随长度快速下降0102030405016 B64 B256 B1 KB4 KB8 KBMB/s横轴:每次事务搬运的字节数 N(对数刻度)T_fix 3.6 µs(x4 实测量级)T_fix 1.2 µs(连续读摊薄后)T_fix 8.0 µs(每事务由软件发起)16 B 随机读约 4.1 MB/s4 KB 顺序读约 49.7 MB/s读图要点:三条曲线在 N 足够大时几乎重合——说明「大块顺序读」测不出软件层的开销差异;要暴露主控发起开销,必须用小事务的随机读去测。这也是为什么「用拷大文件测 Flash 带宽」永远测不出主控的问题。
图 4 · 有效带宽随事务长度的变化(三档固定开销对比)
由此得到一条测试纪律

禁止用「顺序拷贝一个大文件」的结果来评估启动性能。这类测试在 N ≥ 64 KB 时已经进入效率饱和区,测出来的是器件与总线的能力,而启动阶段执行的是零散的小事务,两者可以相差十倍以上。

正确的测法见第 10 章:按「复位 → 第一条有效指令」的口径,用 GPIO 翻转打点,测出三段耗时分别落在哪。

2.4 指令与 dummy 周期的代际对照

dummy 周期是「指令与地址之后、数据之前插入的空 SCK」,用来覆盖器件内部把地址转成行列地址所需的时间。它的数量由器件内部架构决定,不由主控决定,因此同一颗器件在不同模式(x1/x4/x8、SDR/DTR)下 dummy 数可能不同。

代际 / 模式典型时钟(经验区间)地址字节dummy 周期(经验区间)说明
早期 x1(单线读)20 ~ 50 MHz3 B0 ~ 8 SCK地址转换简单,dummy 少甚至为 0
x4 快速读(SDR)50 ~ 104 MHz3 B / 4 B4 ~ 8 SCK四线并行后 dummy 略增以覆盖内部并行化
x8 DTR 八线双沿133 ~ 200 MHz4 B8 ~ 16 SCK(双沿)dummy 数常按双沿计,实际时间与 x4 同量级
x4 DTR 四线双沿80 ~ 133 MHz3 B / 4 B6 ~ 10 SCK带宽介于 x4 SDR 与 x8 SDR 之间
高性能 x8 DTR(二代)166 ~ 250 MHz4 B10 ~ 20 SCK(双沿)内部架构更复杂,dummy 相应增加
dummy 写错的三种典型后果

① 偏少:第一个数据字节(或前几个字节)被丢掉 / 被前一次事务的残留污染,表现为「偶尔头几个字节错」,且与温度、时钟漂移相关,极难复现。

② 偏多:数据整体后移若干字节,表现为「读出来的东西偏移固定字节数」,这个反而容易发现。

③ 模式切换后没同步更新:从 x4 切到 x8 之后仍用旧的 dummy,表现为「同一段代码在两种模式下结果不同」。

规范做法:把 dummy 周期作为器件与模式组合的表项写进配置流程,并在模式切换后强制重写一遍,而不是依赖上电默认值。

最后强调一次本文的数值纪律:上面所有频率、dummy 数、延迟都来自行业经验区间,用于建立量级概念与做快速估算。任何进入原理图 BOM、时序表或软件配置的数值,必须以正式 datasheet 的时序图与实测为准。这条边界在附录 D 有完整说明。

3. 连续读模式

连续读(Continuous Read,也叫 Sequential Read / AutoBoot 家族)是 SPI NOR 里性价比最高的一项技术:它不增加任何引脚、不提高任何频率,只靠「让器件自己递增地址」就把固定开销从每事务一次降到每次传输一次。

3.1 连续读的收益本质:省掉每 256B 的指令与地址开销

普通读命令的语义是「从地址 A 读 N 字节」,命令结束。下一次读必须重新给指令和地址。而连续读把语义改成「从地址 A 开始,一直读下去,直到我打断你」——器件内部有一个地址计数器,读完一段就自己加一段,主控不用再发指令。

同样搬 4 KB:逐次发指令 vs 一次连续读,差别在固定开销被摊了几次逐次发指令:16 次事务指令 48 SCK数据 256 B固定开销第 1 次84104104第 2 次84104104第 3 次84104104第 4 次重复到第 16 次固定开销被支付 16 次;每次只有 256 B 数据摊它连续读:1 次事务,地址自动递增指令 + 地址 + dummy(仅一次)连续数据流 4 KB(CS# 保持有效)内部自动翻页主控只需给首地址与总长度,之后不用再发指令固定开销只支付 1 次,被 4 KB 数据摊薄代价:期间不能插入别的指令;任意地址跳转要重新发指令有效带宽对照(x4 @ 104 MHz,T_fix = 3.6 µs)逐 256 B 发指令约 30.0 MB/s连续读 4 KB约 49.5 MB/s
图 5 · 连续读的本质:把固定开销从「每事务一次」降到「每次传输一次」
维度普通读(每次重新给地址)连续读(器件自动递增)工程影响
指令开销每事务一次指令 + 地址 + dummy每次连续读序列只付一次事务越多、每事务越短,差距越大
地址开销每事务一次完整地址只有首地址由主控给出省掉的是 SCK 时间,不是延迟时间
主控侧开销每事务都要配置一次读事务配置一次,后续只收数据这一项往往是省得最多的
对事务长度的要求任意长度都可越长的连续序列收益越大长序列对写保护状态切换更敏感
打断能力随时可以发新指令需要先发「退出连续读」再发别的指令见 3.4 节的终止条件
适用场景随机取指、随机查表顺序取指、大块数据读取、镜像下载启动阶段两种都要用到
连续读的收益随总线配置单调上升

这一点非常反直觉,值得单独强调:总线越快,固定开销占比越高,连续读的相对收益越大。

在 x1 @ 50 MHz 上,48 个 SCK 的指令开销约 1 µs,而主控发起一次事务的软件开销可能 2 ~ 5 µs——连续读把后者省掉,收益巨大。到了 x8 DTR @ 200 MHz,48 个 SCK 只剩 0.24 µs,占比可以忽略,连续读能省的只剩下软件侧那一份。

所以从「投入产出」看,连续读是高总线配置下的高性价比项,低总线配置下相对收益有限。但它的实现成本几乎为零,理由充分,所以无论什么配置都应该开。

下图与上表给出同一组数字:搬 4 KB 数据时,逐 256 B 发指令要付 16 次固定开销,合计 16 × 3.6 = 57.6 µs;连续读只付一次 3.6 µs(固定开销取 x1 @ 50 MHz 的保守值,不随位宽与频率折算,各档统一沿用)。数据传输时间两者相同(4096 / 52 = 78.8 µs)。于是有效带宽分别为 30.0 MB/s 与 49.5 MB/s,差 1.65 倍。

配置事务次数(搬 4 KB)固定开销合计数据传输时间有效带宽相对普通读的提升
x1 @ 50 MHz(线速 6.25 MB/s)16 次约 57.6 µs655.4 µs约 5.74 MB/s1.10 倍
x4 @ 104 MHz(线速 52 MB/s)16 次约 57.6 µs78.8 µs约 30.0 MB/s1.65 倍
x8 DTR @ 200 MHz(线速 400 MB/s)16 次约 57.6 µs10.2 µs约 60.1 MB/s约 4.9 倍
上表的提升倍数为什么随线速单调上升

提升倍数等于连续读带宽除以逐 256 B 普通读带宽。固定开销按 x1 保守取值、不随线速缩短,而数据传输时间随线速成比例缩短——总线越快,固定开销占总时间的比例越高,连续读摊掉的开销份额越大,所以提升倍数从 x1 档的 1.10 倍一路升到 x8 DTR 档的约 4.9 倍。换句话说:总线越快,连续读越重要。

模式位把「指令 + 地址 + dummy + 数据宽度」打包成一组语义,配置一次、长期生效上电后的配置顺序(寄存器组职责,不涉及具体位域)① 解除写保护先让状态/配置寄存器组可写② 设定模式位总线宽度、DTR、dummy 档位③ 设定连续读进入隐式寻址的读循环④ 恢复写保护锁回,避免运行期误改常见模式位组合及其对应的读行为(数值为经验区间,以 datasheet 为准)x1 单线读线速1 bit/周期dummydummy 最少适用起步与调试阶段;带宽最低x4 四线读线速4 bit/周期dummydummy 中等适用通用嵌入式主流配置x4 DTR 四线双沿线速8 bit/周期dummydummy 按双沿计适用中高速方案,板级约束较松x8 DTR 八线双沿线速16 bit/周期dummydummy 最多适用最高带宽;需要 DQS 与严格布线关键约束:模式位一旦改动,dummy 周期必须同步重写;本文只讲寄存器组职责与配置顺序,具体位域与取值指向 IDE 生成的器件头文件。
图 6 · 模式位组合与上电配置顺序

3.2 模式位(Mode Bits)的常见组合

「模式位」这个词在不同厂商文档里指代略有差异,但实质都是一组决定「后续读命令如何解释总线」的寄存器位:总线宽度、单双沿、dummy 档位、是否连续读。本文只讲它作为寄存器组职责的那一层。

寄存器组职责决定什么何时必须配置配错的表现
模式位(Mode Bits)后续读命令使用几根线、单沿还是双沿切换总线宽度或双沿方式之前读回数据全错或全 0xFF,且与模式相关
dummy 周期配置读命令中插入多少空 SCK每次模式位变更后必须同步重写首字节错、固定偏移、偶发错误
连续读控制是否进入隐式寻址的读循环进入顺序读之前;任何其他指令之前先退出指令被吞、后续读错位、偶发死机
状态寄存器组(含写保护位)是否可写、是否处于擦除/编程中、是否异常写操作之前;每次启动时清零写入静默失败、状态永远忙
器件识别与参数区容量、地址位数、型号特征上电初始化时读一次并校验容量判断错误、地址截断
配置区(一次性可写)保护位、启动方式等出厂配置产测或特殊需求时按需修改不可恢复,需专用解锁序列
本文为什么只写「职责 + 顺序」不写位域

寄存器位域位置与选项字节默认值属于具体料号的数据手册内容,且不同厂商、不同代际之间没有统一定义。写进一份通用技术文档只会带来两个后果:读者照抄到不同料号上直接出错;文档一升级就过时。

正确做法:文档写清「有哪些寄存器组、各自负责什么、配置顺序如何、配置错了什么表现」,位域与取值指向 IDE 生成的器件头文件与对应 datasheet 的寄存器表。本文全篇遵守这一纪律。

模式组合总线宽度传输沿典型线速(@峰值时钟)dummy 相对量板级约束等级
x1 单线1 bit单沿50 MHz → 6.25 MB/s最少低:普通 SPI 布线即可
x4 四线4 bit单沿104 MHz → 52 MB/s中等中:注意 IO 串阻与长度匹配
x4 四线 DTR4 bit双沿133 MHz → 133 MB/s中等偏多中:需关注采样点与串阻
x8 八线8 bit单沿104 MHz → 104 MB/s较多中高:八根等长线,DQS 可选
x8 八线 DTR8 bit双沿200 MHz → 400 MB/s最多高:需 DQS/DQS# 与严格阻抗控制

3.3 AutoBoot 与隐式寻址的连续读

「AutoBoot」这一族功能(不同厂商命名不同,含义一致)的思路是:把一段固定区域(通常是 Flash 开头的一小段空间)的读循环在出厂时或配置时就设定好,上电后器件自动进入该循环并持续输出其中的内容。主控甚至不需要发读指令,只需要按时钟收数据。

特性隐式寻址连续读(模式位方案)AutoBoot(自动启动方案)
谁发起主控先发一条模式设置或读指令,之后器件自行维持上电即处于该状态,主控可零指令启动
起始地址由主控在指令里给出出厂固定或配置区指定
长度由主控控制(发新指令或拉高 CS# 结束)通常固定为一个窗口大小
适合的镜像位置任意,按需设置通常是固定偏移,适合放一段引导代码
对主控的依赖需要主控支持连续读(有些主控不支持)只需要主控能收数据,取指链路要求最低
主要风险退出顺序写错导致后续指令被吞配置区被误改后难以恢复,量产需管控
软件侧配合需要连续读的驱动与退出序列读取到窗口末尾后的行为依赖器件约定
AutoBoot 适合什么、不适合什么

适合:只需要在复位后第一时间喂给 CPU 一小段引导代码(比如一个「模式设置 + 复制到 SRAM」的小 loader),主控的取指链路还没有准备好时的场景。此时它能把「第一条取指」的成本压到只有 SCK 时间。

不适合:需要灵活切换镜像、需要多个镜像并存、需要热更新启动链路的场景。因为它的起点与长度在出厂或配置期就固定了,灵活性为零,一旦配置区写坏往往需要专用解锁序列才能恢复。

3.4 连续读的终止条件与注意事项

进入连续读之后,器件处于「只认数据、不认指令」的状态。这是它最大的价值,也是它最容易出事的地方。退出顺序必须严格按下表执行。

终止方式操作序列适用场景失败时的表现
拉高 CS#在 SCK 的下一个空闲沿拉高片选,器件退出读循环最通用;主控打算发新指令前下次发指令无响应,需重新初始化
发显式退出指令在数据流中插入约定的退出码(无效指令)要求 CS# 保持低、需连续传输多个区域时退出码被判为数据,位置错位
写入模式位先解除写保护,再写模式寄存器把连续读关掉要在不拉高 CS# 的情况下切换到写操作时写操作被忽略,状态位一直不对
复位硬件复位或软件复位器件异常兜底,不适合正常流程启动时间显著变长
软件约定长度主控收满约定字节数后自行停止长度固定的场景(如一段镜像)多收或少收,取决于约定是否与器件一致
连续读的五条纪律

① 任何非读指令之前必须先退出连续读,包括写状态寄存器、写模式位、擦除、编程、以及读 ID 这类「看起来也是读」的指令——很多器件要求显式退出。

② 退出后建议空读一次(发一条无效指令),把总线上残留的字节冲掉,避免下一条真指令的头几个 bit 被污染。这一条在高频下尤其重要。

③ 不要在中断里发新指令。若连续读期间允许中断且中断服务程序要访问 Flash,必须在中断入口显式退出、出口重新进入,代价很高;更好的做法是关中断期间完全不访问 Flash。

④ CS# 拉高的时机要对齐 SCK 空闲沿。在 SCK 高电平中间拉高会触发器件内部状态机的边界情况,表现为「偶尔一次退出不干净」。

⑤ 模式位与 dummy 必须成对更新。连续读的 dummy 与普通读的 dummy 常常不同档,切换时要一起改。

最后补一条器件层面的注意事项:连续读期间器件内部输出驱动器持续驱动总线。如果此时主控的总线上还有其他设备(多片并挂、或者有别的从设备共用),必须确保片选划分清晰,避免总线争用导致电平不确定。多片并挂时,连续读要么每片独立片选,要么严格设计成链式传递(前一片的输出接到后一片的输入,不并联)。

4. DTR 与 Octal:双沿传输

前三章讲的是「怎么把固定开销摊薄」,从本章开始讲另一条路径:把总线本身变宽、变快。这条路线的收益上限很高,但代价全部落在板级约束上——本章与第 9 章必须连着读。

4.1 单沿 SDR 到双沿 DDR 的本质区别

SDR(Single Data Rate)每个时钟周期只在一个边沿采样数据;DDR(Double Data Rate)在上升沿和下降沿各采样一次。就这一个改动,带宽立刻翻倍,但对时序的要求也立刻翻倍。

同一颗器件、同一条总线:单沿每个周期传 1 bit,双沿每个周期传 2 bit单沿 SDR:每周期 1 bitSCKDO8 个周期传 8 bit;上升沿采样,数据保持到下一周期双沿 DTR:每周期 2 bitSCKDO同样 8 个周期传 16 bit;上升沿与下降沿各采样一次为什么 DTR 对布线更苛刻① 采样窗口减半:SDR 每个周期有半个周期用于建立与保持,DTR 只剩四分之一,数据与 DQS 的相位容限约减半。② 边沿对准要求:SCK 与数据在同一封装内共用引脚,封装内互连长度与回流路径差异会直接变成相位误差。处置:按 x8 DTR 的时序图留足建立保持与 DQS 相位裕度,串阻与拓扑方案见第 9 章。
图 7 · 单沿 SDR 与双沿 DTR 的时序对照
对比项单沿 SDR双沿 DDR工程含义
每周期传输位数总线宽度 × 1总线宽度 × 2DDR 是带宽翻倍的直接原因
采样时刻每个周期只有一个稳定采样点每周期两个采样点,均需满足建立/保持采样窗口减半,相位容限约减半
数据有效时间接近半个周期约四分之一个周期走线长度偏差与抖动容限显著变紧
对时钟抖动的要求相对宽松严格(抖动直接吃掉建立/保持余量)PLL 与时钟源的品质成为关键
是否需要 DQS通常不需要高速 DTR 通常需要多一根差分对与一个额外引脚
板级仿真要求常规 SI 仿真可覆盖需做时序通道仿真见第 9 章
典型适用x1 / x4 SDR 中低速配置x4 / x8 DTR 高速配置按线速需求与板级能力取舍

4.2 DTR(Dual Transfer Rate)如何把带宽翻倍

带宽公式里的「每周期传输位数」在 DTR 下直接乘 2。这个倍数是严格的、无条件的——不依赖任何数据压缩、缓存技巧或协议优化,是物理层面的收益。这也是它比连续读更「硬」的地方。

理论带宽 B_th = 总线宽度(bit) × 时钟频率(Hz) × 每周期沿数 / 8 (单位 MB/s)

配置总线宽度时钟(经验区间)每周期沿数理论带宽(区间)器件侧约束
x1 SDR120 ~ 50 MHz12.5 ~ 6.3 MB/s最少;dummy 也最少
x4 SDR450 ~ 104 MHz125 ~ 52 MB/s四线等长;中等 dummy
x4 DTR480 ~ 133 MHz280 ~ 133 MB/s需要相位对齐;dummy 增加
x8 SDR850 ~ 104 MHz150 ~ 104 MB/s八线;引脚压力大
x8 DTR8166 ~ 250 MHz2332 ~ 500 MB/s需 DQS;SI 要求最高
不要把「器件最高频率」当成「你的系统能达到的频率」

datasheet 上的时钟上限是在特定条件下测得的:指定电压范围、指定温度、指定的走线长度与负载、指定的时序余量。板子做出来之后,能不能跑到这个上限取决于你的板级 SI 能不能满足同一组条件。

所以在设计指南里,「最高频率」这一栏的正确写法是一个条件化表述:例如「x8 DTR 下推荐 200 MHz,条件为 VCC 在 2.7 ~ 3.6 V、温度 -40 ~ 85 °C、DQS 与 DO 走线长度差 ≤ 5 mm、单端串阻 33 欧(容差 5%)」。这类表述能让读者判断自己的板子是否落在条件范围内。

4.3 Octal(八线)DDR 的 IO 组织与引脚代价

Octal / OPI(Octal Parallel Interface)把数据线从 4 根扩到 8 根,再加上 DQS/DQS#,引脚数量与布线复杂度都是一次跃升。这不是为了「带宽」而带宽——它是为了在不继续提高时钟频率的前提下把带宽做上去。

信号组x1 方案x4 方案x8 DTR 方案说明
数据线1 根(DO/DI 复用)4 根(D0~D3 双向)8 根(DQ0~DQ7 双向)双向意味着每个方向都要单独做阻抗与串阻设计
时钟1 根 SCK1 根 SCK1 根 CK + DQS + DQS#DQS 是给数据用的采样参考,与 CK 不同源或同源视设计而定
片选1 根 CS#1 根 CS#1 根 CS#(有时另有扩展脚)片选数量往往不够,需要软件或硬件扩展
其它必需脚VCC / GNDVCC / GNDVCC / VCC / GND八线方案的电流与去耦要求明显更高
封装引脚量级8 ~ 1616 ~ 2424 ~ 40+大封装会挤占 PCB 面积并增加焊接与返修难度
PCB 层数与布线2 层可应付2 ~ 4 层建议 4 ~ 6 层八根等长线在 2 层板上极难做
八线方案的真正代价不在引脚数

引脚数只是账面。真正的代价有三条:

① 电流与去耦:八根数据线同时翻转时的峰值电流比四线大一倍多,电源跌落直接抬高读时序的不确定性(详见 9.4 节);② 布线约束:八根 DQ 加一对 DQS 的长度匹配与阻抗一致性,是本系列文档里最严苛的一组要求;③ 主控支持度:很多 MCU 的 QSPI 控制器只支持四线,Octal 需要额外的控制器或专门的引脚复用配置,选型阶段就要确认。

4.4 x1 / x2 / x4 / x8 模式与理论带宽表

把四种总线宽度与两种沿数组合成一张完整的理论带宽表。这张表是第 6 章算例的基础,建议直接引用。

模式线/周期沿/周期位/周期50 MHz104 MHz133 MHz200 MHz
x1 SDR1116.3 MB/s13.0 MB/s16.6 MB/s25.0 MB/s
x2 SDR21212.5 MB/s26.0 MB/s33.3 MB/s50.0 MB/s
x4 SDR41425.0 MB/s52.0 MB/s66.5 MB/s100.0 MB/s
x4 DTR42850.0 MB/s104.0 MB/s133.0 MB/s200.0 MB/s
x8 SDR81850.0 MB/s104.0 MB/s133.0 MB/s200.0 MB/s
x8 DTR8216100.0 MB/s208.0 MB/s266.0 MB/s400.0 MB/s
这张表怎么用:先定线速需求,再反查模式与时钟

典型的反推流程:① 先从启动时间需求算出需要的线速(例如「4 KB 镜像必须在 1 ms 内取完」→ 需要 4 MB/s 以上);② 再扣除固定开销,得到实际需要的理论带宽(除以约 0.8 的折算效率);③ 查表选模式与时钟,并且优先用「加宽总线」而不是「提时钟」来补足带宽——因为提时钟会同时抬高板级约束,而加宽总线只是多几根线与更多引脚。

只有当主控与板级条件都支持、且确实需要 200 MB/s 以上线速时,才值得上 x8 DTR。

相关报告 · 交叉引用 2 器件全部展开收起 ▾
点开类目即可展开:具体文档 / 章节(点章直接跳转到该章)
SPI NOR
电路设计指南
软件设计规范
Linux 驱动开发
样机问题排查
量产问题排查2
系统设计指南
eMMC
电路设计指南
软件设计规范
Linux 驱动开发
样机问题排查
量产问题排查