我是老温,一名热爱学习的嵌入式工程师( ]9 x% Q* F3 o) s! }5 V
关注我,一起变得更加优秀!
9 u, t [1 x4 A/ A' K前言: H6 ~/ H8 N& k
# _' @" _2 T1 B) d: m7 I有些时候在我们的应用过程中要求变量有连续性,或者现场保留,例如 Bootloader 跳转,某种原因的复位过程中我们有些关键变量不能被初始化,2 g+ @/ `6 J+ l$ \
; A, g8 |5 f2 |
在不同的编译环境下有不同的设置,本文就这个操作做总结,分别介绍使用 Keil,IAR 和 CubeIDE 的操作方法,本文中所用芯片为STM32G431RBT6。
# ]2 ]1 |5 R% d( Q1 j2 E
8 b" H" r2 t3 x$ c% G: g9 Q9 BIAR 实现变量不初始化方法) b! y# o! ~* E$ U5 J4 v) z) ]
' p3 _! [* y! N# J8 w7 @
IAR 实现相对简单,直接使用“__no_init”这个关键字即可,也就是在变量前面进行修饰:/ E+ c) o _" t( C$ X* m) n. S6 U
0 H' J& j: K: B+ i
y2hohuctb1464045626223.jpg
+ C9 N& P, x2 h3 m' |# q( r
: H% P" g4 j2 S为了验证是否执行成功,可以考虑周期性让系统复位,看变量的变化,比如下面的示例程序让系统周期复位,会发现每次 Test_NoInit 数据都是在上次数据基础上增加 10,而不是被初始化后的数据增加 10。9 Q8 U9 ]7 V% ~: z- K$ b; \
$ L7 z0 B2 e% s U' @. W
qnyanfnelbm64045626323.jpg
4 x* i1 U& o, f3 h+ T, W. U5 P' b4 \9 k6 b/ {3 P* o1 D
Keil 实现变量不被初始化方法% e9 d+ U$ @- w
8 B1 h& [7 N* cKeil 中没有像 IAR 里面的这个关键字,而且会有版本的区别,下面分别介绍:
0 w1 h* V! I+ B; q4 L" h$ T. [) `% m# g6 c7 F
ft3hxylfu5m64045626423.jpg
7 w" h8 y8 G! c8 r7 P, ^
图1.Keil 不同编译版本9 e, I0 }% y+ g: Z/ P1 f) l
6 v: g) |# ]" H- b# b9 p
为了防止未初始化的变量被初始化为 0,要将未初始化的变量放在一个特殊段内,这个段满足是 ZI 数据段(.bss),它的执行域(region)具有 UNINIT 属性。
% o% z0 k3 E7 _& p+ f2 M C" `0 {8 O* o
Arm? Compiler 5 的操作
: O! _) _0 ~% [& C" w: i+ m- G* m0 ~; V- z2 {4 q; x
修改工程的 linker file 文件,*.sct 文件
$ N, W" `7 A8 K1 T
4 W5 ^% l5 B' b7 k
ykue0cdyxqq64045626524.jpg
7 L( `' g H6 l. Z+ j- O
图2.修改默认 linker file2 u' k% H) X& t U' n! F
d2 L" ^6 [! y f- Q4 Y3 T, |! Z. x' p
这边将 RAM 划分两个区间,其中 RW_IRAM2 就是我们要的变量不初始化区域,属性为UNINIT,定义一个 region 名字 NO_INIT.- {% j7 @3 O0 J) X
4 @/ i; `0 K) q/ }
h1123mqo5ev64045626624.jpg
% h( ]; |! c. Q' a
1 J }3 Z% y; m' o7 Y3 V* m7 i变量定义到这个 section,这边 AC5 要用到 zero_init 这个修饰。
! y6 t* H6 r) V# F9 c, u H7 X8 L. B/ L
tkttmdh0dx064045626724.jpg
2 O5 a6 A+ W! D" E
3 V- Z8 b8 n \7 W0 C2 n% _3 fArm? Compiler 6 的操作- B# V$ i* j4 K; p! r4 R1 K/ ]& n
$ S! T9 A9 }5 `; I8 h" |在 AC6 上面需要加入.bss 这个 ZI 定义,如下的 sct 文件修改:" d# T3 B/ f2 M& y( a
- t! g- x* I( a4 F3 m( w
j1byteg0u2g64045626824.jpg
# `' U- F) [. d9 S: } O: D
$ `9 O5 ~7 A5 I# S. @" O/ F% o变量定义到 section 部分,AC5 和 AC6 也是有区别的,不再支持 zero_init 这个修饰,如下定义:& R @0 D' r0 u4 O$ k5 m4 q
# A; I& C5 _% l" O, \: G: Z* E/ r
lucwogwvlkx64045626924.jpg
- C0 G( J7 V* n1 _7 \
6 Y1 Y8 q' d$ S. p& l
对于版本 AC5 和 AC6 具体区别可以参考 Keil 帮助文件中的描述:
, V0 I/ v0 M, c
2 B2 M4 n' S- G9 W: n
hdv5dmlcmd164045627024.jpg
+ V: s5 h9 S6 Q$ E/ b5 L( a图3.Keil 帮助文件关于 zero initialized$ ? G6 E4 ]8 U2 K! }
CubeIDE 实现变量不初始化方法
$ g% E& f+ [4 l9 D% D
. O7 E. J# N: @9 c, D: UCubeIDE 的实现和 Keil 有类似的操作,需要修改 linker file 文件*.ld。首先对 RAM 进行划分,划分出不初始化的 RAM 区域:" d; L/ E7 \; J3 a3 x2 w
+ S x+ c4 j: C _+ L
gcutovz5q5a64045627124.jpg
# V5 A3 R( s' ~6 W1 ?
图4.划分 RAM 区域, G, _5 z3 a1 K; s7 X r6 g* G4 D
9 c$ p4 u" v( H: p9 L) n
增加区域描述,并且加入区域名字:
3 }" q7 @! h( Q/ p
5 _7 s7 H" m* @. A/ x
2hfr0cv3zmf64045627224.jpg
0 J' ^1 Q+ v% D4 e9 R
图5.区域描述,名字定义
+ W, T7 K# h( L+ ~, X8 C3 ]) l. w9 z% _/ R* [/ C
0 Z7 W1 ]9 V) O+ l
定义变量到这个不初始化区域中:7 y: d8 g& S& U1 Q
3 W' H) y- X: [+ a/ R: o, `
j25tid4fnte64045627324.jpg
8 J5 C0 Z4 A/ a0 I
* y6 u/ ~9 [; W7 [3 A% e" ~
另外,还提醒一点,有些 STM32 系列有专门针对特定 RAM 区复位后是否会被初始化的 Option 配置位。比方 STM32L4 系列,想让 SRAM2 变量不被初始化,得配置选项字节中的 SRAM2_RST位。如下图所示: s. H, i, g% U: X8 `: ~9 i
! a5 w0 O* l. A9 }; b
xrgi22yjjtv64045627424.jpg
/ S% |' M' A) A; c' S; ]+ G! L6 ~来源:STMCU
+ z$ h+ _& R$ u" ]$ |# m文章来源于网络,版权归原作者所有,如有侵权,请联系删除。
, ~: l. j- c9 e( y# s+ d! N
' f% D2 D; W3 {! \7 o
vy5nkeewk3n64045627525.png
5 C& K1 T/ f* k; t, q! e' g
) K* R% x" R$ `2 k4 t
- `4 H- i$ K3 j Q: \# |
-END-
% B) @6 P# p' S, g7 R6 v! c- k往期推荐:点击图片即可跳转阅读" t8 a4 j3 H( A1 g$ z+ g4 M
. Y5 S3 V& P+ X0 p7 P , [# q3 q9 l5 \# \3 \; Y
3 q: C3 I1 Z4 e. `& t
( z: r1 x! s* [4 Z' ^0 V6 {) Z4 S ( P/ S5 M0 f* n/ Q# Q/ `
rbfmgwqzz4i64045627625.jpg
, `% g: u( ~# B" H5 P! J8 N( l
- _0 e: k% Z$ v0 {6 g, | 嵌入式工程师的2024,这一年,感谢微信读书!, _* ~8 D/ ~, F$ A9 l
7 z% j9 ]8 B( T8 ]+ k1 O
5 B1 U0 h. i4 t* e: f4 Y& t2 { ( k9 o; v/ A4 C `( d, `
0 V5 S% ] |% I4 M6 [- B
: X s* k @& h* Y" Y6 L3 s2 O, F
+ q* u& C0 b% x" D4 z8 W
2 y; e5 f- _( {* Y7 B/ ] # A, G# C9 ^7 g; k2 \
3 X5 d7 J+ w, m$ ?/ c : k I2 r5 ]3 O6 h3 q$ L
nrqzbwpv0lg64045627725.jpg
5 T* o1 c: N* Q; E X
$ G6 I e) T3 R$ c: N c 嵌入式 C 语言编程,如何有效防止内存泄漏?
* m- L& U: g* w% |7 H9 [* |
) i w- W ^/ _/ Z 3 Z/ \& `4 u5 R- T5 E; @
- l. O6 q% `8 @3 V- R1 N1 @, ?
3 E8 Z. e. e$ d- z+ |/ y0 p / {9 \# B7 o# O+ Z
# T) Q% \3 s$ Y9 C& K% A" y; g
& w) F0 P& K( p, C, l) \) x2 E " X1 M* A' V, T C/ e
& H: u2 R9 p" P3 B# z( T9 y- L
+ O1 x# N! L5 E. }
2eupvh4vevu64045627825.jpg
4 e7 E9 f H+ a. x1 s. R1 j
+ c; J; D) r: o- X+ s: a' d7 D 嵌入式 C 语言,位操作的几种常见用法。
2 ]3 y: L+ r/ I, B9 N4 @$ L% q 5 u! C! B8 L* m
" `' I2 V# {: L" O u
1 r5 O2 s$ X0 G# M
8 y& d& E2 p( f) j - E$ ~& r4 ~7 e
我是老温,一名热爱学习的嵌入式工程师9 N! l5 N2 A8 p$ F$ V1 M
关注我,一起变得更加优秀! |