SPI NOR 块保护(BP)功能设计方案
编制日期 2026-09-21 | 版本号 Rev 1.0
从 BP/TB/SEC/CMP 四个位、保护分区规划、WP# 引脚设计,到驱动实现与量产加锁时机的完整落地方案
- 文中寄存器位名、保护档位、命令码取自主流 SPI NOR 通用架构(如 W25Q / MX25 / GD25 一类),用于讲清机制;你在做的料号必须以 XTX 正式 datasheet 为准,尤其是 BP 位数、TB 极性、是否存在 CMP 与 WPS 位。
- SPI NOR 与 SPI NAND 的 BP 机制不同源(默认值、TB 极性、WP# 语义都不一样),不要互相套用。NAND 侧请看同系列《SPI NAND 块保护(BP)功能设计方案》。
- 涉及 OTP / SRL 非易失写 1 / 永久锁定 的操作不可逆,必须在小批量验证通过、量产 SOP 冻结之后再执行。
一句话结论:SPI NOR 的 BP 不是「把三个位写进去」这么简单,而是分区规划 → 档位换算 → 引脚设计 → 驱动时序 → 产线加锁时机五件事的串联。其中最容易翻车的是档位换算:CMP=0 时能保护的最小范围是 1/2,想只锁 64 KB 的 Bootloader,必须先把 CMP 置 1 反转语义——而这个反转本身就是「清 BP 反而锁死整片」事故的来源。
这份文档解决什么
块保护(Block Protect,简称 BP)是 SPI NOR 里成本最低、也最容易被做错的一道防护。它不加密、不鉴权,只是在芯片内部给地址空间画一条线,让跨越这条线的擦除和编程命令被静默忽略。正因为它「静默」,做错的时候往往不报错——你以为写进去了,其实芯片早就把命令丢了。
本分册只讲 SPI NOR:从 SR-1/SR-2/SR-3 三个状态寄存器里与保护相关的位讲起,把 BP / TB / SEC / CMP 四个位怎么联合决定保护区说透,再给出分区怎么规划、WP# 怎么接、驱动怎么写、产线在哪一步加锁、加锁之后 OTA 怎么办,最后是速查表与核查清单。
定位「为什么写不进去」的故障排查请看同系列《写保护误触发_SR_BP位_量产排查》;SPI NAND 与并行 NOR(PPI NOR)的保护机制完全是另一套,各有独立分册。
1. BP 保护的本质:它锁住的是命令,不是数据
在动手配寄存器之前,先要接受一个事实:BP 生效时芯片不报错。理解这一点,后面所有的验证方法都要围绕「回读校验」而不是「看有没有报错」来设计。
1.1 BP 锁的是命令,不是数据
BP 生效时,芯片不会拒绝你的命令、也不会报错——它照常接收地址和数据,然后在内部判断「这段地址在保护区内」,于是把这次擦除或编程直接丢弃。所以 BP 配置错误最典型的现场表现不是报错,而是「烧录工具显示成功,回读却是旧数据」。
BP 只在芯片内部拦住擦写命令,它不加密数据、不做鉴权、也不阻止读出。任何人把芯片拆下来接到编程器上,只要能改状态寄存器,保护就能被解除。需要保密性请配合 OTP 区与 UID 加密方案,需要防拆请考虑物理防护。
1.2 三层防护,缺一层就等于没锁
| 层次 | 由谁决定 | 挡住什么 | 挡不住什么 |
|---|---|---|---|
| 第 1 层 · 区域锁 | SR-1 的 BP[2:0] / TB / SEC,SR-2 的 CMP | 对保护区内地址的 Page Program、Sector/Block Erase、Chip Erase 命令 | 对状态寄存器本身的写入 |
| 第 2 层 · 寄存器锁 | SR-1 的 SRP0 + SR-2 的 SRL | 在软件层面改写状态寄存器(即「先解锁再擦」这条路) | 硬件引脚被拉到允许电平的情况 |
| 第 3 层 · 硬件锁 | WP# 引脚电平 + SR-3 的 WPS 位 | 在板状态下的一切软件解锁尝试 | 把芯片拆下来单独烧录 |
很多原理图把 WP# 留成 NC 或直接拉到 VCC,认为「反正不接就是没保护」。实际上 WP# 悬空会让引脚电平在噪声下抖动,保护状态随机翻转;而固定拉到可写电平,则意味着任何软件都能解锁 BP,第 1 层锁形同虚设。详见第 6 章的三种接法。
1.3 上电默认态:NOR 是无保护
SPI NOR 出厂 / 上电后 BP[2:0] = 000、TB = 0、SEC = 0、CMP = 0、SRP0 = 0,也就是整片可擦写、SR 随时可改。这是一个「默认开放」的设计:好处是产线拿来就能烧,坏处是保护必须靠后续工位主动去写——漏了这一步,整批产品裸奔,而外观和功能测试全都正常,发现不了。
SPI NAND 上电默认 整片保护,SPI NOR 上电默认 无保护。两者方向完全相反。团队用 NOR 调通后换 NAND,第一反应通常是「料号不良 / 虚焊」,实际只是没发解锁命令。反过来从 NAND 换到 NOR,则要警惕「以为有保护、其实一片没锁」。
2. 寄存器地图:三个状态寄存器里与保护相关的位
BP 的复杂度不在命令,而在「哪几个位在联合起作用」。把这张位图看明白,后面所有计算才不会算错。
2.1 三个状态寄存器怎么读、怎么写
| 寄存器 | 读命令 | 写方式 | 与保护相关的内容 |
|---|---|---|---|
| SR-1 | 05h | 01h 的第一字节(或单字节 WRSR) | BUSY / WEL / BP[2:0] / TB / SEC / SRP0 |
| SR-2 | 35h | 01h 的第二字节(16-bit WRSR,31h / 01h 视料号) | SRL / QE / LB[3:1] / CMP / SUS |
| SR-3 | 15h | 01h 的第三字节(11h / 01h 视料号) | ADS / ADP / WPS / DRV[1:0] / HOLD·RST 复用选择 |
只想改 BP 位却只发了一个字节,或者第二个字节填了 0x00——很可能顺手把 QE 位清掉,芯片从 Quad 退回单线,表现为读取速度骤降、甚至 XIP 时序不满足而跑飞。正确做法是:先读回 SR-2 的当前值,只改目标位,其余位原样回填。
2.2 每个位的一句话解释
| 位 | 所在寄存器 | 类型 | 一句话 |
|---|---|---|---|
| BP[2:0] | SR-1 bit4:2 | 非易失 | 保护范围档位,000 = 无保护,111 = 全片保护 |
| TB | SR-1 bit5 | 非易失 | 保护方向:0 = 从低地址端起算,1 = 从高地址端起算 |
| SEC | SR-1 bit6 | 非易失 | 粒度:0 = 按 64 KB 块计,1 = 按 4 KB 扇区计 |
| CMP | SR-2 bit6 | 非易失 | 语义反转:1 = 保护区与开放区整体互换 |
| SRP0 | SR-1 bit7 | 非易失 | 寄存器锁使能:置 1 后 SR 的可写性受 WP# 控制 |
| SRL | SR-2 bit0 | 非易失(易失写可选) | 寄存器锁级别:置 1 后 SR 锁定;非易失写则不可逆 |
| WPS | SR-3 bit2 | 非易失 | WP# 语义选择:0 = 引脚模式,1 = 寄存器模式 |
| LB[3:1] | SR-2 bit5:3 | 一次性(OTP) | 安全寄存器(Security Register)锁定位,写 1 不可逆 |
| WEL | SR-1 bit1 | 易失 | 写使能锁存,每次写 SR / 擦 / 写前都要重新发 06h |
| BUSY | SR-1 bit0 | 只读 | 器件忙标志,写 SR 与擦写后必须轮询到 0 |
构造要写入的 SR 字节时,BUSY 与 WEL 位不参与——它们是只读或自动清零的。把目标值直接写死成 0x0C 这类常量是对的,但如果你先读回 SR 再改位,记得把 bit1/bit0 屏蔽掉再回填,否则可能把 WEL 位算进去,凑出一个错误的字节。
2.3 4 字节地址器件(> 128 Mb)的额外注意事项
容量大于 128 Mb 的器件需要进入 4 字节地址模式(或配合地址长度切换)才能访问高地址空间,此时要额外确认三件事:
- 保护档位表是否按新容量重算:同一 BP 编码在 16 MB 与 32 MB 器件上对应的绝对容量不同,档位比例不变但边界地址变了。
- 写 SR 命令的字节数是否变化:部分料号在 4 字节模式下写 SR 的指令码不同(如 01h / 3Eh 的区分),写错会被静默忽略。
- ADS / ADP 位(SR-3):决定上电后的默认地址长度与 4 字节指令是否启用,若配置不当,保护区的实际地址会偏移,出现「看着锁对了其实锁错位」。
3. 保护区怎么算:BP / TB / SEC / CMP 四把钥匙
NOR 的 BP 是一个「范围 + 方向 + 粒度 + 语义」的四维组合。只看 BP 三个位,一定会算错保护区。
3.1 把 BP 想成一把从某一端量起的尺子
TB 决定从哪一头量,SEC 决定刻度是 64 KB 还是 4 KB,BP[2:0] 决定量多长,CMP 决定「量到的部分被保护」还是「量到的部分反而开放」。四者必须一起算,只看 BP 三个位一定会算错。
| 位 | 作用 | 取值含义 |
|---|---|---|
| BP[2:0] | 保护范围 | 000 = 无保护;111 = 全片保护;中间档按比例递增(见 3.2 表) |
| TB | 方向 | 0 = 从低地址端起算;1 = 从高地址端起算 |
| SEC | 粒度 | 0 = 按 64 KB 块计;1 = 按 4 KB 扇区计(边界更精细) |
| CMP | 语义反转 | 0 = 正常;1 = 保护区与开放区整体互换 |
3.2 保护档位速查(CMP=0、SEC=0,通用规律)
| BP[2:0] | TB=0(保护低地址) | TB=1(保护高地址) | CMP=1 时的等效效果 |
|---|---|---|---|
| 000 | 无保护 | 无保护 | 全片保护 |
| 001 | 低 63/64 | 高 63/64 | 仅保护对侧 1/64 |
| 010 | 低 31/32 | 高 31/32 | 仅保护对侧 1/32 |
| 011 | 低 15/16 | 高 15/16 | 仅保护对侧 1/16 |
| 100 | 低 7/8 | 高 7/8 | 仅保护对侧 1/8 |
| 101 | 低 3/4 | 高 3/4 | 仅保护对侧 1/4 |
| 110 | 低 1/2 | 高 1/2 | 仅保护对侧 1/2 |
| 111 | 全片保护 | 全片保护 | 无保护 |
看上表就能发现:CMP=0 时你能保护的最小范围是 1/2——想只锁 Bootloader 那 64 KB 根本做不到,最小也会锁掉半个芯片。而 CMP=1 把语义反转,BP=001 就变成「只保护对侧 1/64」,这才是小范围保护的正确做法。代价是:配置顺序必须先清 CMP,再改 BP,否则你「清 BP」的动作反而会把整片锁死。
3.3 SEC 位:4 KB 粒度能救回多少精度
SEC=1 时保护边界按 4 KB 扇区而不是 64 KB 块对齐。在 CMP=1 + 小档位场景下,SEC=1 可以让你把保护区边界卡得更准;但在 CMP=0 + 大档位场景下,SEC 的影响可以忽略。判断标准很简单:
| 场景 | SEC 该取多少 | 理由 |
|---|---|---|
| 要保护的范围 ≥ 数 MB(比例档位) | SEC=0 即可 | 边界本来就在 64 KB 量级,4 KB 精度无意义 |
| CMP=1 保护几十~几百 KB | SEC=1 | 档位边界与真实分区边界的偏差可缩小到 4 KB 内 |
| 分区表按 4 KB 扇区对齐设计 | SEC=1 | 让分区边界与保护边界用同一套刻度 |
| 不确定 | SEC=1 | 代价几乎为零,精度只增不减(除非档位表对 SEC=1 有专门定义) |
部分料号在 SEC=1 时给出的是另一张档位表(因为最小单位变了)。不要假设「SEC 只影响边界精度、不影响档位比例」,拿到料号后要对着 datasheet 里的 Sector/Block Protection Table 核一遍。
4. 寄存器锁:SRP0 / SRL / WPS 与不可逆的 LB 位
只配 BP 不配寄存器锁,等于给门装了锁芯却把钥匙插在门上。这一章决定这套保护到底能挡住谁。
4.1 第 1 层锁管「哪些区域不能写」,第 2 层锁管「BP 位能不能被改」
如果只做了第 1 层,那么任何一段跑在设备上的代码——包括被攻破的应用固件——都可以先发 06h 再把 BP 清成 000,然后随意擦写启动区。第 2 层锁(SRP0 / SRL)就是用来堵这条路的。
| SRL | SRP0 | WP# 引脚 | 状态寄存器可写性 | 说明 |
|---|---|---|---|---|
| 0 | 0 | X(任意) | WREN 后可写 | 出厂默认:WP# 无控制作用,软件全权 |
| 0 | 1 | 低电平 | 锁定,不可写 | 硬件保护:需要 WP# 拉高才能改 SR |
| 0 | 1 | 高电平 | WREN 后可写 | 硬件未保护:仍需 WREN 才能写 |
| 1 | X | X | 锁定 | 易失写入 = 掉电解锁;非易失写入 = 永久锁定(OTP),不可逆 |
SRL 置 1 之后:如果是易失写入,掉电一次即可恢复,可以用来做「本轮上电期间禁止改保护」的临时锁;如果是非易失写入,则是一次性编程(OTP),永久不可逆。两者寄存器值完全一样,从回读结果上区分不出来——区别只在你发的是哪一条写命令。下达非易失写命令前必须确认:保护配置已经过完整验证、且未来 OTA 不需要再改保护区。
4.2 WPS:WP# 引脚到底听谁的
SR-3 的 WPS(Write Protect Select)位决定 WP# 引脚的语义来源,这是 SPI NOR 比 NAND 多出来的一个开关:
| WPS | 模式 | WP# 引脚的作用 |
|---|---|---|
| 0 | 引脚模式 | WP# 电平直接决定 SR 是否可写:拉低即锁 SR,拉高才允许(仍须先发 WREN) |
| 1 | 寄存器模式 | 由 SR 内部的 SRP0 / SRL 决定锁定状态,WP# 退居辅助或不生效 |
软件层面把 BP 清得再干净,只要 WP# 被拉低且 WPS=0,状态寄存器照样写不进去,现象和「芯片锁死」一模一样。在板烧录失败时,WP# 电平与 WPS 位是与 BP 同等优先级的排查项,而且量一个引脚电平比读寄存器还快。
4.3 安全寄存器(Security Register)与 LB 位
部分料号除了主阵列还提供若干安全寄存器(典型 256 B × 3),由 SR-2 的 LB[3:1] 三个位分别锁定。这三个位是一次性编程(OTP)的:写 1 之后对应安全寄存器永久只读,且该位本身也再也改不回来。
典型用途是存放设备唯一标识、出厂校准值、公钥指纹。它与 BP 的区别在于:BP 管的是主阵列的地址区间,LB 管的是独立的安全寄存器;LB 锁定的粒度是「整个安全寄存器」,不能按字节。
BP + CMP 锁住 Bootloader(可擦写区之外的启动代码),安全寄存器 + LB 锁住设备身份与密钥指纹,主阵列其余部分留给 APP 与文件系统。这样即使 APP 被完全攻破,攻击者既改不了启动链,也改不了设备身份。