IAR中Overlay和manual initialization的使用技巧

4 篇文章 1 订阅
1 篇文章 0 订阅

IAR中Overlay和manual initialization的使用技巧

需求导入

经常做嵌入式开发的同学们肯定熟悉Keil MDK和IAR这两个IDE,在相对简单的MCU开发中非常常见,而还有些同学可能经常进行嵌入式Linux上的开发,那么GCC则更为熟悉。因为个人工作学习需求,我主要使用的开发工具链是GCC和IAR。最近收到了有这么需求:

我们使用的某一代芯片(MCU级别)上,大多数代码段均通过BootLoader搬运到SRAM中运行,但也可以将一部分代码放置在flash中直接运行,那么在flash中的代码映射到系统map的基地址为0x1fbb0000,因此我们需要指定一个特殊的数据段即.text_in_flash段,将它的VMA(Run Memory Address)指定到该区域,而LMA(Load Memory Address)可以放置在普通的text段之后地址并且和HEAP内存复用,因为系统启动加载后进入main后才会使用HEAP区域,这样可以节约不少空间。并且我们还注意到一个情况,那就是当程序在非jtag调试模式下通过BootLoader直接加载运行时,这段Load Memory Address内的数据完全没必要加载到flash中,因为程序原本就在flash内,而在jtag调试模式下,则需要将Load Memory Address写入到对应的flash地址以使程序正确运行。
这里描述的有点绕,可以参考下图示说明:
在这里插入图片描述

如果熟悉linux内核开发的同学看到上述需求想必已经知道如何实现了,只需要编写好lds链接脚本,标记好代码段LMA和VMA起始结束地址,在进入main函数之前完成对flash的数据初始化操作即可搞定,这种链接脚本的技巧使用在linux内核中使用的简直登峰造极。但这并不是本文的重点,因为最近我拿到的需求是在我们另一款芯片上完成相同的操作,唯一不同的情况上这款芯片使用IAR的编译环境,众所周知,IAR是一款商业编译器,它的链接脚本与GCC不同是一种后缀为ICF的文件,其语法也与GCC完全不同,况且IAR的数据段初始化是由链接器产生的,而且还使用LZ77的压缩方式进行了压缩,那么如何完成上述需求呢?

资料查找

经过一番查找我们在IAR官网上找到了这样一篇文章
Technical Note 36546
其核心内容就是使用Overlay和manual initialization方式自定义一部分数据/代码段的初始化方式,那我们就来分析使用这种方式如何实现我们需求。

实践解决

首先打开icf文件,一般来讲在iar中运行地址和加载地址不一致的数据段都需要一段搬运工作,iar给出的默认写法是:

initialize by copy { readwrite };
place in RAM_region   { readwrite,  block CSTACK};

这个例子表明readwrite段运行地址在RAM_region区域,而加载地址由链接器自动指定到所有ro段的尾部,且使用iar的__iar_data_init3函数来实现搬运。

而我们目前需求是定义一个text_in_flash的段,且不用__iar_data_init3函数加载而是我们的自定义函数加载,并且不需要压缩,写法如下:

define overlay text_in_flash_overlay { section text_in_flash };
initialize manually with packing = none, copy routine = __low_level_init_in_flash_code { section text_in_flash };

这第一行定义overlay是为了显式指定这个数据段的运行地址,且可以通过C代码访问数据段加载地址和运行地址,写法如下:

place at address mem: __region_FHEAP_start__+__region_CODE_IN_FLASH_start__ { overlay text_in_flash_overlay };

自定义函数__low_level_init_in_flash_code用来加载代码,对应的加载地址和运行地址获取方式如下:

/* 用于flash中运行代码的搬运工作,特殊技巧请查阅iar官网:Technical Note 36546 */
#pragma section = "text_in_flash_init"
#pragma section = "text_in_flash_overlay"
extern void __low_level_init_in_flash_code(uint32_t _data_lma, uint32_t text_in_flash_start, uint32_t text_in_flash_end);
    __low_level_init_in_flash_code(
              (uint32_t)__section_begin("text_in_flash_init"),
              (uint32_t)__section_begin("text_in_flash_overlay"),
              (uint32_t)__section_begin("text_in_flash_overlay") + (uint32_t)__section_size("text_in_flash_overlay")
             );

然后实现这个函数的具体内容即可。可以看到iar的中的自定义加载机制还是比较晦涩的,其icf语法有一些固定的使用要求和写法,而不像GCC中lds那么自由的编写,当然一般的MCU往往也不需要这么复杂的加载机制,所以iar将更多的功能都预设了,可扩展性就没有那么强了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quard_D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值