SPI NAND 块保护(BP)功能设计方案
编制日期 2026-09-21 | 版本号 Rev 1.0
从 4 位 BP / TB / WP-E 机制、上电默认整片保护、分区规划,到驱动命令、WP# 引脚与量产加锁时机的完整落地方案
- 文中寄存器位名、保护档位、命令码取自主流 SPI NAND 通用架构(如 W25N 一类),用于讲清机制;你在做的料号必须以 XTX 正式 datasheet 为准,尤其是 BP 位数、TB 极性、WP-E 与 SRP 组合表、是否存在 SR3。
- SPI NAND 与 SPI NOR 的 BP 机制不同源(默认值、TB 极性、WP# 语义、命令码都不一样),不要互相套用。NOR 侧请看同系列《SPI NOR 块保护(BP)功能设计方案》。
- 涉及 OTP-L / SR1-L 非易失写 1 / WP# 固定下拉 的操作不可逆,必须在小批量验证通过、量产 SOP 冻结之后再执行。
一句话结论:SPI NAND 的 BP 最反直觉的有两点:一是上电默认整片保护,新料号拿来烧录第一反应往往是「芯片不良」,其实只是没发解锁;二是TB 极性与 NOR 相反、还多了一个决定「是否禁用 Quad」的 WP-E 位。只要记住「第一件事读 SR-1、先解锁再烧、WP-E 保持 0 以保留 Quad」,NAND 的 BP 比 NOR 反而更省心。
这份文档解决什么
块保护(Block Protect,BP)是 SPI NAND 内部的一道低成本防护:它给地址空间画一条线,让跨越这条线的擦除和编程命令被静默忽略。正因为它「静默」,做错的时候往往不报错——你以为烧进去了,其实芯片早把命令丢了。
本分册只讲 SPI NAND:先讲清楚它「上电默认整片保护」这个与 NOR 完全相反的事实,再拆解 SR-1(保护寄存器)里的 4 位 BP、TB 方向、WP-E 模式选择,然后给出分区怎么规划、WP# 怎么接、驱动命令(1Fh + 寄存器地址)怎么发、产线在哪一步加锁、加锁之后 OTA 怎么办,最后是速查表与设计核查清单。
定位「为什么烧不进去」的故障排查请看同系列《写保护误触发_SR_BP位_量产排查》;SPI NOR 与并行 NOR(PPI NOR)的保护机制完全不同源,各有独立分册。
1. BP 保护的本质:它锁住的是命令,不是数据
在动手配寄存器之前,先接受一个事实:BP 生效时芯片不报错。理解这一点,后面所有的验证方法都要围绕「回读校验」而不是「看有没有报错」来设计。
1.1 BP 锁的是命令,不是数据
BP 生效时,芯片不会拒绝你的命令、也不会报错——它照常接收地址和数据,然后在内部判断「这段地址在保护区内」,于是把这次擦除或编程直接丢弃。所以 BP 配置错误最典型的现场表现不是报错,而是「烧录工具显示成功,回读却是旧数据」。
BP 只在芯片内部拦住擦写命令,它不加密数据、不做鉴权、也不阻止读出。任何人把芯片拆下来接到编程器上,只要能改状态寄存器,保护就能被解除。需要保密性请配合 OTP 区与 UID 加密方案,需要防拆请考虑物理防护。
1.2 三层防护,缺一层就等于没锁
| 层次 | 由谁决定 | 挡住什么 | 挡不住什么 |
|---|---|---|---|
| 第 1 层 · 区域锁 | SR-1 的 BP[3:0] / TB | 对保护区内地址的 Page Program、Block Erase、Chip Erase 命令 | 对状态寄存器本身的写入 |
| 第 2 层 · 寄存器锁 | SR-1 的 SRP1 / SRP0,SR-2 的 SR1-L | 在软件层面改写保护配置(即「先解锁再擦」这条路) | 硬件引脚被拉到允许电平的情况 |
| 第 3 层 · 硬件锁 | WP# 引脚电平 + SR-1 的 WP-E 位 | 在板状态下的一切软件解锁尝试 | 把芯片拆下来单独烧录 |
很多原理图把 WP# 留成 NC 或直接拉到 VCC,认为「反正不接就是没保护」。实际上 WP# 悬空会让引脚电平在噪声下抖动,保护状态随机翻转;而固定拉到可写电平,则意味着任何软件都能解锁 BP,第 1 层锁形同虚设。详见第 5 章的三种接法。
1.3 上电默认态:NAND 是整片保护
SPI NAND 上电 / 出厂后 BP[3:0] 处于「整片保护」编码、TB 与 SRP 取默认值,也就是整片只读、SR-1 不可随意改写。这是一个「默认保守」的设计:好处是防误擦,坏处是产线拿来第一件事必须发解锁流程,否则根本烧不进去。
SPI NAND 上电默认 整片保护,SPI NOR 上电默认 无保护。两者方向完全相反。团队用 NOR 调通后换 NAND,第一反应通常是「料号不良 / 虚焊」,实际只是没发解锁命令。反过来从 NAND 换到 NOR,则要警惕「以为有保护、其实一片没锁」。
2. 寄存器地图:SR-1 与 SR-2 里与保护相关的位
NAND 只有两个寄存器参与保护(SR-1 管区域、SR-2 管锁与 OTP),比 NOR 的 3 个寄存器更精简,但命令码必须带寄存器地址。
2.1 两个寄存器怎么读、怎么写
| 寄存器 | 读命令 | 写方式 | 与保护相关的内容 |
|---|---|---|---|
| SR-1(保护寄存器) | 0Fh + Axh 后读 | 1Fh + Axh + 1 字节 | BP[3:0] / TB / WP-E / SRP1 / SRP0 |
| SR-2(配置寄存器) | 0Fh + Bxh 后读 | 1Fh + Bxh + 1 字节 | BUF / ECC-E / SR1-L / OTP-E / OTP-L |
SPI NAND 不像 NOR 那样用 05h / 01h 直接读写状态寄存器,而是先发 0Fh(读)或 1Fh(写),再发寄存器地址(Axh / Bxh / Cxh),最后才是数据。漏掉寄存器地址这一步,命令会被静默丢弃,现象和「芯片锁死」一模一样。NOR 与 NAND 的命令码不要混用。
2.2 每个位的一句话解释
| 位 | 所在寄存器 | 类型 | 一句话 |
|---|---|---|---|
| BP[3:0] | SR-1 bit4:1 | 非易失 | 保护范围档位;0000 = 无保护,101X / 11XX = 全片保护 |
| TB | SR-1 bit5 | 非易失 | 方向:0 = 保护高地址端,1 = 保护低地址端(与 NOR 相反) |
| WP-E | SR-1 bit6 | 非易失 | 模式:0 = 软件模式(Quad 可用),1 = 硬件模式(Quad 禁用) |
| SRP1 / SRP0 | SR-1 bit7 / bit0 | 非易失 | 寄存器锁级别:软件 / 上电锁定 / OTP 保护三种强度 |
| SR1-L | SR-2 bit5 | 一次性(OTP) | 把 SR-1 当前保护配置永久固化,不可逆 |
| OTP-E | SR-2 bit6 | 易失 | 进入 OTP 访问模式,才能读写 OTP 区与 Unique ID |
| OTP-L | SR-2 bit7 | 一次性(OTP) | 锁定 OTP 区(典型 10 页 × 2 KB),之后只读,不可逆 |
| ECC-E | SR-2 bit4 | 非易失 | ECC 使能;影响读路径,配置保护时顺带确认 |
| BUF | SR-2 bit3 | 非易失 | 数据缓冲模式选择,与保护无关但写 SR 时同字节处理 |
| WEL | SR-1(内部) | 易失 | 写使能锁存,每次写 SR / 擦 / 写前都要重新发 06h |
构造要写入的 SR-1 字节时,WEL 位不参与——写 SR 指令本身会自动置位。把目标值写成常量(如 0x1C)是对的;若先读回 SR 再改位,记得把无关位屏蔽后回填,避免把读到的「脏位」凑进目标字节。
2.3 容量与块结构:1 Gb 典型架构
主流 1 Gb SPI NAND(如 W25N01GV)通常组织为 1024 个 block,每块 128 KB = 64 页 × 2 KB。保护档位以「block 数量」为刻度,所以后面所有档位表都按 1024 块来算。换更大或更小的容量时,档位比例不变,但每块对应的绝对地址会变,分区边界要重新换算。
3. BP 机制与 WP-E 总开关
NAND 的 BP 有 4 位、默认整片保护、TB 极性与 NOR 相反,还多了一个决定「软硬件模式 + 是否禁用 Quad」的 WP-E 位。
3.1 把 BP 想成一把从某一端量起的尺子
TB 决定从哪一头量,BP[3:0] 决定量多长。两者必须一起算,只看 BP 四个位一定会算错——尤其 TB 极性与 NOR 相反。
| 位 | 作用 | 取值含义 |
|---|---|---|
| BP[3:0] | 保护范围 | 0000 = 无保护;101X / 11XX = 全片保护(见 3.2 表) |
| TB | 方向 | 0 = 从高地址端起算;1 = 从低地址端起算 |
| WP-E | 模式 | 0 = 软件模式(Quad 可用);1 = 硬件模式(Quad 禁用、WP# 控锁) |
3.2 保护档位速查(1 Gb / 1024 块 × 128 KB 架构)
| TB | BP[3:0] | 保护块范围 | 保护容量 | 占整片比例 |
|---|---|---|---|---|
| X | 0000 | — | 0 | 无保护 |
| 0 | 0001 | 1022 ~ 1023 | 256 KB | 高 1/512 |
| 0 | 0010 | 1020 ~ 1023 | 512 KB | 高 1/256 |
| 0 | 0011 | 1016 ~ 1023 | 1 MB | 高 1/128 |
| 0 | 0100 | 1008 ~ 1023 | 2 MB | 高 1/64 |
| 0 | 0101 | 992 ~ 1023 | 4 MB | 高 1/32 |
| 0 | 0110 | 960 ~ 1023 | 8 MB | 高 1/16 |
| 0 | 0111 | 896 ~ 1023 | 16 MB | 高 1/8 |
| 0 | 1000 | 768 ~ 1023 | 32 MB | 高 1/4 |
| 0 | 1001 | 512 ~ 1023 | 64 MB | 高 1/2 |
| 1 | 0001 ~ 1001 | 对称的低地址端 | 同上 | 低 1/512 ~ 低 1/2 |
| X | 101X | 0 ~ 1023 | 128 MB | 全片保护 |
| X | 11XX | 0 ~ 1023 | 128 MB | 全片保护 |
注意档位的跳跃性:最小档是 1/512(256 KB),然后直接跳到 1/256、1/128……想保护 384 KB,只能往上取整到 512 KB,多出来的 128 KB 会连累相邻分区。这是分区规划必须提前对齐的原因。
3.3 WP-E:软硬件模式的总开关,也是性能开关
WP-E=0(软件保护模式,推荐):WP# 与 HOLD# 复用为 IO2 / IO3,Quad 编程与读取全程可用,SR-1 的写入由 SRP 位控制。绝大多数应用跑在这个模式。
WP-E=1(硬件保护模式):WP# 与 HOLD# 变成专用控制引脚,所有 Quad 功能被禁用。此时 WP# 拉到 GND,芯片的整片(含状态寄存器、存储阵列、OTP 区)进入只读;WP# 接 VCC 时才允许改 SR-1。
SPI NAND 多用作启动介质,Quad 读取速度通常是 Standard SPI 的 3~4 倍。把 WP-E 置 1 意味着读固件也要降回单线,对于从 NAND 直接 XIP 或整包加载的方案,启动耗时可能翻倍。决策顺序建议:先确认能不能接受单线启动,再决定要不要开硬件锁。折中做法是 WP-E=0 + SRP 软件锁 + WP# 由 GPIO 控制(第 5 章)。
3.4 OTP 区与 SR1-L:NAND 上的不可逆手段
| 手段 | 位置 | 作用 | 可逆性 |
|---|---|---|---|
| OTP-E | SR-2 bit6 | 进入 OTP 访问模式,才能读写 OTP 区与 Unique ID / 参数页 | 易失,可反复切换 |
| OTP-L | SR-2 bit7 | 锁定 OTP 区(典型 10 页 × 2 KB),之后只读 | 不可逆 |
| SR1-L | SR-2 bit5 | 把 SR-1 当前的保护配置永久固化,上电默认值即为锁定值 | 不可逆 |
SR1-L 不是想写就能写。必须:① 先把 SR-1 的 BP/TB/SRP 配置成最终目标值 → ② 把 SRP1,SRP0 设为 (1,1) → ③ 置 OTP-E=1 进入 OTP 访问模式 → ④ 执行写状态寄存器把 SR1-L 写 1 → ⑤ 回读确认。任何一步顺序错了,写入会被忽略,而你可能会误以为已经锁定成功。
4. 保护分区规划:先有布局,才有编码
BP 是按整片比例划线的,不是按任意地址划线。分区布局必须提前去适配 BP 档位,否则只能在「多保护一点」和「改布局」之间二选一。
4.1 从分区表反推 BP 编码的六步法
- 列出完整分区表:偏移、大小、是否可写、更新频率(OTP 一次 / OTA 偶尔 / 日志频繁)。
- 标出「必须只读」的分区:Bootloader、校准参数、SN/MAC、密钥。日志与文件系统不在此列。
- 检查它们在地址空间上是否连续、且紧邻某一端。这是 BP 能否成立的前提。
- 计算需保护的总容量占比,向上取整到最近的 BP 档位(3.2 表)。
- 选 TB(方向):要保护低地址端取 TB=1,高地址端取 TB=0。
- 核算溢出:取整后多出来的容量是否吃掉了相邻的可写分区?吃掉就必须回到第 1 步改布局。
4.2 小范围保护换算(Bootloader 在低地址端,TB=1)
NAND 没有 CMP 位,不能像 NOR 那样用 CMP=1 反转语义去锁「对侧一小段」。但它档位更细(最小 1/512),锁一段低地址的小 Bootloader 反而比 NOR 容易:
| BP[3:0] | TB=1 时保护容量 | TB=1 时保护位置 | 典型用途 |
|---|---|---|---|
| 0001 | 256 KB | 低地址端 256 KB | 参数区 / 校准值 |
| 0010 | 512 KB | 低地址端 512 KB | 小型 Bootloader + 参数 |
| 0011 | 1 MB | 低地址端 1 MB | Bootloader + 双份参数表 |
| 0100 | 2 MB | 低地址端 2 MB | 含 Recovery 的启动区 |
| 0101 | 4 MB | 低地址端 4 MB | 大固件启动区 |
| 1001 | 64 MB | 低地址端 64 MB | 半片固化(少见) |
4.3 两端都要保护怎么办(方案 C 的两难)
双备份 OTA 的典型布局是:Boot 在低地址、参数区在高地址,中间两个 APP 槽轮流写。而 BP 只能表达从一端量起的连续区间,「低地址一小段 + 高地址一小段」这种两端需求,单套 BP 表达不了。四条出路:
| 方案 | 做法 | 优点 | 代价 / 风险 |
|---|---|---|---|
| ① 调整布局(推荐) | 把参数区搬到 Boot 旁边,合并成一段连续保护区;两个 APP 槽放后面 | 一套 BP 搞定,无需运行时切换 | 要改动分区表与链接脚本,OTA 兼容需处理 |
| ② 运行时动态切换保护 | 平时锁 Boot;需要写参数时由特权代码临时解开、写完立刻恢复 | 布局不用改 | 解锁窗口期有风险;掉电可能停在解锁态,需上电自检兜底 |
| ③ 参数区改用 OTP | 一次性写入 SN / MAC / 校准值,OTP-L 锁定 | 不占 BP 档位,且不可逆更安全 | 参数只能写一次,后续无法升级;OTP 容量小 |
| ④ 放弃保护,改软件校验 | 参数区双备份 + CRC/序列号,读出时校验,坏了用备份恢复 | 零硬件依赖 | 挡不住恶意改写,只防意外损坏 |
能改布局就改布局(①)。布局冻结的项目,参数类小数据走 OTP(③),大数据走软件校验(④)。运行时动态切换(②)是下下策——它引入了一个「保护暂时失效」的时间窗,而这个窗口恰好是最容易被掉电打断的时刻,真要用就必须配套上电自检与恢复逻辑。
4.4 保护粒度与 OTA 的冲突
OTA 升级时要擦写 APP 槽,而 BP 的保护区是非易失的——上电就在,不会因为你在跑 OTA 就自动消失。设计时必须确认:OTA 目标地址完全落在保护区之外。一种隐蔽的失败是:分区表改过一次(APP 槽变大了),但 BP 档位没跟着调,于是新固件的尾部地址落进保护区,OTA 显示成功、重启后却是半成品。
把「分区表变更后重新核算 BP 编码」写进变更流程。任何一次分区大小调整、新增分区、固件体积增长超过档位边界,都要回到 4.1 的六步法重算一遍。这个动作不做,问题会在几个月后的某次 OTA 才暴露,且难以复现。