STM32芯片被读出固件的根本原因是RDP未正确设置:Level 0裸奔,Level 1可逆且能拦截99%量产攻击,Level 2永久锁死但不可恢复;用STM32CubeProgrammer连接后查Option Bytes中RDP字段,0xAA为Level 0、0x55为Level 1、0xCC为Level 2,若显示Unknown或读取失败则极可能已为Level 2。

STM32芯片被J-Link或ST-LINK读出固件,根本原因不是加密弱,而是RDP没设对——Level 0就是裸奔,Level 1可逆但已拦住99%的量产攻击,Level 2是真锁死,但锁完就再也连不上,别手抖。
怎么确认当前RDP级别(用STM32CubeProgrammer查)
调试器能连上不代表RDP无效,得看选项字节实际值。很多“连不上”其实是接线/供电问题,不是RDP生效了。
- 打开STM32CubeProgrammer,选择正确的接口(SWD/JTAG)和端口,点击Connect
- 连接成功后切到
Option Bytes标签页 - 找到
RDP字段:显示0xAA是Level 0(无保护),0x55是Level 1(可擦除恢复),0xCC是Level 2(永久锁死) - 注意:如果显示
Unknown或报错Failed to read option bytes,大概率已是Level 2,芯片拒绝返回任何选项信息
用命令行刷RDP Level 1(批量产线最稳的方式)
图形界面点错一次可能锁死一片,命令行加脚本才是量产标配。关键是加 -ob RDP=1 后必须跟 -ob WDG_SW=1(启用软件看门狗),否则整片擦除时可能卡死在擦除中途,变砖。
- 确保已安装
STM32_Programmer_CLI(v2.14+,旧版不支持部分F4/H7系列) - 执行命令:
STM32_Programmer_CLI -c port=SWD -ob RDP=1 -ob WDG_SW=1 -ob nRST_STOP=1 -ob nRST_STDBY=1 -
nRST_STOP和nRST_STDBY设为1,防止低功耗模式下调试复位失效导致误判 - 执行完立刻断电重启,不要点“Reset”,某些版本GUI Reset会跳过选项字节重载
为什么Level 1擦除后还是读不出代码?
整片擦除(mass erase)确实能解除Level 1,但前提是芯片没进“假死”状态——比如擦除中途断电、或Flash正在执行中被强制擦除,会导致选项字节区损坏,RDP残留为0x55但调试接口无法响应。
- 现象:
STM32_Programmer_CLI -c port=SWD -memunprotect返回Operation failed: Memory unprotection failed - 解决:先用
-hardreset强制复位,再试;还不行就换-c port=UART(需BOOT0拉高)走串口DFU方式擦除 - 真正风险不在Level 1本身,而在你用HAL库调用
HAL_FLASHEx_OBProgram()时没检查返回值:if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK)必须判断,否则失败静默,你以为设成功了
Level 2不是更安全?为什么不敢用
Level 2确实让J-Link识别不到内核,连SWD引脚都输出高阻态,但它把所有退路封死——没预留USB DFU、没留UART Bootloader、没做eFUSE备份方案,等于把钥匙焊死在锁芯里。
- 一旦固件有严重bug(比如看门狗配置错误导致无法启动),芯片只能报废
- 某些封装(如LQFP64)的SWDIO/SWCLK引脚同时复用为GPIO,Level 2后这些引脚彻底失去功能,可能影响外设初始化
- 真实产线经验:我们只在军工模块用Level 2,且每颗芯片烧录前都用
STM32_Programmer_CLI -c port=SWD -readunprotect预验证擦除通道是否通畅
RDP不是开关,是信任链起点。Level 1够用时别碰Level 2,而比RDP更常被忽略的是:你有没有在代码里清空调试寄存器?DBGMCU->CR = 0 这一行漏写,调试器仍可能在启动瞬间抓到RAM快照。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











