徽州骆驼 · 7月19日

IAR的变量初始化浅析

目录

1.问题分析和解决

2.初始化变量的方法

3.使用JLINK RTT实现串口功能

Hi,大家好,今天是落汤的肌肉,因为这天像是漏了一样。

昨天的文章最后留了一个小坑,今天把他填了。再赠送一段使用JLINK RTT串口模拟,这样在调试时节省一个串口资源。

1.问题分析和解决

在IAR工程里不使用__iar_program_start,发现会产生如下错误:

image.png

它需要使用__iar_data_init3来初始化.bss段;

这就奇怪了,既然都没有使用IAR的初始化,理应这后续代码不会参与编译呀。

但事实如此,还是分析分析问题。

经验告诉我这种 no reference的问题多半是发生在链接阶段,因此最先想到的是在链接器上找问题。

IAR ILINK linker的流程如下:

image.png

其中与初始化相关联的就是可以通过特定标识符 initialize 让Linker安排启动代码对变量或者代码进行初始化(from ROM to RAM)。

该标识符用在IAR链接文件ICF(ILINK configuration file),语法如下:

image.png

其中,

  • 参数 by copy:在应用启动前由启动代码estartup里自动进行初始化;
  • 参数 manually:在应用启动前由启动代码不会自动进行初始化,需要自行进行初始化;

by copy所谓自动初始化,个人理解就与使用__iar_program_start作为entry有关,在之前编译生成的mpa文件里,我看了一个所谓的INIT TABLE,如下:

image.png

这样一下就清晰了,我们仔细看上述编译错误,它说的是需要使用__iar_data_init3这个函数来初始化.bss这一段。而INIT TABLE里应该是存放与编译器自带cstarup启动流程相关的函数等,所以会报这个错误;但是我们看到这里面包含了zero init,难道说initialize这个对需要初始化0的段是没有影响的?导致Linker继续默认使用内置库来进行bss段的初始化?

最终在手册上找到这样一段话:

Zero-initialized sections are not affected by the initialize directive.

果真如此,那谁能影响它呢?在开发手册530页,我找到了答案--特定标识符:do not initialize

该标识符主要就是用来指定哪些section不想自动初始化为0,并且只对zeroinit section有效,如下:

image.png

那么哪些section是zero-initiized?在IAR里,很明显是.bss段和.tbss段:

image.png

所以,我们在icf文件里添加这样一段话:

do not initialize {section .bss};

再进行编译,没有报错了:

image.png

2.初始化变量的方法

上面讲到了既然不用__iar_program_start,那肯定是想用自己的初始化代码来搞了,这样做就是为了平台移植起来方便。

所以我们可以用标识符initialize manually来告诉linker:你不要多管闲事,我自己会初始化变量的。

最简单的语法就是 initialize manually { section MYSECTION };那么代码里如何使用呢,如下:

#pragma section = "MYSECTION"
#pragma section = "MYSECTION_init"
void DoInit()
{
char * from = __section_begin("MYSECTION_init");
char * to = __section_begin("MYSECTION");
memcpy(to, from, __section_size("MYSECTION"));
}

针对.bss段来说,使用 do not initialize表示对.bss段进行手动初始化。这就没什么好说。

3.使用JLINK RTT实现串口功能

JLINK RTT全称Real Time Transfer,可以从目标MCU输出信息,也可以以非常高的速度向应用程序发送输入;它利用debug接口,如JTAG\SWD(2pin)、英飞凌SPD接口等来实现串口功能,逻辑如下:

image.png

 该模块的代码移植性非常强,我们可以在JLINK安装目录下找到对应源码,如下:

image.png

我们只需要将该目录下红框内文件(共计5个),添加到我们自己的工程里即可:

image.png

参考代码更简单了,只需要包含头文件,#include "SEGGER_RTT.h",调用初始化就可以开始打印了,如下:

image.png

在PC端,我们使用 J-LINK RTT Viewer进行数据接收和发送,如下:

image.png

注意,RTT Control block的搜寻地址范围需要根据工程编译出map文件进行定位,如下图:

image.png

连接成功后,我们可以看到终端正常显示信息,如下:

image.png

END

作者:快乐的肌肉
来源: 汽车MCU软件设计

推荐阅读:

更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
5726
内容数
470
汽车电子与软件行业的相关技术报道及解读。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息