4. Flash读写保护:读保护(RDP)级别与设置、写保护(WRP)配置、选项字节编程与修改、保护解除与全局擦除
Flash保护这个话题,说实话,很多工程师容易忽略。我早年做一款工业控制器时,就因为没设读保护,样机被客户“逆向”了个干净。从那以后,只要涉及产品量产,保护机制我一定会上。
Flash保护分两类:读保护(RDP) 和 写保护(WRP)。前者防别人读你的代码,后者防你自己(或异常程序)把关键区域擦写了。咱们一个一个说。
4.1 读保护(RDP)级别与设置
读保护,说白了就是给Flash上把锁。别人拿到芯片,想通过调试接口(SWD/JTAG)把固件读出来?没门。
STM32的RDP分三个级别,我习惯用这张表来对比:
| 级别 | 数值 | 保护状态 | 调试接口访问 | 从SRAM/System Memory启动 |
|---|---|---|---|---|
| Level 0 | 0xAA | 无保护 | 完全开放 | 允许 |
| Level 1 | 0xBB(或其他非0xAA/0xCC值) | 读保护开启 | 禁止读Flash,允许读写RAM/外设 | 允许,但Flash不可读 |
| Level 2 | 0xCC | 永久保护 | 完全禁止(调试接口永久失效) | 禁止 |
Level 1 是最常用的。你想想看,产品出厂时设成Level 1,别人用J-Link连上,读Flash直接返回全0或全1,代码安全就有了基本保障。
Level 2 是个狠角色。一旦设了,调试接口永久锁死,连你自己都救不回来。我只有在产品完全定型、绝不打算做任何现场调试时才会用。嗯,这里要注意:Level 2不可逆,选之前想清楚。
核心要点: RDP Level 1 是量产标配。Level 2 慎用,除非你确定这辈子不再需要调试接口。
4.2 写保护(WRP)配置
写保护防的是谁?防的是程序跑飞后把Bootloader区域给擦了。我在一个OTA项目里就遇到过——升级程序有个bug,直接把引导区覆盖了,设备变砖。从那以后,Bootloader区域我一定上WRP。
WRP的原理是按页(或按扇区)设置保护。配置时你需要指定:
- 起始地址(WRP_start)
- 结束地址(WRP_end)
- 保护使能位
以STM32F4为例,配置代码大致长这样:
// 假设保护扇区4到扇区7(地址范围0x08010000 ~ 0x0801FFFF)
FLASH_OB_WRPConfig(OB_WRP_Sector_4 | OB_WRP_Sector_5 |
OB_WRP_Sector_6 | OB_WRP_Sector_7, ENABLE);
// 别忘了启动选项字节编程
FLASH_OB_Launch();
写保护生效后,任何对该区域的写/擦操作都会被硬件拒绝。你想想看,就算程序跑飞了,它也动不了你的Bootloader,这就是最后一道防线。
我的习惯: 把Bootloader和关键配置参数所在的扇区全部加上WRP。应用区可以不加,方便后续OTA升级。
4.3 选项字节编程与修改
RDP和WRP的配置,最终都存储在选项字节(Option Bytes)里。选项字节是Flash里一块独立的区域,专门存放芯片的配置信息。
修改选项字节的流程,我总结为三步:
- 解锁Flash控制器(FLASH_Unlock)
- 解锁选项字节(FLASH_OB_Unlock)
- 编程并启动(FLASH_OB_Program + FLASH_OB_Launch)
注意:选项字节的修改需要重新上电或系统复位才能生效。FLASH_OB_Launch() 函数内部会触发一个复位,别被它吓到,这是正常行为。
我曾经犯过一个错:修改完选项字节后,直接读RDP寄存器,发现值没变。后来才意识到——没复位!复位后再读,就对了。
警告: 选项字节编程过程中,芯片绝对不能断电。一旦掉电,选项字节可能处于未定义状态,轻则保护配置丢失,重则芯片锁死。建议在编程前先确保供电稳定。
4.4 保护解除与全局擦除
保护不是永久的(Level 2除外)。如果你想解除Level 1的读保护,或者修改WRP的区域,需要执行全局擦除。
流程是这样的:
- 将RDP设置为Level 0(写入0xAA)
- 芯片会自动执行Mass Erase(整片擦除)
- 擦除完成后,所有保护配置清零,芯片回到无保护状态
为什么要整片擦除?这是硬件设计的安全策略——防止你通过修改RDP来绕过保护。你想想看,如果允许不擦除就降级保护,那读保护还有什么意义?
代码实现:
// 解除读保护(Level 1 -> Level 0)
FLASH_Unlock();
FLASH_OB_Unlock();
FLASH_OB_RDPConfig(OB_RDP_Level_0); // 写入0xAA
FLASH_OB_Launch(); // 触发复位,执行Mass Erase
执行完这段代码,芯片会擦除整个Flash(包括你的程序),然后复位。所以,解除保护意味着程序也没了,需要重新烧录。
避坑指南: 我曾经在生产线上遇到过一批芯片,RDP Level 1设好后,想通过调试器解除保护,结果一直报错。后来发现是调试器供电不稳,导致Mass Erase过程中断。解决办法:换了个带独立供电的调试器,一次成功。
4.5 知识结构总览
下面这张图,把Flash保护的整体逻辑串起来了。我建议你保存下来,调试时对照着看。
这张图把RDP、WRP、选项字节、保护解除的关系理清了。你调试时遇到保护相关的问题,先看这张图定位到哪个环节,再针对性排查。
调试小技巧: 如果调试器连不上芯片,先检查RDP级别。很多开发板出厂时RDP是Level 0,但如果你误操作设成了Level 1或Level 2,调试器就会“失联”。解决办法:用串口ISP模式(System Memory启动)重新配置选项字节。
Flash保护这块,说白了就是“防君子也防小人”。RDP防的是外部窃取,WRP防的是内部崩溃。两者配合使用,产品的固件安全才算有了基本保障。嗯,我建议你在项目初期就把保护方案定下来,别等到量产了再补,那时候改起来就麻烦了。