前言
! ]0 t8 q8 Y0 [STM32 PCROP 专有代码读出保护,将某个区域设置为仅允许执行,可防止代码被非法读出与修改。ST 网站提供了免费的PCROP 参考代码,但是例程中仅仅提供了用代码设置 PCROP。为方便利用 PCROP 进行知识产权保护的开发和部署,这篇文章提供了方法, 可在 RDP 级别设置为 1 或者 0 时,使用代码清除 PCROP。" ~6 h) ~2 q8 J" n/ h7 @& Q1 b1 t
0 T9 Q8 {# F8 |3 O; i/ n+ X, i9 DST 网站上的 PCROP 参考代码
1 C% E% n/ _' V9 r3 ?学习使用 PCROP,可从 ST 网站下载文档以及参考代码。文档里有一步一步的详细说明。参考代码则实现了,如何设置编译开发环境去掉文字库(Literal pool),以避免受保护区域需要被读访问;参考代码也实现了如何利用代码使能 PCROP 保护以及如何导出接口符号供二次开发使用。你可以编译运行 PCROP 参考代码。一旦下载到开发板并运行后,扇区 2 会自动被设置成 PCROP 保护。你将无法再次下载. K( n; c9 k H! _8 D
代码到该扇区,也无法读出该扇区的内容。若想通过 STLink 工具解除 PCROP 保护,则会导致整个 Flash 被擦除。; ?8 A% f# d4 C9 k; G
6 T) C! e( H! U) P+ Z- f6 L! a3 R( _使用代码清除 PCROP6 O; D/ H0 x+ Y
在熟悉 ST 网站上的 PCROP 参考代码基础之上,我们将讨论如何使用代码清除 PCROP。- \* U2 h( Y+ X& C0 O5 O
1. 原理1 K7 u# N, I3 j- n! ^; u5 D, O
根据用户手册,要想清除 PCROP 保护,读保护 RDP 级别必须从 1 设置成 0。也就是说,即使当前 RDP 级别为 0,我们也要使用代码将其设置成 1。然后,同时关掉 PCROP 和将 RDP 设置成 0。这也说明,尽管是清除 PCROP 保护,我们的代码必须加入 RDP 的设置函数, 而不能仅仅修改参考代码中的 PCROP_Enable 的状态字段使其变成 PCROP_Disable。. s0 ]2 L+ a6 X! u; k
$ g. B) f8 e) f' z
+ f V" a& N E6 W$ E
. {0 Y# w ]+ ~9 n, V2. 材料准备
- N# J/ I" `1 g& s- m) x 开发板: STM32F429I-Discovery, Y! `* r% ]6 C. v2 c
开发工具:STM32Cube_FW_F4_V1.15.0" \" [! }- X7 f7 _! C$ @' C
STM32CubeExpansion_AN4701_F4_V1.0.0(从 ST 网站下载的参考代码)
0 ]9 A$ h, ]! A( K6 S o" j STM32 STLink
9 J# U! s0 H" G- A IAR/Keil
8 j8 Z% l4 T# a3 L9 S8 Y* X 注:也可以选择其他支持 PCROP 的 STM32 系列并选择相应的开发板与固件库。
) X0 G( b% \1 ~, Q- D7 i3. 代码
" X5 @* {" I8 A 设置 RDP 到级别 19 f G: P t' M+ D1 ]5 G
该函数在 RDP 级别为 0 时,若需要清除 PCROP, 必须被使用。
7 [' d5 x" ]( L; C7 ^/ }* Y# K: [- void RDP_Enable()
& x: H6 a/ W- u% W, l - {- i' F. x* s) |6 N
- HAL_FLASH_OB_Unlock();9 Y9 m! Y6 |& s1 E i* Q) e2 Y
- /* Allow Access to Flash control registers and user Falsh */
: b4 v6 \. z/ |6 K - HAL_FLASH_Unlock();0 d' w ^, c: ?; Q( f5 H4 _9 K- h) L
- HAL_FLASHEx_OBGetConfig(&OBInit);+ z- ~' g# T. p
- //After programming please power off and power on in order to use this board
# q5 O( f3 B5 t4 W- T: F - if(OBInit.RDPLevel == OB_RDP_LEVEL_0)5 J6 o' y2 {) R+ Q
- {
7 C% |5 a7 z( y, `; v - OBInit.OptionType = OPTIONBYTE_RDP;
: y! t0 J9 y1 v! X4 r# e: S' v7 K - OBInit.RDPLevel = OB_RDP_LEVEL_1;
! ^' |( i* ^. p+ U0 @. O: ] - HAL_FLASHEx_OBProgram(&OBInit);: {7 t- \$ F3 O' _
- - D# u7 Y6 B& n+ t; u+ I6 w' A! }
- /* Start the Option Bytes programming process */
8 _. y9 L+ y n# h - if (HAL_FLASH_OB_Launch() != HAL_OK)
2 J4 m# \6 w+ K( q& K- n - {
& N, ?: j, L. m h! _* K0 `9 J5 ` - /* User can add here some code to deal with this error */
3 t" C9 l, ]* @" @ - while (1)
+ ?2 f& j- E* r$ w, M2 S - {
8 E$ \3 P- j. U1 ~2 |% _ - }
6 K9 v2 E: E. _ - }( O. m0 P7 r4 j; S- C1 I/ T9 R
- }/ |- g0 H3 `. ]: K8 Z
- /* Prevent Access to option bytes sector */
4 B- x) S- ?2 n/ W9 S! t - HAL_FLASH_OB_Lock();
8 z( A1 i4 ?! g; z, ~ - HAL_FLASH_Lock();
; M& G$ Z+ u: g% Z. n& S - }
复制代码 9 u$ a; c$ B& W A% _! w
设置 RDP 到级别 0
w q& _6 C* [$ {0 o在清除 PCROP 保护的代码里不会直接调用这个函数。参考手册提到,PCROP 的清除必须与 RDP 从 1 到 0 同时发生,而下列 RDP_Disable 函数则是完整独立的,无法与 PCROP 的 Option bytes 同时操作。不过,这个代码的中间部分,也就是实际功能部分,将在清除 PCROP 时被重用。
0 y- N& e/ ^) E" c' O1 ]- void RDP_Disable()
7 h$ {2 u2 j; y3 }2 ]: @ - {
* Q% n4 }) U" \! F( n - HAL_FLASH_OB_Unlock();/ F# p- q6 f" X5 Y7 n. E4 w- D6 H
7 @+ _+ I: R8 ^$ `- /* Allow Access to Flash control registers and user Falsh */. S& H6 s- y. g9 _
- HAL_FLASH_Unlock(); z3 V) \2 s7 E2 b( @; m% E( {
- 1 `' l* T0 p" i- w& u3 m1 u0 X
- HAL_FLASHEx_OBGetConfig(&OBInit);
|7 y. R$ d! P - //After programming please power off and power on in order to use this board
* l0 U6 C" I. C8 w2 J3 W - if(OBInit.RDPLevel == OB_RDP_LEVEL_1)
" p2 n4 e5 v# m2 T - {
/ v3 b/ O+ V( S2 S5 ]; L1 y6 O2 g - OBInit.OptionType = OPTIONBYTE_RDP;
1 [% ^; w6 z* P4 z" G - OBInit.RDPLevel = OB_RDP_LEVEL_0;
/ u4 t" Z. W. w5 k' L3 [% ~9 P - HAL_FLASHEx_OBProgram(&OBInit);
' f" w2 ]" q. ~! [! g - 9 I! l! N( c# F# V
- /* Start the Option Bytes programming process */ t. i- s; p8 q4 X
- if (HAL_FLASH_OB_Launch() != HAL_OK) ~; ?. t) ?" [' Q0 W L8 ^: ?1 x
- {9 J, R8 l0 `& R% b" F
- /* User can add here some code to deal with this error */
6 T% X( U6 M3 |8 i - while (1)3 w) |! k7 }$ a3 _8 I' W& D [
- {% `! n& P% M0 g$ M8 I) k$ }6 P+ s
- }/ ~5 S1 q# s4 c! \6 l4 O
- }+ f# g( B/ M( C. M& L" t) u
- }
( ]2 {0 \( X2 [' M2 {7 O. K - /* Prevent Access to option bytes sector */2 X8 _- C9 ]* P$ u, S& t
- HAL_FLASH_OB_Lock();
, k' O' b+ Q0 O9 r. q1 a, I1 q - HAL_FLASH_Lock();( G* t, _+ ?0 ~) Y' h% H
- }
复制代码
9 f+ R% p- \ [' ?$ ~+ G$ y4 T 清除 PCROP
# s0 ?* ~' s* y* G6 a# q下述代码清除 PCROP, 它基于参考代码中的 PCROP_Enable 函数改写而成。首先,它通过 RDP_Enable 将 RDP 设置成 1。注意实验中不要将 RDP 设置成为 2,否则所有的 Option bytes 将不再被允许修改。然后将 RDP 和 PCROP 都设置完毕,调用一次 HAL_FLASH_OB_Launch 达到同时将 RDP 设置成 1 并清除 PCROP 保护。. j4 {: r; ^- |3 B8 J' v
- uint32_t PCROP_Disable(void)2 b* u: Z0 X& d- k
- {3 K# p& E/ A- x' [, D- L# h
2 g- @/ M& o6 r1 N' o- RDP_Enable();/ D8 z4 O; p2 p, L' W' d
- 3 { w' e% M+ b+ ?' N% C9 j
- /* Get FLASH_PCROP_SECTORS protection status *// J' b$ `( J0 `8 d+ N
- HAL_FLASHEx_AdvOBGetConfig(&pAdvOBInit);4 J* S, c) |3 ]
- SectorsPCROPStatus = pAdvOBInit.SectorsBank1 & FLASH_PCROP_SECTORS;; u1 T! v' b7 V0 t
- PCROPStatus = pAdvOBInit.SectorsBank1 & PCROP_ENABLED;$ x5 v/ B. e% f) r& `; |
- ! I: @3 N& V/ ^4 c6 Q; K6 }4 S
- /* Check if sector 2 has been already PCROP-ed */% y+ x3 ]" u" s K
- if ((PCROPStatus == PCROP_ENABLED) && (SectorsPCROPStatus == FLASH_PCROP_SECTORS))4 B( q2 a* y' h/ o/ A q
- {" [. Q) D1 a/ t3 c4 U, `
- /* Allow Access to option bytes sector */
3 C3 q( s& A/ [1 D& b2 | - HAL_FLASH_OB_Unlock();
3 D2 W3 w+ B1 M/ h& c, g3 L - /* Allow Access to Flash control registers and user Flash */7 l8 F$ D% E; k( z
- HAL_FLASH_Unlock();# }7 p* {7 W3 w: P
- /* Clear all nWRP bits */% e. w/ p! ?" m1 V$ [1 G. r
- pAdvOBInit.OptionType = OPTIONBYTE_PCROP;2 X; Y3 }5 U, \6 E
- pAdvOBInit.PCROPState = OB_PCROP_STATE_DISABLE;9 X* y) G5 T) r" n! {& j2 {
- pAdvOBInit.Banks = FLASH_BANK_BOTH;, I7 g( o% [ c& G' `% T. R
- pAdvOBInit.SectorsBank1 = OB_PCROP_SECTOR_All;
+ \* i+ i2 x) W! @1 ? - pAdvOBInit.SectorsBank2 = OB_PCROP_SECTOR_All;( Z1 [3 u) l6 d) s3 q% M6 ^
- HAL_FLASHEx_AdvOBProgram(&pAdvOBInit);
0 ] I( j5 L+ \ - /* Clear PCROP protection on sector 2 by setting nWRP 2 bit */
; @( d8 Z; Z* {' G - pAdvOBInit.OptionType = OPTIONBYTE_PCROP;5 M* y: p `; i8 @7 c" @3 e4 u
- pAdvOBInit.PCROPState = OB_PCROP_STATE_DISABLE;
2 t/ R" E6 V0 d/ d# d* _ - pAdvOBInit.Banks = FLASH_BANK_1;
* W/ N2 S1 U, g) D7 r - pAdvOBInit.SectorsBank1 = OB_PCROP_SECTOR_2;
3 [2 ]* o8 m4 z: P0 U) E - HAL_FLASHEx_AdvOBProgram(&pAdvOBInit);
- Q' t1 M5 L' d% T - $ x3 U- M# @3 z% b9 M
- /* Disable PCROP Protection by setting SPRMOD bit */
7 J" I( \0 V$ w) M* O9 m; x! K& [ - HAL_FLASHEx_OB_SelectPCROP();
" {. d8 q9 @, `) H+ F. u - /* Set RDP from 1 to 0*/
( L$ z; H; L# Y6 T3 Y. j$ @6 \ - OBInit.OptionType = OPTIONBYTE_RDP;
( B1 X0 e) }4 _) {' Y/ w - OBInit.RDPLevel = OB_RDP_LEVEL_0;+ Q* }3 t* V( G0 X `$ v: z: M2 d& {! u
- HAL_FLASHEx_OBProgram(&OBInit);7 x, h% R! n. `/ f4 X
- /* Start the Option Bytes programming process */2 R& ?* a0 k5 o' O4 } a
- if (HAL_FLASH_OB_Launch() != HAL_OK)" a, y6 q R5 @4 V
- {) w6 L7 J1 X- g+ m6 T5 `, P
- /* Error occurred while options bytes programming */
6 L4 x. [* {" O7 [ - return(0);' f8 [* b* b" K9 J: X6 z* C
- }/ z, f& x5 H6 ]+ ^0 [- {$ E
- /* Prevent Access to option bytes sector */
2 i1 [5 l) d1 T% b8 L' B5 L) s" s - HAL_FLASH_OB_Lock();/ J L7 u+ [9 [/ R
- /* Disable the Flash option control register access (recommended to protect x4 x2 q. d( R5 z0 }) M
- the option Bytes against possible unwanted operations) */
/ i5 b- P3 u& h* R - HAL_FLASH_Lock();
1 y8 q \0 N. S5 L! ^. g" Y
3 Y! Q' l$ a/ J' A# N- /* PCROP Protection successfully Enabled */3 J1 s) ~; b D, I( Z
- return(1);
: J2 X/ b$ X/ J - }
6 W/ H0 F" N7 X% F* Y1 z7 x; t - }
复制代码 / [0 ^+ c9 s5 m1 @+ }, C
4.运行7 d* r; B7 U. r' W
在主函数中,调用 PCROP_Disable 可解除 PCROP 保护。RDP_Enable 后需要关闭电源,重新启动,然后系统正常运行解除 PCROP 保护。解除保护后,可通过 STLink 确认 PCROP Option bytes 已恢复,同时也可以看到整个 Flash 内容已被擦除。! D1 s% P7 m6 A2 z: \
2 x9 |9 ]3 k6 e' p# [
+ `5 b1 M1 `* \2 M% H
结论. \3 M9 L8 Q) I( B! F6 |. {
本文讨论了完全使用代码控制 PCROP 的设置与清除。它可以使用在 PCROP 代码保护的开发与部署阶段。* a% |2 A6 H! _3 x4 c7 B0 v
- X8 X* P' y+ R- i: g+ G# l/ V+ s- a, P1 h9 L9 U8 m$ b) u5 m- l
|