Es8P5086 定义非初始化变量办法
一些产品,当系统复位后(非上电复位),可能要求保持住复位前 RAM 中的数据,
用来快速恢复现场,或者不至于因瞬间复位而重启现场设备。而 keil mdk 在默认
情况下,任何形式的复位都会将 RAM 区的非初始化变量数据清零。如何设置非初
始化数据变量不被零初始化,这是本篇文章所要探讨的。
在给出方法之前,先来了解一下代码和数据的存放规则、属性,以及复位后为何默
认非初始化变量所在 RAM 都被初始化为零了呢。
什么是初始化数据变量,什么又是非初始化数据变量?(因为我的文字描述
不一定准确,所以喜欢举一些例子来辅助理解文字。)
定义一个变量:int nTimerCount=20;变量 nTimerCount 就是初始化变
量,也就是已经有初值;
如果定义变量:int nTimerCount;变量 nTimerCount 就是一个非赋值的
变量,Keil MDK 默认将它放到属性为 ZI 的输入节。
那么,什么是“ZI”,什么又是“输入节”呢?这要了解一下 ARM 映像文件
(image)的组成了,这部分内容略显无聊,但我认为这是非常有必要掌握的。
ARM 映像文件的组成:
一个映像文件由一个或多个域(region,也有译为“区”)组成
每个域包含一个或多个输出段(section,也有译为“节”)
每个输出段包含一个或多个输入段
各个输入段包含了目标文件中的代码和数据
输入段中包含了四类内容:代码、已经初始化的数据、未经过初始化的存储
区域、内容初始化为零的存储区域。每个输入段有相应的属性:只读的(RO)、
可读写的(RW)以及初始化成零的(ZI)。
一个输出段中包含了一些列具有相同的 RO、RW 和 ZI 属性的输入段。输出
段属性与其中包含的输入段属性相同。
一个域包含一到三个输出段,各个输出段的属性各不相同:RO 属性、RW 属
性和 ZI 属性
到这里我们就可以知道,一般情况下,代码会被放到 RO 属性的输入节,已经
初始化的变量会被分配到 RW 属性输入区,而“ZI”属性输入节可以理解为是初始化
成零变量的集合。
已 经 初 始 化 变 量 的 初 值 , 会 被 放 到 硬 件 的 哪 里 呢 ? ( 比 如 定 义 int
nTimerCount=20;那么初始值 20 被放到哪里呢?),我觉得这是个有趣的问
题,比如 keil 在编译完成后,会给出编译文件大小的信息,如下所示:
Total RO Size (Code + RO Data) 54520 ( 53.24kB)
Total RW Size (RW Data + ZI Data) 6088 ( 5.95kB)
Total ROM Size (Code + RO Data + RW Data) 54696 ( 53.41kB)
很多人不知道这是怎么计算的,也不知道究竟放入 ROM/Flash 中的代码有多