yyttfwovytq64023638524.png
% Y) A8 J9 c/ K: e+ H6 C$ [5 b0 m0 U/ J8 c- r; A, d
有些时候在我们的应用过程中要求变量有连续性,或者现场保留,例如 Bootloader 跳转,某种原因的复位过程中我们有些关键变量不能被初始化,在不同的编译环境下有不同的设置,本文就这个操作做总结,分别介绍使用 Keil,IAR 和 CubeIDE 的操作方法,本文中所用芯片为:STM32G431RBT6。Keil 中没有这个关键字,而且会有版本的区别,下面分别介绍:) }0 y& h4 e1 |: w* q# o6 c, C: Q2 Y
fv0j1rt40gq64023638625.png
0 x E5 [- u3 C, s: C0 H5 u
为了防止未初始化的变量被初始化为0,要将未初始化的变量放在一个特殊段内,这个段满足是ZI数据段(.bss),它的执行域(region)具有UNINIT属性。
# Q3 Q/ w5 B; y: m1.Arm? Compiler 5的操作
# ^' Z6 Q# G. K修改工程的linkerfile文件,*.sct文件0 O0 p+ i1 m) w
2gqycutqfh164023638725.jpg
: O4 k7 R; }0 v; Q+ f) }0 z2 X9 I5 c; @这边将RAM划分两个区间,其中RW_IRAM2就是我们要的变量不初始化区域,属性为UNINIT,定义一个region名字NO_INIT.ER_IROM1 0x08000000 0x00020000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)} RW_IRAM1 0x20000400 0x00007C00 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20000000 UNINIT 0x00000400 { .ANY (NO_INIT) }}变量定义到这个 section,这边 AC5 要用到 zero_init 这个修饰。uint16_t Test_NoInit __attribute__((section("NO_INIT"),zero_init)); // Work for AC5. ~' [+ j$ m0 Q$ a) w( D; u
2. Arm? Compiler 6 的操作
! |2 ]" @, f* h9 P5 {) W, S在 AC6 上面需要加入.bss 这个 ZI 定义,如下的 sct 文件修改:RW_IRAM2 0x20000000 UNINIT 0x00000400 { .ANY (.bss.NO_INIT)}变量定义到 section 部分,AC5 和 AC6 也是有区别的,不再支持 zero_init 这个修饰,如下定义:uint16_t Test_NoInit __attribute__((section(".bss.NO_INIT"))); // Work for AC6+ d5 J% B1 G! e t2 H/ n, ^4 m
对于版本 AC5 和 AC6 具体区别可以参考 Keil 帮助文件中的描述:) x# q {9 c B+ }' N
n514izwlxko64023638825.png
N3 X9 S5 k4 q9 S) d/ u# _
==========
% P1 D! I' K y" o/ d' I往期回顾:如何提高单片机的运算效率之FPU
+ Q9 R! V2 ^9 b蓝桥杯物联网教程汇总_240529
1 B5 ?0 ~: q3 M' V- I1 F5 y+ [==========
+ r- p- G D! y3 ^2 c+ f- T4 J7 ~2 C0 y( _& K% G
nttv10lbuh164023638925.png
! m" @) ^$ x% q i& f
' V% G8 P1 [- l0 i( T! s
045sgoj15el64023639025.png
- K E9 m5 B# m4 s: z. X; k; v9 e5 ~& Z0 n4 C
3yvmrqybqac64023639125.png
|