1njpm0i3uos6409896515.png
1 t' i0 |$ ^) C6 i/ i
3 ^6 u0 v* i/ v( o' u2 g
有些时候在我们的应用过程中要求变量有连续性,或者现场保留,例如 Bootloader 跳转,某种原因的复位过程中我们有些关键变量不能被初始化,在不同的编译环境下有不同的设置,本文就这个操作做总结,分别介绍使用 Keil,IAR 和 CubeIDE 的操作方法,本文中所用芯片为:STM32G431RBT6。Keil 中没有这个关键字,而且会有版本的区别,下面分别介绍:
$ `. T! i7 k9 C9 Q" z
g5pki5ymjv56409896616.png
, |# a# W. i0 o: F1 Q6 c! y为了防止未初始化的变量被初始化为0,要将未初始化的变量放在一个特殊段内,这个段满足是ZI数据段(.bss),它的执行域(region)具有UNINIT属性。
5 {& v) |, }; Q0 K2 u1.Arm? Compiler 5的操作% u( C+ E9 z6 |# J
修改工程的linkerfile文件,*.sct文件
! K. ~" B1 U, ]4 I% Y* B, Y
ut32nqwyeqo6409896716.jpg
* f; F H. C& a/ H! V0 S
这边将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, q4 Q/ i0 V/ p2 L: Z7 u
2. Arm? Compiler 6 的操作( d+ Y; a+ J0 p3 N
在 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! j& I& D6 p7 K- n+ T/ [
对于版本 AC5 和 AC6 具体区别可以参考 Keil 帮助文件中的描述:1 t& N& m4 r0 O! K9 v' o4 j
icdjozh2ksp6409896816.png
T, C5 r! H0 T5 N1 g
==========
. A7 G0 `1 f; N# q% q) l往期回顾:如何提高单片机的运算效率之FPU
2 ?) r; q" ]" d( f蓝桥杯物联网教程汇总_240529
6 M$ f/ C; o9 S/ P. {==========4 z: j& u7 P* C! T
6 b# [! r' T4 J( }. ^# `
ilrzbzbe1yp6409896916.png
2 }) Y8 N6 q; |: }, X5 {
9 I# `8 E2 S" b: \) i. Y) G
drzgbmxnjcz6409897016.png
4 r; N- U+ \$ @9 W- W, S
: M/ c; A# b4 }" a& F1 v# w& w
1jafylgg0gn6409897116.png
|