打印
[XMC™]

不同IDE下变量不被初始化的方法

[复制链接]
544|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
IFXNaZhang|  楼主 | 2024-7-10 10:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 IFXNaZhang 于 2024-7-10 10:18 编辑

在默认情况下,编译器会将变量存放在RAM中,并在启动时对其进行初始化。但是有些时候,当芯片复位(不含上电复位)时,我们希望变量在复位后不被初始化, 保存复位前的一些信息。比如将系统进入hardfault前的PC指针和一些详细的DEBUG信息写入Noinit RAM保存起来,等到复位启动后可以将错误的DEBUG信息拿出来分析。实际上,由于变量是存储在RAM中的,只要不掉电,变量的数值是不会改变的,所以只要不让系统在复位时进行初始化操作即可。对此,不同的编译环境有不同的设置方法,下面就来讲讲在Keil、 IAR、ModusToolbox编译环境下,实现该功能的方法。
   1. IAR 实现变量不初始化的方法
在IAR Embedded Workbench中,__no_init是一个特殊的关键字,用于指示编译器不要对变量进行初始化操作,可参考IAR帮助文件中的相关内容:
即在IAR中“__no_init”可以直接使用,类似下面定义一个不被初始化的变量:
__no_init uint16_t Test_NoInit;
在这个例子中,关键字“__no_init”用于告诉编译器,这个变量不需要在复位时进行初始化。为了验证是否执行成功,可以考虑周期性地让系统复位,观察变量的变化,比如下面的示例程序定义一个复位后初始化的变量和一个不被初始化的变量,系统周期复位,会发现每次Test_NoInit 数据都是在上次数据基础上增加10,而不是像Test_Init那样每次是被初始化后的数据增加10。
     2. Keil 实现变量不被初始化方法
Keil MDK (Microcontroller Development Kit) 使用的编译器是 ARM 公司推出的 ARM Compiler。编译器说明文档中没有专门的关键字,解决方法是需要自己开辟一个UNINIT的段,再把不需要初始化的变量定义到这个段里面。
首先需要手动修改分散加载文件:
打开Options for Target对话框,选择Linker标签页,不勾选Use Memory Layout from Target Dialog。这个选项的意思是使用Target标签进行链接设置,所以在其勾选的情况下,分散加载文件是不能进行手动编辑的。当该选项不勾选时,就可以点Edit进行分散加载文件的设置了。
分散加载文件如下:
定义了一个 UNINIT 段,并指定它不被初始化。
注意:在 Arm Compiler 6 中使用的是 ".bss.NoInit",而在 Arm Compiler 5 中使用的是 zero_init。
定义变量:

验证代码同IAR,可进行复位后初始化的变量和不被初始化的变量的观察。
  3. ModusToolbox 实现变量不被初始化方法
在ModusToolbox中可以使用GNU Arm Embedded Compiler。操作与Keil中类似,需要修改linker.ld文件。linker.ld文件的路径一般如下:
MTB生成的工程中,变量SystemCoreClock就是定义在不被初始化的区域,如需加入更多变量,可在linker文件中修改no_init_size大小,利用该部分区域。
在linker文件中关于不被初始化区域的描述:

定义变量到这个不被初始化的区域:

验证代码同IAR。

使用特权

评论回复
评论
@我就是我 2024-8-1 10:45 回复TA
学习了! 
沙发
IFX-Frank| | 2024-7-15 10:55 | 只看该作者
请问首次上电时,这个值是否是乱的呢??
能否配置成,上电时初始化为0,异常复位或看门狗复位后该变量保持复位前的状态??

使用特权

评论回复
板凳
IFXNaZhang|  楼主 | 2024-7-17 13:35 | 只看该作者
是的,系统首次上电时,这些变量的值是随机的,所以如果想实现你说的效果,可以先辨别是上电,还是异常或者看门狗复位。

使用特权

评论回复
地板
ym0sly| | 2024-7-30 11:04 | 只看该作者
不同的编译环境有不同的设置方法,

使用特权

评论回复
5
梵蒂冈是神uy| | 2024-7-30 17:27 | 只看该作者
等到复位启动后可以将错误的DEBUG信息拿出来分析。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

34

帖子

0

粉丝