|

我是老温,一名热爱学习的嵌入式工程师
. L1 k/ C+ R$ \( `2 r# A关注我,一起变得更加优秀!
% h) O2 t" d5 b$ Z前言+ `9 H) ?# L- y! [" [! g
& F" J" Y8 G4 F; X j( ^有些时候在我们的应用过程中要求变量有连续性,或者现场保留,例如 Bootloader 跳转,某种原因的复位过程中我们有些关键变量不能被初始化,- G" G( e# p8 ^$ I- l
4 [ q1 {6 f1 u+ U
在不同的编译环境下有不同的设置,本文就这个操作做总结,分别介绍使用 Keil,IAR 和 CubeIDE 的操作方法,本文中所用芯片为STM32G431RBT6。
" Z4 J+ n& b3 W
: w. P6 v/ s* ?1 gIAR 实现变量不初始化方法6 h% r0 i3 {$ b, J
0 ~7 X# s+ \* Y6 v, HIAR 实现相对简单,直接使用“__no_init”这个关键字即可,也就是在变量前面进行修饰:7 e. X2 J8 G' v6 T8 X9 Y4 I
, d, k# q5 k$ L) ]
y2hohuctb1464045626223.jpg
$ L; w+ g K8 v
! U& Q# O3 l7 T" S3 g为了验证是否执行成功,可以考虑周期性让系统复位,看变量的变化,比如下面的示例程序让系统周期复位,会发现每次 Test_NoInit 数据都是在上次数据基础上增加 10,而不是被初始化后的数据增加 10。
1 ], C N, G m! s* q0 k" R( @$ B+ G7 y4 }
qnyanfnelbm64045626323.jpg
?5 z7 P) t- p! _. N* M) g7 _
2 T$ N7 l) B1 x# b) ~; M
Keil 实现变量不被初始化方法3 \! \0 l. i, X! p; V
* O" n& Y! m( Z+ w# j( O
Keil 中没有像 IAR 里面的这个关键字,而且会有版本的区别,下面分别介绍:4 P3 M* S7 b. n% d! {: S4 S
" Q! f0 [9 l- R; a: n% I
ft3hxylfu5m64045626423.jpg
F) e' d1 }* Y( A- V
图1.Keil 不同编译版本) n, h' S& c. S+ _& F
6 X, g' p" S, m
为了防止未初始化的变量被初始化为 0,要将未初始化的变量放在一个特殊段内,这个段满足是 ZI 数据段(.bss),它的执行域(region)具有 UNINIT 属性。
0 q: ]7 u4 M6 I9 y' U, u$ |; [9 Q0 f
Arm? Compiler 5 的操作
1 }2 r- Z; p, k4 ^3 s1 {" P5 P# A+ f! F& u$ N( N" K5 s$ D
修改工程的 linker file 文件,*.sct 文件
6 h3 G ~1 k: @
6 A% v. z9 D" ]" R, H
ykue0cdyxqq64045626524.jpg
. b2 O9 u5 {, E. \* M图2.修改默认 linker file' Q2 ~0 J- }+ i
) O$ A) f3 m3 W) N这边将 RAM 划分两个区间,其中 RW_IRAM2 就是我们要的变量不初始化区域,属性为UNINIT,定义一个 region 名字 NO_INIT.) o/ B' S% g& v' G
* s$ G9 t% _' m k. D& N% T
h1123mqo5ev64045626624.jpg
8 I& k& U- o" Q& z% Q) C
$ z* d1 C h8 X, X' L变量定义到这个 section,这边 AC5 要用到 zero_init 这个修饰。3 R) `( t" y$ N- v
3 B$ e# U7 T9 n0 u
tkttmdh0dx064045626724.jpg
" }0 I, J4 |& V, Y1 R3 `
2 S& A, y1 u7 p. n8 X! v
Arm? Compiler 6 的操作$ V: ~( E4 N; F" E% H
j/ N1 b4 s9 S! ? [# Y1 @在 AC6 上面需要加入.bss 这个 ZI 定义,如下的 sct 文件修改:, D* d2 G% n% k; X' r, E2 A3 E8 @
: p0 { i, |" `
j1byteg0u2g64045626824.jpg
& o1 j0 O: {, C; l) \; i
r% f3 T2 y+ N% X+ r变量定义到 section 部分,AC5 和 AC6 也是有区别的,不再支持 zero_init 这个修饰,如下定义:
& p& b, K: \/ \2 D+ [1 E/ ` A F: g, q% _8 f4 e0 _# z- \4 I6 n) Q
lucwogwvlkx64045626924.jpg
; H* [8 f; W' w4 v2 s
/ k4 _8 B4 n8 R0 U* V
对于版本 AC5 和 AC6 具体区别可以参考 Keil 帮助文件中的描述:
2 |1 r U) D8 u6 L, G4 J* g+ |0 g5 r
hdv5dmlcmd164045627024.jpg
) u/ T- o; f1 j9 `* \; a图3.Keil 帮助文件关于 zero initialized3 ~7 H% y* x. q" _/ S$ m/ y) |
CubeIDE 实现变量不初始化方法8 b9 V2 \' n. l5 W
& R( `0 ~% a6 r7 ^1 A" @9 H
CubeIDE 的实现和 Keil 有类似的操作,需要修改 linker file 文件*.ld。首先对 RAM 进行划分,划分出不初始化的 RAM 区域:
; p, H- b# v$ [% B; s2 \/ Q3 E7 n
6 y* v1 o- F8 Y0 K( E5 E+ F S
gcutovz5q5a64045627124.jpg
* |) E# d% M( W1 Z* q4 M4 R图4.划分 RAM 区域
- g- p' i7 }( Q
' W, E( o1 D9 N2 K& M- H1 M' N) N6 B, {增加区域描述,并且加入区域名字:; a; f: ~+ ?% L5 y, E8 n1 \
) H; E1 K& N, Z3 a" T
2hfr0cv3zmf64045627224.jpg
. O- \8 k; N. V' P8 `- y& e
图5.区域描述,名字定义! M5 F r, q0 Q F( I- J; G
! |6 k2 _' h4 r# K; W
0 n3 f. O" p Z) X& O! M6 x5 R; g/ Z8 o定义变量到这个不初始化区域中:# v4 d' ]6 y7 @ P
& j' [% ?3 e, d U) x( u+ f
j25tid4fnte64045627324.jpg
0 r3 S: u( a# S" z! y1 s- O
3 v/ [' H9 @: B/ ?* v另外,还提醒一点,有些 STM32 系列有专门针对特定 RAM 区复位后是否会被初始化的 Option 配置位。比方 STM32L4 系列,想让 SRAM2 变量不被初始化,得配置选项字节中的 SRAM2_RST位。如下图所示:& i$ T6 C. q( U6 `" d
( L7 q" u5 p! m0 u
xrgi22yjjtv64045627424.jpg
7 \; Q8 s' w1 o来源:STMCU
4 z9 @- U1 D7 O$ w文章来源于网络,版权归原作者所有,如有侵权,请联系删除。2 }5 [ m$ D' p$ ]
! }. g: P6 z7 M' u3 V" R
vy5nkeewk3n64045627525.png
1 l8 [( I: [/ F, {3 S% a# z* w N4 \
6 n+ V" _! ?. L
: d7 R, \2 R' j" \
-END-: v: p; X% g2 |$ o4 X' k7 k
往期推荐:点击图片即可跳转阅读; h1 K1 m( Q9 j1 [' @2 E1 W
5 ?. Q* u4 y5 w% f. y+ l
+ H( }% p; I/ z
1 i% B: g2 }- t8 u, L( T
/ o! y+ ]; d& M% x" D( k/ ^; a) E( N3 P 2 ?4 c# h6 i8 f& ?. u, U' s
rbfmgwqzz4i64045627625.jpg
7 Z7 k7 c" `3 p; x6 S$ C- v
8 T* K/ Y2 e! Q" b 嵌入式工程师的2024,这一年,感谢微信读书!* _, ]- d; }: Z. V$ }
* Z$ i/ T$ \4 V$ m
& w+ t9 q0 [; m% p/ p, {
I. v+ ?7 ^0 W2 {) ~, r 7 Z' H1 k! n4 A3 a; z6 X
6 G5 U7 W; r9 L
3 {) q6 W* f% M5 ?' }
# }- H* V& ? A( j5 t; h( q% ?' K & O+ u& B1 Z0 H6 m) P
2 f7 f/ l6 n: h
6 Z: l) ?/ I/ G: |" g$ \
nrqzbwpv0lg64045627725.jpg
# t* z1 K, x! X4 d. U 1 a; P+ T8 R) d' m K
嵌入式 C 语言编程,如何有效防止内存泄漏?
5 L- W7 [: r. S7 h3 L" y, r : j$ F) h6 F F! I3 L& S0 k
. n8 y9 ^1 l: g# [( k$ G
$ r4 {8 w. ~1 Y& O
( q8 m2 E" c$ X( T V/ g
& k+ ]1 a5 s* K$ t
; ]; F X% D* D8 ?1 N0 ]' B0 k # ]# W& A& h- C$ R3 ?5 p# g0 o- D
& _% f3 V2 x9 u* O1 ^$ h
$ E) ^3 z& O1 {$ ?5 w, E2 U: z $ Q# ~% k, P) J/ b1 a: ~
2eupvh4vevu64045627825.jpg
- x* {" y9 u# w) |7 b2 k ] # K0 z3 {! J, u, \5 I
嵌入式 C 语言,位操作的几种常见用法。
$ P. K: L/ P, I
) ?) y; Y( G/ A2 f 5 E& M! O: D; z/ C* x0 B i
7 O* Q2 |7 z7 f) h" O' X& R
$ `, d+ y7 e* q- ^) W 7 L p) F# O0 k$ R
我是老温,一名热爱学习的嵌入式工程师. I+ [6 L6 [/ S% M* Q
关注我,一起变得更加优秀! |
|