MCU Security
Allow opt bytes device selection
“allow opt. bytes” 设备选择仅适用于STM32F1系列设备。对于以后的设备,选项字节的内存映射编程是不可行的,因为对于某些系列设备,选项字节立即生效,这将导致在选项字节编程可以被验证之前,立即会失去与设备的连接(在启用读保护的情况下)。
STM32系列设备提供选项字节,允许对设备进行 “permanent” 配置和读保护。为了启用或禁用读保护,必须对STM32 MCU的特殊功能寄存器执行一系列多次读/写访问。对于STM32设备系列的每个子系列而言,这一系列的访问指令是不一样的,并在设备的相应参考手册中进行了描述。下面提供了启用或禁用STM32设备读保护的 J-Link commander 文件和 J-Flash 工程示例列表。请注意,所提供的文件是一个概念性的示例/证明。用户可以更改它们以适应其特定的用例,例如使用较小的超时时间、编程其他值等。
注意:
在连接调试探针的同时给设备设置"安全性",需要进行上电复位。
Disabling readout protection
J-Link Commander and J-Flash
J-Link Commander 和 J-Flash 会自动检测具有"安全性"的STM32设备,并询问用户是否应该解锁。有关这方面的更多信息,请点击此处:Secured_ST_device_detected
Flasher standalone mode
为了在独立模式下解锁STM32设备,需要在 J-Flash 工程的 init
步骤中配置解锁序列指令(见下表中的示例)。
Restoring factory defaults
独立软件工具 STM32 Unlock 可用于将STM32设备的 Option Bytes 重置为出厂默认设置。STM32 Unlock 是 J-Link software & documentation pack 的一部分。
Enabling readout protection
所有提供的 J-Link Commander 命令文件和 J-Flash 工程都将读保护设置为 level 1 (ROP == Level 1) 。为了设置 ROP Level 2,需要将值 “0xBB” 更改为 “0xCC” ,如 J-Flash 工程的命令文件 / Exit
步骤所示。请注意,ROP Level 2 是永久性的,SEGGER和ST都无法恢复。
Device Table
- 有关 J-Flash 中原生支持的更多信息,以及为什么不再为新设备实现原生支持,请参阅本文:MCU_Security_Options
注意:
- 如果设置了读保护并且调试器仍通过JTAG/SWD连接,则一些STM32设备需要上电复位。
- 所有命令文件和J-Flash工程都选择了特定的MCU。仅为了通过 J-Link commander 锁定设备,则无需更改设备名称。
但是,在使用 J-Flash 或在 J-Link commander 中进行任何 flash 烧写时,必须将设备名称更改为实际使用的设备。- 请注意,通过J-Link命令文件来设置设备的"安全性"是受到 “返回值解释”,“if / else 分支”等的限制的。这是行不通的。因此,只能使用J-Flash或J-Link SDK进行设备的生产烧写和安全性设置。
- 在任何情况下,用户都有责任在"烧录器"离开"生产设施"之前验证所需的读保护是否有效。
- 上表中提供的文件也可以用于更改所有其他用户选项字节,因为解锁和烧写它们的一般过程是相同的。
Option bytes
大多数STM32设备都带有选项字节,可以对其进行修改以影响设备行为,例如设置安全性(请参阅 MCU Security)。
- J-Link支持大多数STM32设备的直接地,内存映射选项字节编程。请注意,通常情况下,所有选项字节都必须一次性写入。
- 可以使用 STM32 Utility 将选项字节重置为出厂默认值(除非设备的安全性不允许恢复MCU)。
使用 J-Link Commander 来操作选项字节
以下示例用于擦除选项字节,也就是将读保护设为 level 1
,其它的均为出厂默认值。
device stm32f070rb
if 1
speed 1000
con
sleep 100
w4 0x40022004 0x45670123 // Unlock Flash registers
w4 0x40022004 0xCDEF89AB
w4 0x40022008 0x45670123 // Unlock Option Bytes
w4 0x40022008 0xCDEF89AB
w4 0x40022010 0x00000220 // Set Write and Erase bit to prepare Option Byte erase
w4 0x40022010 0x00000260 // Trigger operation (Option Byte erase)
sleep 1500 // It is not possible to check the Status register in a commander file, therefore we
sleep 1500 // just wait here a fixed amount of time
w4 0x40022010 0x00000020 // Reset Write bit
w4 0x40022010 0x00000000 // Reset Erase bit
w4 0x40022010 0x00000080 // Set Flash lock. This step and two previous steps cannot be combined.
sleep 1 // We do not actually write the ROP/nROP bytes, because erased (0xFF) state already sets ROP to Level 1
sleep 1500 // It is not possible to check the Status register in a commander file, therefore we
sleep 1500 // just wait here a fixed amount of time
w4 0x40022010 0x00002210 // Trigger Option Byte Loader
sleep 1500 // It is not possible to check the Status register in a commander file, therefore we
sleep 1500 // just wait here a fixed amount of time
q
使用 J-Flash 操作选项字节
以下示例用于擦除选项字节,也就是将读保护设为 level 1
,其它的均为出厂默认值。别看这个文件很长,您只需要关注其中的ExitStep
,也就是J-Flash 的退出步骤。
AppVersion = 61203
FileVersion = 2
[GENERAL]
ConnectMode = 0
CurrentFile = ""
DataFileSAddr = 0x00000000
GUIMode = 0
HostName = ""
TargetIF = 1
USBPort = 0
USBSerialNo = 0x00000000
[JTAG]
IRLen = 0
MultipleTargets = 0
NumDevices = 0
Speed0 = 4000
Speed1 = 4000
TAP_Number = 0
UseAdaptive0 = 0
UseAdaptive1 = 0
UseMaxSpeed0 = 0
UseMaxSpeed1 = 0
[CPU]
NumInitSteps = 1
InitStep0_Action = "Reset"
InitStep0_Value0 = 0x00000000
InitStep0_Value1 = 0x00000000
InitStep0_Comment = "Reset and halt target"
NumExitSteps = 23
ExitStep0_Action = "Read 32bit"
ExitStep0_Value0 = 0x4002201C
ExitStep0_Value1 = 0x00000000
ExitStep0_Comment = ""
ExitStep1_Action = "Var AND"
ExitStep1_Value0 = 0x00000000
ExitStep1_Value1 = 0x00000002
ExitStep1_Comment = ""
ExitStep2_Action = "Var BNE"
ExitStep2_Value0 = 0x00000014
ExitStep2_Value1 = 0x00000000
ExitStep2_Comment = "Flash already secured, lock not necessary"
ExitStep3_Action = "Write 32bit"
ExitStep3_Value0 = 0x40022004
ExitStep3_Value1 = 0x45670123
ExitStep3_Comment = "Unlock Flash registers"
ExitStep4_Action = "Write 32bit"
ExitStep4_Value0 = 0x40022004
ExitStep4_Value1 = 0xCDEF89AB
ExitStep4_Comment = ""
ExitStep5_Action = "Write 32bit"
ExitStep5_Value0 = 0x40022008
ExitStep5_Value1 = 0x45670123
ExitStep5_Comment = "Unlock Option Bytes"
ExitStep6_Action = "Write 32bit"
ExitStep6_Value0 = 0x40022008
ExitStep6_Value1 = 0xCDEF89AB
ExitStep6_Comment = ""
ExitStep7_Action = "Write 32bit"
ExitStep7_Value0 = 0x40022010
ExitStep7_Value1 = 0x00000220
ExitStep7_Comment = "Set Write and Erase bit to prepare Option Byte erase"
ExitStep8_Action = "Write 32bit"
ExitStep8_Value0 = 0x40022010
ExitStep8_Value1 = 0x00000260
ExitStep8_Comment = "Trigger operation (Option Byte erase)"
ExitStep9_Action = "Delay"
ExitStep9_Value0 = 0x00000000
ExitStep9_Value1 = 0x00000005
ExitStep9_Comment = ""
ExitStep10_Action = "Read 32bit"
ExitStep10_Value0 = 0x4002200C
ExitStep10_Value1 = 0x00000000
ExitStep10_Comment = ""
ExitStep11_Action = "Var AND"
ExitStep11_Value0 = 0x00000000
ExitStep11_Value1 = 0x00000001
ExitStep11_Comment = ""
ExitStep12_Action = "Var BNE"
ExitStep12_Value0 = 0x00000009
ExitStep12_Value1 = 0x00000000
ExitStep12_Comment = "Wait for busy bit to clear"
ExitStep13_Action = "Write 32bit"
ExitStep13_Value0 = 0x40022010
ExitStep13_Value1 = 0x00000020
ExitStep13_Comment = "Reset Write bit"
ExitStep14_Action = "Write 32bit"
ExitStep14_Value0 = 0x40022010
ExitStep14_Value1 = 0x00000000
ExitStep14_Comment = "Reset Erase bit"
ExitStep15_Action = "Write 32bit"
ExitStep15_Value0 = 0x40022010
ExitStep15_Value1 = 0x00000080
ExitStep15_Comment = "Set Flash lock. This step and the two previous steps cannot be combined."
ExitStep16_Action = "Delay"
ExitStep16_Value0 = 0x00000000
ExitStep16_Value1 = 0x00000005
ExitStep16_Comment = ""
ExitStep17_Action = "Read 32bit"
ExitStep17_Value0 = 0x4002200C
ExitStep17_Value1 = 0x00000000
ExitStep17_Comment = ""
ExitStep18_Action = "Var AND"
ExitStep18_Value0 = 0x00000000
ExitStep18_Value1 = 0x00000001
ExitStep18_Comment = ""
ExitStep19_Action = "Var BNE"
ExitStep19_Value0 = 0x00000010
ExitStep19_Value1 = 0x00000000
ExitStep19_Comment = "Wait for busy bit to clear"
ExitStep20_Action = "Write 32bit"
ExitStep20_Value0 = 0x40022010
ExitStep20_Value1 = 0x00002210
ExitStep20_Comment = ""
ExitStep21_Action = "Delay"
ExitStep21_Value0 = 0x00000000
ExitStep21_Value1 = 0x000007D0
ExitStep21_Comment = "Cannot read memory in order to check the busy bit, therefore fixed wait."
ExitStep22_Action = "Reset"
ExitStep22_Value0 = 0x00000000
ExitStep22_Value1 = 0x00000064
ExitStep22_Comment = ""
UseScriptFile = 0
ScriptFile = ""
UseRAM = 1
RAMAddr = 0x20000000
RAMSize = 0x00004000
CheckCoreID = 1
CoreID = 0x0BB11477
CoreIDMask = 0x0F000FFF
UseAutoSpeed = 0x00000001
ClockSpeed = 0x00000000
EndianMode = 0
ChipName = "ST STM32F070RB"
[FLASH]
aRangeSel[1] = 0-63
BankName = "Internal flash"
BankSelMode = 1
BaseAddr = 0x08000000
NumBanks = 1
[PRODUCTION]
AutoPerformsErase = 1
AutoPerformsProgram = 1
AutoPerformsSecure = 0
AutoPerformsStartApp = 0
AutoPerformsUnsecure = 0
AutoPerformsVerify = 1
EnableTargetPower = 0
EraseType = 2
MonitorVTref = 0
MonitorVTrefMax = 0x0000157C
MonitorVTrefMin = 0x000003E8
OverrideTimeouts = 0
ProgramSN = 0
SerialFile = ""
SNAddr = 0x00000000
SNInc = 0x00000001
SNLen = 0x00000004
SNListFile = ""
SNValue = 0x00000001
StartAppType = 0
TargetPowerDelay = 0x00000014
TimeoutErase = 0x00003A98
TimeoutProgram = 0x00002710
TimeoutVerify = 0x00002710
VerifyType = 1
以下示例用于解除读保护,也就是将读保护设为 level 0
,其它的均为出厂默认值。别看这个文件很长,您只需要关注其中的ExitStep
,也就是J-Flash 的退出步骤。
AppVersion = 61203
FileVersion = 2
[GENERAL]
ConnectMode = 0
CurrentFile = ""
DataFileSAddr = 0x00000000
GUIMode = 0
HostName = ""
TargetIF = 1
USBPort = 0
USBSerialNo = 0x00000000
[JTAG]
IRLen = 0
MultipleTargets = 0
NumDevices = 0
Speed0 = 4000
Speed1 = 4000
TAP_Number = 0
UseAdaptive0 = 0
UseAdaptive1 = 0
UseMaxSpeed0 = 0
UseMaxSpeed1 = 0
[CPU]
NumInitSteps = 22
InitStep0_Action = "Read 32bit"
InitStep0_Value0 = 0x4002201C
InitStep0_Value1 = 0x00000000
InitStep0_Comment = ""
InitStep1_Action = "Var AND"
InitStep1_Value0 = 0x00000000
InitStep1_Value1 = 0x00000002
InitStep1_Comment = ""
InitStep2_Action = "Var BEQ"
InitStep2_Value0 = 0x00000018
InitStep2_Value1 = 0x00000000
InitStep2_Comment = "Flash not secured, unlock not necessary"
InitStep3_Action = "Write 32bit"
InitStep3_Value0 = 0x40022004
InitStep3_Value1 = 0x45670123
InitStep3_Comment = "Unlock Flash registers"
InitStep4_Action = "Write 32bit"
InitStep4_Value0 = 0x40022004
InitStep4_Value1 = 0xCDEF89AB
InitStep4_Comment = ""
InitStep5_Action = "Write 32bit"
InitStep5_Value0 = 0x40022008
InitStep5_Value1 = 0x45670123
InitStep5_Comment = "Unlock Option Bytes"
InitStep6_Action = "Write 32bit"
InitStep6_Value0 = 0x40022008
InitStep6_Value1 = 0xCDEF89AB
InitStep6_Comment = ""
InitStep7_Action = "Write 32bit"
InitStep7_Value0 = 0x40022010
InitStep7_Value1 = 0x00000220
InitStep7_Comment = "Set Write and Erase bit to prepare Option Byte erase"
InitStep8_Action = "Write 32bit"
InitStep8_Value0 = 0x40022010
InitStep8_Value1 = 0x00000260
InitStep8_Comment = "Trigger operation (Option Byte erase)"
InitStep9_Action = "Delay"
InitStep9_Value0 = 0x00000000
InitStep9_Value1 = 0x00000005
InitStep9_Comment = ""
InitStep10_Action = "Read 32bit"
InitStep10_Value0 = 0x4002200C
InitStep10_Value1 = 0x00000000
InitStep10_Comment = ""
InitStep11_Action = "Var AND"
InitStep11_Value0 = 0x00000000
InitStep11_Value1 = 0x00000001
InitStep11_Comment = ""
InitStep12_Action = "Var BNE"
InitStep12_Value0 = 0x00000009
InitStep12_Value1 = 0x00000000
InitStep12_Comment = "Wait for busy bit to clear"
InitStep13_Action = "Write 32bit"
InitStep13_Value0 = 0x40022010
InitStep13_Value1 = 0x00000210
InitStep13_Comment = "Set Write and Programming bit to prepare Option Byte programming"
InitStep14_Action = "Write 16bit"
InitStep14_Value0 = 0x1FFFF800
InitStep14_Value1 = 0x000055AA
InitStep14_Comment = "55AA = ROP Level 0."
InitStep15_Action = "Delay"
InitStep15_Value0 = 0x00000000
InitStep15_Value1 = 0x00000005
InitStep15_Comment = ""
InitStep16_Action = "Read 32bit"
InitStep16_Value0 = 0x4002200C
InitStep16_Value1 = 0x00000000
InitStep16_Comment = ""
InitStep17_Action = "Var AND"
InitStep17_Value0 = 0x00000000
InitStep17_Value1 = 0x00000001
InitStep17_Comment = ""
InitStep18_Action = "Var BNE"
InitStep18_Value0 = 0x0000000F
InitStep18_Value1 = 0x00000000
InitStep18_Comment = "Wait for busy bit to clear"
InitStep19_Action = "Write 32bit"
InitStep19_Value0 = 0x40022010
InitStep19_Value1 = 0x00002210
InitStep19_Comment = "Trigger the Option Byte Loader"
InitStep20_Action = "Delay"
InitStep20_Value0 = 0x00000000
InitStep20_Value1 = 0x000007D0
InitStep20_Comment = "Memory cannot be read, therefore we wait a fixed amount of time here"
InitStep21_Action = "Reset"
InitStep21_Value0 = 0x00000000
InitStep21_Value1 = 0x00000064
InitStep21_Comment = ""
NumExitSteps = 0
UseScriptFile = 0
ScriptFile = ""
UseRAM = 1
RAMAddr = 0x20000000
RAMSize = 0x00004000
CheckCoreID = 1
CoreID = 0x0BB11477
CoreIDMask = 0x0F000FFF
UseAutoSpeed = 0x00000001
ClockSpeed = 0x00000000
EndianMode = 0
ChipName = "ST STM32F070RB"
[FLASH]
aRangeSel[1] = 0-63
BankName = "Internal flash"
BankSelMode = 1
BaseAddr = 0x08000000
NumBanks = 1
[PRODUCTION]
AutoPerformsErase = 1
AutoPerformsProgram = 1
AutoPerformsSecure = 0
AutoPerformsStartApp = 0
AutoPerformsUnsecure = 0
AutoPerformsVerify = 1
EnableTargetPower = 0
EraseType = 2
MonitorVTref = 0
MonitorVTrefMax = 0x0000157C
MonitorVTrefMin = 0x000003E8
OverrideTimeouts = 0
ProgramSN = 0
SerialFile = ""
SNAddr = 0x00000000
SNInc = 0x00000001
SNLen = 0x00000004
SNListFile = ""
SNValue = 0x00000001
StartAppType = 0
TargetPowerDelay = 0x00000014
TimeoutErase = 0x00003A98
TimeoutProgram = 0x00002710
TimeoutVerify = 0x00002710
VerifyType = 1
通过内存映射编程修改选项字节(以STM32F1x为例)
J-Flash 支持对STM32设备的选项字节进行编程。为了对选项字节进行编程,只需在 CPU settings 选项卡中选择允许选项字节编程的适当设备(例如 STM32F103ZE (allow opt. bytes) )。J-Flash将允许对地址为 0x06000000
的虚拟16字节扇区进行编程,该扇区表示8个选项字节及其补码。您不必关心选项字节补码,因为它们是自动计算的。下表描述了选项字节扇区的结构:
Address | [31:24] | [23:16] | [15:08] | [07:00] |
---|---|---|---|---|
0x06000000 | complement | Option byte 1 | complement | Option byte 0 |
0x06000004 | complement | Option byte 3 | complement | Option byte 2 |
0x06000008 | complement | Option byte 5 | complement | Option byte 4 |
0x0600000C | complement | Option byte 7 | complement | Option byte 6 |
注意:
- 在 option byte 0 内写入 0xFF 值将对STM32进行读保护。为了使设备不受保护,您必须将 key 值
0xA5
写入 option byte 0 。- 地址 0x06000000 仅为虚拟地址。选项字节最初位于地址 0x1FFFF800 处。从 0x06000000 到 0x1FFFF800 的重新映射由J-Flash自动完成。
要用值 0xAA 和 0xBB 对 option bytes 2 和 3 进行编程,但不保护设备,您的选项字节扇区(地址0x06000000)应如下所示:
Address | [31:24] | [23:16] | [15:08] | [07:00] |
---|---|---|---|---|
0x06000000 | 0x00 | 0xFF | 0x5A | 0xA5 |
0x06000004 | 0x44 | 0xBB | 0x55 | 0xAA |
0x06000008 | 0x00 | 0xFF | 0x00 | 0xFF |
0x0600000C | 0x00 | 0xFF | 0x00 | 0xFF |
有关每个选项字节的详细说明,请参阅ST编程手册 PM0042 ,“Option byte description” 一节。