在项目移植、添加启动引导程序、划分闪存存储区域,或者适配不同容量芯片的时候,开发人员经常会遇到如何改动IAR链接配置文件,以及怎么解决地址冲突的问题;在IAR软件里经常被提到的链接脚本,实际上通常就是项目里用到的.icf格式的配置文件;这个文件主要负责告诉链接工具把代码放在哪里,把变量安排在什么地方,还要从哪一段内存里把栈空间和堆空间分配出来。
一、IAR链接脚本怎么修改
在对IAR链接配置文件进行修改之前,大家不要直接去改动项目目录里一眼看到的第一个.icf文件;因为很多项目里都会存在好几个配置文件,比如调试版本有一份,正式发布版本有一份,启动程序有一份,主应用程序也有一份;所以必须先弄清楚目前的编译设置到底把哪一个文件调用了。
1、找到当前使用的.icf文件
用户需要进入到【Project】菜单,接着点击【Options】,再找到【Linker】下的【Config】选项,在这里可以看到【Linker configuration file】里写明的文件路径。
这上面显示出来的路径,才是当前项目在实际中使用的链接配置文件;如果这个项目是从别的平台或者旧工程复制过来的,目录里面可能还留着好几个没用的.icf文件,要是把文件改错了,重新编译之后是不会发生任何变化的。
2、核对Flash和RAM起止地址
把.icf文件打开以后,首先要注意看存放代码的只读存储区和存放数据的运行内存区的范围定义。文件里一般会有类似于闪存起始位置、闪存结束位置、内存起始位置和内存结束位置的设置参数.这些数据必须由开发人员对照着芯片官方手册、启动引导程序的分区规划表,还有项目本身的内存设计一起查看,不能光看着芯片的总容量就随便填写。
3、修改应用程序起始地址
如果项目里面包含了启动引导程序,那么主应用程序通常就不能再从闪存的默认开头位置开始存放了;比如启动引导程序把前面的64KB空间占用了,实际的应用程序就必须从后面新的偏移位置开始摆放;在修改的时候,不仅要把.icf文件里的只读存储区起始地址改掉,还要去确认中断地址表、启动引导文件、烧录工具的地址,以及启动程序跳转的地址是不是都保持了一致;如果只是把链接脚本改了,而没有把跳转的逻辑改掉,程序最后依旧是没办法跑起来的。
二、IAR链接脚本地址冲突怎么处理
当地址冲突的问题发生以后,大家要先去观察软件弹出的报错提示,千万不能凭着感觉去把闪存改大或者去删掉变量;这种链接冲突通常意味着某一个数据块放不下了,或者是两个区域在大范围上重叠了,也有可能是固定地址被重复定义了,或者是内存里的栈空间、堆空间以及全局变量把彼此的空间给互相挤占了。
1、先判断冲突发生在ROM还是RAM
在项目编译完成之后,我们需要把.map这个地址映射报告文件打开,去查看代码存储区和运行内存区各自被占用了多少空间;如果是代码存储区装不下了,就要重点去检查代码量、常量数据、调用的库函数以及固定的闪存分区;如果是运行内存发生了冲突,就要重点去排查全局变量、定义的大数组、堆栈空间、直接内存访问缓存区还有不初始化的区域;因为代码区和内存区的问题解决办法是不一样的,绝对不能混在一起瞎改。
2、检查分区是否重叠
启动引导程序、主应用程序、参数保存区、数据备份区以及升级缓存区之间,必须被划分出清清楚楚的界限;经常容易犯的错误是,主应用程序的代码范围把参数区给覆盖掉了,或者是把参数区写在了闪存的最末尾,但是.icf文件却依然把整片闪存都分给了代码使用;这种情况在链接的时候不一定会马上表现出来,但是等程序运行起来,在保存参数的时候就会把原本的程序内容给擦除掉。
3、排查固定地址变量重复
如果我们在代码里指定了某些变量的固定位置,或者好几个功能模块都定义了自己专属的数据块,就要仔细检查这些内容有没有被错放到同一段地址里面;这些写死在固定地址的数据最好被集中放在一起管理,不要零零散散地分布在很多个.c源文件里面;否则到了后期,如果需要再增加一个新的校准表格、升级标志或者产品信息区域,就非常容易和之前已经存在的数据撞在一起。
三、修改链接脚本后还要验证哪些问题
.icf文件修改完毕并且能够编译通过,这仅仅只能说明链接工具接受了当前的内存排布方案,并不能代表程序的启动和日常运行就一定没有问题;特别是在那些带有启动引导程序、外挂闪存、双核芯片、实时操作系统或者支持在线升级的项目里,开发人员还必须在运行层面上进行反复的核对。
1、确认向量表地址是否同步
当主应用程序的起始位置发生偏移以后,中断地址表的位置也必须被同步进行处理;启动代码、系统初始化过程、启动程序的跳转逻辑以及调试工具的下载入口,这些地方都必须保持完全一致;要不然经常会碰到的古怪现象是,虽然程序能够顺利下载进去,但是芯片复位以后它就是不执行,或者是在进入主函数之前,系统就直接发生异常死机了。
2、检查.map文件里的段分布
每一次对.icf文件做出改动之后,我们都必须重新把.map文件生成出来,去确认代码段、只读数据段、变量段、清除零段、栈区、堆区以及自定义的数据块是不是都落在了原先预期的范围里;因为IAR链接工具会按照配置文件里写好的规则来摆放各个数据块,而且初始化数据还会牵扯到在闪存中的装载位置和在内存中的运行位置,所以光看一个表面地址是远远不够的。
3、验证下载和擦除范围
调试工具或者闪存算法文件的擦除范围,必须和新规划的闪存布局相匹配才行;比如某些参数区域是需要被保留下来的,那就绝对不能让下载这个动作把整片芯片都给擦除了;如果用的是外挂闪存的项目,还要去确认烧录算法是不是支持当前的芯片硬件,否则虽然链接出来的地址看起来是对的,但是在下载阶段依然会报错失败。
总结
修改IAR链接配置文件的核心,就是我们要先认准当前项目到底调用了哪一个.icf文件,然后紧紧围绕着闪存、内存、数据块摆放规则以及引导程序分区来一项项地调整;在碰到IAR链接文件地址冲突的时候,大家要先通过错误提示和编译映射报告文件,去弄明白这到底是代码区冲突、内存区冲突、区域重叠还是固定地址撞车,接着再去解决对应的区域;千万不要只是为了让项目能编译通过,就随心所欲地把地址范围改大,真正稳妥的做法是把链接文件、芯片内存、启动代码、下载参数和运行测试全都凑在一起,进行整体的检查。