关于TI-ARM的代码重定位

	最近在使用TI的J7系列的一块处理器,由于需要使用nor flash的XIP模式,就研究了一下代码重定位的问题,在网上找了很多资料,学到了很多,接下来做一个总结吧。
	首先,代码重定位的目的:一个完整的程序分为.data、.text.、.bss、..stack等,如果使用xip运行的话只有.text在nor flash中run,.data在SRAM里边run,但是保存在nor flash中。在lds(链接文件)中如果直接把.data设置到SRAM的地址,生成的bin文件很很大,比如我现在用到的地址SRAM = 0x51c00000 ,length = 0x9000;nor flash的地址 = 0x600e0000 ,length = 0x20000,这样算下来生成的bin文件大小大概为:0x600e0000+0x20000-0x51c00000 = 0xe500000=240123904 = 229M;为什么这么大,我用的空间加起来也没这么多啊?因为在elf文件转bin的过程中是不管你实际使用的大小的,转换器只在意你的起始地址和结束地址,然后中间没用的地方补0,为了解决这个问题就使用到了重定位的概念。
	重定位的概念简述:一段程序,.data/.text可以分为load address(加载地址)和run address(运行地址),如果使用XIP模式.txet段的load address = run address,但是.data段的load address必须在nor flash,run address必须要在SRAM中。重定位就是让程序在运行中使用的是run address,但是在存储的时候使用的是load address。
	如何实现?
	具体的实现分为两步:
	1、lds文件进行设置
	2、main函数之前或者main函数的第一条指令进行数据copy
	具体例子实现:
	由于使用的是TI的ARM处理器,使用的是CCS下边的CGT_ARM_V20.0.0.LTS(具体名字忘记了)编译器,所以需要根据TI的规则来编写lds文件,废话少说,直接上干货!!!!
	SRAM : (RW) origin = 0x51c00000, length = 0x9000
	XIP_FLASH : (R) origin = 0x600e0000,length = 0x20000	
	.data : LOAD = XIP_FLASH, RUN = SRAM, align(4)
	{
	      .=align(4);
	      *(.data)
	      .=align(4);	
	 } LOAD_START(_load_data_start),
	  LOAD_SIZE(_load_data_size),
	  LOAD_END(_load_data_end),
	  RUN_START(_run_data_start),
	  RUN_SIZE(_run_data_size),
	  RUN_END(_run_data_end),
	  align(4)

分析
.data : 定义一个.data段;
LOAD = XIP_FLASH, RUN = SRAM, align(4):.data段的load address在XIP_FLASH中,run address在SRAM中,以四字节方式对齐;
.=align(4):.data段使用4字节对齐的方式;
*(.data):程序中所有的全局变量都存储在data段;
.=align(4):同上;
LOAD_START(_load_data_start):LOAD_START是链接器的保留字,作用是在map文件中会生成_load_data_start字符,该字符的值代表.data段在nor flash中存储的起始地址,可以在代码中使用;
LOAD_SIZE(_load_data_size):同上,该字符的值代表.data段在nor flash中存储的空间大小;
LOAD_END(_load_data_end):同上,该字符的值代表.data段在nor flash中存储的结束地址;
RUN_START(_run_data_start):同上,该字符的值代表.data段在SRAM中运行的起始地址;
RUN_SIZE(_run_data_size):同上,该字符的值代表.data段在SRAM中运行的空间大小;
RUN_END(_run_data_end):同上,该字符的值代表.data在SRAM中运行的结束地址;
align(4):以4字节地址对齐;
以上,lds文件编写完成。进入第二步!!
第一步生成相应的地址字符之后就需要在代码中进行copy了。对应的copy代码如下:

/* Symbol variable */
extern uint32 _load_data_start;
extern uint32 _load_data_size;
extern uint32 _load_data_end;
extern uint32 _run_data_start;
extern uint32 _run_data_size;
extern uint32 _run_data_end;
/* Function prototype */
void Start_SectionDataCopy(uint32 *runStart, uint32 *loadStart, uint32 *loadEnd)
{
	while(loadStart<loadEnd)
	{
		*runStart++ = *loadStart++
	}
	
}
/* Call copy function */
Start_SectionDataCopy(&_run_data_start, &_load_data_start, &_load_data_end);

以上,记录一下!

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值