关于STM32对内部Flash的保护 为了防止对Flash的非法访问,所有STM32的芯片都提供对Flash的保护,具体分为写保护和读保护。
k. i/ B) w% e; G$ o& A0 Z9 K
; C" @/ X! R( ~* U/ O$ R; q
. v7 }: N; Z. ^/ X 如果对Flash设置了写保护,那就无法对Flash进行编程和擦除。在开发STM32的时候,如果出现这种情况,通常仿真器都支持对Flash进行解锁,像jlink,stlink等仿真器都支持这个功能。
5 Y" Q( V9 b2 v0 a* Q8 U& h3 V2 U; o B$ w
* I- Z6 \ g6 L0 N$ T
: y& `% N2 B6 v7 W0 I" e 在使用MDK进行调试的时候,可能会遇到如下图所示的报错信息,这时候就要排查Flash是不是被保护起来了。
* @4 H$ d: E) @ {1 I4 N 读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:, k+ X- x1 q0 P: n
' }! c8 X0 d" B, w$ O/ p" J# _4 P, ^4 _% @' ]
通过调试器(JTAG或SWD)2 l. q( I6 p9 f
6 r" p. r& t: T {
: L% ]# m: B; c0 k) L8 e9 n
从RAM中启动并执行的程序
( O3 C4 {& O9 ^* J' V
: |* T3 {# Z" i( [+ ]
2 [; R6 c- s8 R' s- x5 O 写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志,读与写设置的效果见下表: " |. P: M% B7 ^3 \5 `
当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况:
4 E5 D& q: y0 t" |- O( t2 Y1 B, t- a( K A$ h+ f
$ M: D( L5 |$ o0 @% b( A C3 s |调试执行程序时
, s# g4 v$ R0 l4 e$ {2 e9 w. c
+ X$ F( t: k. r% g8 _: F
- V: Q: B9 s# D0 ^% L. l从RAM启动并执行程序时 & h5 T1 l2 t2 G
~+ g/ p x! d! |, y1 l+ Z- ?4 @: `2 E1 G: |8 ^7 e% s. A$ u7 s
STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。
3 k. R7 g+ ?$ Z, O O& k% xFlash保护的相关函数.
7 [- F3 v7 w3 Q- FLASH_Unlock(); //Flash解锁
; ~1 b$ `5 I4 X) M. m - FLASH_ReadOutProtection(DISABLE); //Flash读保护禁止
5 J! U& ~- A ?! Q7 `( y2 g- V - FLASH_ReadOutProtection(ENABLE); //Flash读保护允许
复制代码 STM32如何设置读保护和解除读保护?
6 }. y+ Q3 [# l4 q! C3 `. Y% W# t7 P( }' x: X3 a
* B8 U2 C+ R+ E 读保护设置后将不能读出Flash中的内容。- L' n& M) [2 H
- ~& N) L: H* H
3 j; d1 ^5 k) ?4 A6 T2 T如何设置读保护
) n6 g* @+ n# x) i3 F0 W9 M3 W' r0 ]
" F4 M3 ~, i) G! F7 ^: R4 ]; ]0 W) n b7 j& P5 X: ^
在程序的开头加入“设置读保护”的代码即可,每次运行代码时都检查一下,如果没有开就打开,如果打开了就跳过。其中,设置读保护的代码如下:
( k* }7 N+ ~0 i: o ^6 N- l3 y- G8 _- + N2 E! j0 }# I$ G8 ?
- int main(void)1 _2 n+ z2 `0 U, q' Q+ d3 D& ^
- {- ?( N* ^$ L% u' u! Y5 X5 r
- ...
6 W0 \3 f2 Y- @7 _, G1 o' ~ - if (FLASH_GetReadOutProtectionStatus()!=SET)//检查设置读保护与否
# u; L. I2 s* X" Q- q$ Z - {$ `5 |7 N1 b/ X8 {
- FLASH_Unlock(); //写保护时可以不用这句话,可用可不用# @6 r$ L. m6 v
- FLASH_ReadOutProtection(ENABLE); //设置读保护
* m) W+ b5 ]: g) A) T4 i+ K - }
1 G) p) m( b U - ...
- v4 H, x. B( i/ ?! o5 Z+ @0 o) x - while(1)
' j1 O2 u( P% e. R6 Z - {
" Q1 [2 V3 H1 T6 T* \" Q2 z - ...0 H: u: b6 N/ ^( { q5 H4 `
- }
. V; \" }& U; E) i - }
复制代码 上面的代码执行后,使用j-link就不能读出程序了,实现了代码读保护。需要注意的是,芯片读保护后无法再次烧写新的程序到Flash中,必须要解除读保护才可以。但是当解除读保护的时候STM32会自动擦除整个Flash,起到保护数据的作用。
! X) o5 m& B6 j o9 d
3 J, r: S* L' I
( ~3 U' i: r! q5 ~通过代码解除Flash保护! J) N7 J6 u2 w: v4 A
7 S* V0 p; P( m C" \, j% n
. N5 Z' h$ ^7 }/ ]7 i. c( c( s- u 解除读保护可以设置在按键里面,方便实现解锁,也可以设置在命令中。如下是解除读保护代码:) D/ M" U, V/ J7 h$ \! I
- void Off_Protect(void) //关闭保护
+ C" Y7 R; D* S- u9 u( D9 l - {' c- D, E- M( y% F8 `, m2 c
- if(FLASH_GetReadOutProtectionStatus() != RESET)+ u: ^) t7 |( D0 ?( t
- {/ [; J8 w+ ]( N( V
- FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
% M6 D! y" `, ?# j - FLASH_ReadOutProtection(DISABLE);* H% ?# N7 R& [
- FLASH_Lock(); //上锁
( m! O, e C8 \! B; s6 q6 w - }
7 E: X, U3 V7 L7 x+ s - }
复制代码 程序中设置一个按键或者命令,可以随时解除Flash的读保护,让芯片又可以重新烧录程序。如果没有留,还可以专门写一个程序,下载到RAM中去运行,用来解除读保护。
& ~6 t: p8 R) }/ O' Z. J- j* v
/ ?. ^" Z$ l+ X$ }& d
4 \; U7 k0 m5 j6 i0 k5 P- Y$ ?5 Y 注意:执行后,Flash会自动全部擦除。3 d) _0 ^$ y& o2 ^
- O9 K5 m. a; X! U6 J6 C9 l$ u- int main(void)
7 c8 b; o& [6 {3 \- m - {
' m9 Z8 |8 W5 |% p. e3 R$ W. k/ a1 b - Chip_Init();
6 U4 K5 v% @4 f+ X' C# l' W- E# O - FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
6 G! V3 ^! f( l8 r4 H7 F - FLASH_ReadOutProtection(DISABLE);4 p6 r- D, N% Q
- }
复制代码 通过ST-Link Utility来解除Flash保护
. t1 F f- D( J. T( ~, K9 X4 W2 X) r# N' z0 G
, |4 c; \ t ^# L1 i 在STLink连接目标板的情况下打开程序烧写软件ST-Link Utility,在菜单栏的Target下选择connect,因为这时候Flash已经被锁住了,能看到如下图所示的错误提示。
# a# Z- u; v8 Z# r8 v: }6 Y- ] 下面来操作如何解除Flash保护。" X8 e/ X9 M9 C) S/ Z% d/ P
; Q8 j8 }( g1 k) a' d
8 r/ F9 j6 K8 B/ ?6 b( M$ ` 请确保当前已经正确连接了STLink和目标板,在菜单栏Target里打开Option Bytes...选项,发现在这里Read Out Protection选项是Enable,这个表示无法通过SWD读取STM32内部Flash的程序。
( |* X! e7 b- l5 V3 j) M% x# E3 r 将Read Out Protection选项设置为Disable,并点击Apply。
" X) e, w4 n' T& e! B3 A
+ F$ F7 R9 M* I/ h( J
$ D( ]0 F P4 O 这时候Flash已经成功解锁了,跟上文提到的解除Flash保护的结果一样,内部Flash已经被擦除了,如下图红框中所示。
~1 U( z# y. T" B, v 完成以上步骤之后,在菜单栏Target下选择Disconnect断开与目标板连接。0 k' l6 I! \1 a, l
: Y# r6 M3 v5 @$ S1 V9 H% ?# U
" p( N ]+ }5 u 重新进入MDK,可以正常对目标板烧写程序了。9 J, n. p; |2 W7 l
4 m- @% z1 r3 {: o( |- j9 {. }; ?% _4 J+ J% w% h# ?
通过ST-Link Utility来设置Flash保护' E: k! M% B" w9 J
在菜单栏Target里打开Option Bytes...选项,可以看到下面有Flash sector protection选项。选择Select all之后,发现所有Page的Protection项都已经变成Write Protection了,只要选择Apply选项就可以对Flash进行写保护,如上图所示。: P. E+ C- z8 `: n: \: b
3 d4 S8 M0 N# S
1 G8 B" X0 n9 r/ ]. H0 ^& y. q; ^/ @7 b6 R; \1 W
8 |8 A+ ?+ S6 j
& R" @. F, X/ A5 ^% o! v4 {
|
步骤二:下载程序到RAM中,通过在RAM中运行程序进行flash读写保护的解除
步骤三:正常下载程序