|
关于STM32对内部Flash的保护 为了防止对Flash的非法访问,所有STM32的芯片都提供对Flash的保护,具体分为写保护和读保护。
9 L! m* W( ]+ h4 s+ z! J, a' Z1 a3 y
j1 j) B+ F$ G8 ~5 C# z
( N% [5 Z9 w! `) `/ b+ t6 N6 \ 如果对Flash设置了写保护,那就无法对Flash进行编程和擦除。在开发STM32的时候,如果出现这种情况,通常仿真器都支持对Flash进行解锁,像jlink,stlink等仿真器都支持这个功能。
8 G' N' `" p2 p( `6 s% e& p$ y2 N5 S/ h( r8 M. @
3 _# j3 {" |) Y$ ~) |6 _ 在使用MDK进行调试的时候,可能会遇到如下图所示的报错信息,这时候就要排查Flash是不是被保护起来了。
# u* i& p- Y& y2 I" Q* ? 读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:
% \8 j7 J+ j) e: _: b
+ c1 N6 ], D1 O; Y
1 j7 ~7 c3 n; D$ J通过调试器(JTAG或SWD)7 i1 D" }5 |. |9 V7 `
5 Q* S& ^5 ?3 O4 Z% V" f2 _: z( h- x% I! E; ~* O
从RAM中启动并执行的程序 `9 L2 b! h+ C, I; g% y
/ f! l; `& P% S& o* {
9 i* \% k& |, ~: r. \# ?# g 写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志,读与写设置的效果见下表: ! n7 M; A O% L) h, l
当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况: ) ]. x% D) y% g) `1 Z4 r
4 X. e% A/ V- ?% ]% ~$ I: x
0 z1 M) k. T0 L! O4 P+ c% [1 H1 S
调试执行程序时
9 z- ]" ]& s9 ~( T; Z0 l7 K- I$ k- i P
( R1 ?0 s6 T( n% J1 q* x* J从RAM启动并执行程序时
! M8 V$ z( Y$ Z, n
3 `5 |0 i+ P4 \: f6 F' K! F% Y8 ^3 {2 S8 {+ ~/ p
STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。
/ ]5 b' D. N% PFlash保护的相关函数.9 F ]% n) N0 h0 Y# m
- FLASH_Unlock(); //Flash解锁
: h. K5 D9 h# d4 \5 u - FLASH_ReadOutProtection(DISABLE); //Flash读保护禁止 3 ~, m( u; h$ \! D6 p' N
- FLASH_ReadOutProtection(ENABLE); //Flash读保护允许
复制代码 STM32如何设置读保护和解除读保护?
/ S! K9 k+ `7 M4 c. |9 f7 _8 ^
! _# z7 v$ r W& b" ?; H3 |! L% n4 g1 ~$ I9 ?
读保护设置后将不能读出Flash中的内容。
) e0 q7 ? X2 I; e; L/ q: N, b/ a y1 x Z( H8 a4 L
9 ~1 G% [5 V9 ?' p7 O/ d如何设置读保护
! d1 E% Q8 \9 |: F' h- q/ X- I- \# T
( G ~- q$ E6 m/ n% i 在程序的开头加入“设置读保护”的代码即可,每次运行代码时都检查一下,如果没有开就打开,如果打开了就跳过。其中,设置读保护的代码如下:& T# W- Y) Z7 s0 } A
- % l6 X! c8 u* p- B' U3 q
- int main(void)
( J- ^4 W3 P3 [7 R5 i3 Y& q - {! l" u, c0 @3 A2 R. f& q
- ...' g- g" l, z1 y% ^. u
- if (FLASH_GetReadOutProtectionStatus()!=SET)//检查设置读保护与否! c, [2 V O# I* i/ ]8 E
- {
! o3 Q+ X' g6 i4 i: J - FLASH_Unlock(); //写保护时可以不用这句话,可用可不用
/ H7 H& a, m! K. T7 b - FLASH_ReadOutProtection(ENABLE); //设置读保护8 K [) M- }' h* Q
- }
6 r* r) X0 I. {. x, p - ...
6 H+ _6 z: _# Q. ~& ^6 I$ \) @ - while(1)! [, Q* K ~# W9 s, I- g$ ]+ r( W
- {/ [% F7 {/ u4 f {
- ...
1 F3 G, R- p; E* ?6 U' q - }
' W \! W5 L* ~0 ~: A - }
复制代码 上面的代码执行后,使用j-link就不能读出程序了,实现了代码读保护。需要注意的是,芯片读保护后无法再次烧写新的程序到Flash中,必须要解除读保护才可以。但是当解除读保护的时候STM32会自动擦除整个Flash,起到保护数据的作用。
% I/ U5 Y) y/ _3 P1 z( b
" a+ }* e8 j. `1 t
0 R: J- {% s2 z3 \. H9 M2 L. u通过代码解除Flash保护
8 i# a" H$ a' `' d- R
% x, \1 k: D/ Z
4 A+ R* o# H( c. K% t. ^ 解除读保护可以设置在按键里面,方便实现解锁,也可以设置在命令中。如下是解除读保护代码:. X5 K9 ~# }( N4 U% t. n1 O
- void Off_Protect(void) //关闭保护
6 U# V2 T7 L u: } - {
5 I" k. Q/ C& j% i! s' f6 P - if(FLASH_GetReadOutProtectionStatus() != RESET)
) G) w# E- c$ O2 K. C - {, Q" P' e* ]) z
- FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
4 }9 P* U' M k( w1 ^! }: Z - FLASH_ReadOutProtection(DISABLE);! R9 H& v6 n% m, F1 Y6 K, C% M a
- FLASH_Lock(); //上锁
& \# J5 X& Q% W7 R - }, x( v( _9 O: h8 m
- }
复制代码 程序中设置一个按键或者命令,可以随时解除Flash的读保护,让芯片又可以重新烧录程序。如果没有留,还可以专门写一个程序,下载到RAM中去运行,用来解除读保护。
! Q# g$ @ E; r, n( |- ^5 ]/ i2 E* X ~. [
) V: T7 D: v) {& S+ [ u 注意:执行后,Flash会自动全部擦除。' T* a9 d& N( x% @1 n
$ L" B R/ i) `7 r7 f" j+ V- int main(void)8 k/ z& y, ^# [" Z, I
- {
n2 F5 E7 J: C; Z0 B - Chip_Init();
" X' J, l" B0 Q - FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
8 u" H8 P5 N1 H! J; ~. P$ v) V5 ~5 g - FLASH_ReadOutProtection(DISABLE);
; z# R. v/ M$ \; m5 L; { - }
复制代码 通过ST-Link Utility来解除Flash保护
$ G( ]$ R( ~3 m) l% ^
) |0 w* {- T, n0 x$ P, V" U2 _ H$ ~: V5 T
在STLink连接目标板的情况下打开程序烧写软件ST-Link Utility,在菜单栏的Target下选择connect,因为这时候Flash已经被锁住了,能看到如下图所示的错误提示。
' H& f6 m- r6 B0 N2 b7 c 下面来操作如何解除Flash保护。
; w6 y6 n* T! v* ~! o' w2 b9 h' o. n% Q9 [2 L
+ @* d) f/ Q5 a. w9 R7 @ r$ q 请确保当前已经正确连接了STLink和目标板,在菜单栏Target里打开Option Bytes...选项,发现在这里Read Out Protection选项是Enable,这个表示无法通过SWD读取STM32内部Flash的程序。
! K o7 k' G, l- m# s9 L5 G 将Read Out Protection选项设置为Disable,并点击Apply。. c2 R# f o$ b3 `
% x9 v. O) R/ i/ O/ J- ]( P+ U1 Z# C
这时候Flash已经成功解锁了,跟上文提到的解除Flash保护的结果一样,内部Flash已经被擦除了,如下图红框中所示。# j7 m! V: W' {" J d
完成以上步骤之后,在菜单栏Target下选择Disconnect断开与目标板连接。
; {+ [& N2 a5 E: R- Q
1 C" o( A* O0 A0 `9 R- d# L
: G& ^9 ]) _) |2 J 重新进入MDK,可以正常对目标板烧写程序了。$ [7 M8 _' W+ g9 I
6 j" o- o+ l; _
! s8 m1 K( y: o" w9 I3 d! W通过ST-Link Utility来设置Flash保护( o5 J X5 u6 [4 d) v* C' @) c
在菜单栏Target里打开Option Bytes...选项,可以看到下面有Flash sector protection选项。选择Select all之后,发现所有Page的Protection项都已经变成Write Protection了,只要选择Apply选项就可以对Flash进行写保护,如上图所示。9 w1 W9 N1 B( H
) |8 v- Y7 G3 e
/ v" S% s6 K& E9 _) K" g( O' C, O: q, H& n
. O: ]! ?5 [9 \/ ~1 x2 _/ p
{# l; e$ o5 |1 t5 G! E$ v |
步骤二:下载程序到RAM中,通过在RAM中运行程序进行flash读写保护的解除
步骤三:正常下载程序