电子产业一站式赋能平台

PCB联盟网

搜索
查看: 99|回复: 0
收起左侧

嵌入式软件,如果想变量不被初始化,通常有哪些方法?

[复制链接]

568

主题

568

帖子

4221

积分

四级会员

Rank: 4

积分
4221
发表于 2025-1-2 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
. 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表