一个程序,由代码段、只读数据段、数据段、bss段等组成。
程序一开始可以烧在Nor Flash上面,运行时代码段仍可以在Nor Flash运行,但对于数据段,就必须把数据段移到SDRAM中,因为只要在SDRAM里面,数据段的变量才能被写操作,把程序从一个位置移动到另一个位置,把这个过程就称为重定位。
先梳理下把整个程序复制到SDRAM需要哪些技术细节:
把程序从Flash复制到运行地址,链接脚本中就要指定运行地址(Runtime addr)为SDRAM地址;
编译链接生成的bin文件,需要在SDRAM地址上运行,但上电后却必须先在0地址运行,这就要求重定位之前的代码与位置无关(是位置无关码写成);
参考Uboot修改链接脚本:
SECTIONS
{
. = 0x30000000;
. = ALIGN(4);
.text :
{
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) *(.COMMON) }
_end = .;
}
现在我们写的这个链接脚本,称为一体式链接脚本,对比前面的分体式链接脚本区别在于代码段和数据段的存放位置是否是分开的。
例如现在的一体式链接脚本的代码段后面依次就是只读数据段、数据段、bss段,都是连续在一起的。
分体式链接脚本则是代码段、只读数据段,中间相关很远之后才是数据段、bss段。
我们以后的代码更多的采用一体式链接脚本,原因如下:
分体式链接脚本适合单片机,单片机自带有flash,不需要再将代码复制到内存占用空间。而我们的嵌入式系统内存非常大,没必要节省这点空间,并且有些嵌入式系统没有Nor Flash等可以直接运行代码的Flash,就需要从Nand Flash或者SD卡复制整个代码到内存;
JTAG等调试器一般只支持一体式链接脚本;
修改start.S段
/* 重定位text, rodata, data段整个程序 */
mov r1, #0
ldr r2, =_start /* 第1条指令运行时的地址 */
ldr r3, =__bss_start /* bss段的起始地址 */
cpy:
ldr r4, [r1]
str r4, [r2]
add r1, r1, #4
add r2, r2, #4
cmp r2, r3
ble cpy
/* 清除BSS段 */
ldr r1, =__bss_start
ldr r2, =_end
mov r3, #0
clean:
str r3, [r1]
add r1, r1, #4
cmp r1, r2
ble clean
bl main
halt:
b halt
将修改后的代码重新编译烧写在Nor Flash上,上电运行。
对本代码的启动情况进行分析:
在生成的bin文件里,代码保存的位置是0x30000000。随后烧写到NOR Flash的0地址,但代码的结构没有变化。之后再重定位到SDRAM
查看反汇编:
3000005c: eb000106 bl 30000478 30000060: e3a01000 mov r1, #0 ; 0x0 30000064: e59f204c ldr r2, [pc, #76] ; 300000b8 <.text+0xb8> 30000068: e59f304c ldr r3, [pc, #76] ; 300000bc <.text+0xbc> 这里的bl 30000478不是跳转到30000478,这个时候sdram并未初始化; 为了验证,我们做另一个实验,修改连接脚本sdram.lds, 链接地址改为0x32000478,编译,查看反汇编: 3000005c: eb000106 bl 30000478 30000060: e3a01000 mov r1, #0 ; 0x0 30000064: e59f204c ldr r2, [pc, #76] ; 300000b8 <.text+0xb8> 30000068: e59f304c ldr r3, [pc, #76] ; 300000bc <.text+0xbc> 可以看到现在变成了bl 30000478,但两个的机器码eb000106都是一样的,机器码一样,执行的内容肯定都是一样的。 因此这里并不是跳转到显示的地址,而是跳转到: pc + offset,这个由链接器决定。 假设程序从0x30000000执行,当前指令地址:0x3000005c ,那么就是跳到0x30000478;如果程序从0运行,当前指令地址:0x5c 调到:0x00000478 跳转到某个地址并不是由bl指令所决定,而是由当前pc值决定。反汇编显示这个值只是为了方便读代码。 重点: 反汇编文件里, B或BL 某个值,只是起到方便查看的作用,并不是真的跳转。 怎么写位置无关码? 1、使用相对跳转命令 b或bl; 2、重定位之前,不可使用绝对地址,不可访问全局变量/静态变量,也不可访问有初始值的数组(因为初始值放在rodata里,使用绝对地址来访问); 3、重定位之后,使用ldr pc = xxx,跳转到/runtime地址; 写位置无关码,其实就是不使用绝对地址,判断有没有使用绝对地址,除了前面的几个规则,最根本的办法看反汇编。 因此,前面的例子程序使用bl命令相对跳转,程序仍在NOR/sram执行,要想让main函数在SDRAM执行,需要修改代码 //bl main /*bl相对跳转,程序仍在NOR/sram执行*/ ldr pc, =main/*绝对跳转,跳到SDRAM*/
上一篇:S3c2440代码重定位详解4---拷贝代码和链接脚本的改进
下一篇:S3c2440代码重定位详解6---重定位清除BSS段的C函数实现
推荐阅读最新更新时间:2024-11-16 19:52
推荐帖子
- PCB设计中遇到的一些问题整理
- PCB设计中遇到的一些问题整理谢谢你的资料最近开始用PADS,谢谢LZ的资料谢谢你的无私贡献啦,学习啦回复楼主静若幽兰的帖子
- 静若幽兰 PCB设计
- 开关电源兴趣小组 第13次任务
- 第12次思考题 本次活动要求阅读的《精通开关电源设计(第2版)》第3章3.2.5小节中给出的正激变换器变压器的设计例子中,变压器的损耗为3.131W,超出了原来2.26W的预计损耗,致使温升达到55℃,超过预定的40℃。该书也说:不可否认,仍有优化的余地。 如果要降低该变压器的损耗,你打算怎样修改设计?或者说打算怎样优化? 要降低变压器的损耗,无非是降低变压器的铁损或者变压器的铜损。 要降低变压器的铁损,就要降低铁芯中的磁通密度,或者降低工作频率。降低工作频率
- maychang 开关电源学习小组
- 是德科技有奖直播:如何让你的Wi-Fi测试“兔”飞猛进?报名中
- 是德科技有奖直播:如何让你的Wi-Fi测试兔飞猛进?报名中点击报名直播直播时间:2023年03月01日(周三)下午14:00-15:30直播主题:如何让你的Wi-Fi测试兔飞猛进?直播简介:兔年归来,返工的攻城狮们看过来!虽然物联网设备提供了极大的便利,但要在狭小的空间内容纳大量设备,会导致设备设计、测试、性能和安全防护变得非常复杂。如何测试这些器件是设计工程师和器件制造商面临的一个最大挑战正因为射频环境非常拥挤,因此一定要进行合规性测试
- EEWORLD社区 综合技术交流
- 单片机控制TC35i GSM 模块的问题
- 单片机控制TC35iGSM模块的问题单片机发给模块的每句AT指令结束的回车在c语言里面要怎么表示,\\r还是\\r\\n还是什么比如我是直接puts(AT\\r);的。然后单片机连接模块后发不了短信,求解释单片机控制TC35iGSM模块的问题如果你不确定是\\r还是\\n那么你都写上就可以然后单片机连接模块后发不了短信,求解释?你都用了哪些命令,回复的内容是什么,你说一下我就知道怎么回答你了二种方式发送短信:1:文本方式2:PDU编码方式 回复楼主chao
- chaosyp 嵌入式系统
- 雨伞在高压线下放电,毛骨悚然
- 今天下大雨之后下班回家路上打着伞经过了一条高压线路的下方,突然听到一阵奇怪的滋滋声,有点像静电放电的声音,然后我抬头一看发现伞骨的位置真的有一个电火花在晃来晃去,还以为是雷电要来了,吓得我赶紧加快了脚步。然后想起来好像不是这么回事,其实每次下雨天打伞经过高压线都有类似的现象,网上看到有人说这个是因为下过雨空气湿度大,上面的高压线有很强的电场,空气变得有了一点导电性,伞骨尖端放电,电流流过空气就会看见电弧。然后还有人说,这样的现象虽然不是雷电引起的,但是被电离的空气会形成一条低阻抗的路径,更容易
- Nubility 综合技术交流
- 【AT32A403A 车规MCU开发板】 SPI-DMA方式驱动LCD
- 测试SPI-DMA方式驱动LCD显示屏。一、硬件部分测试使用SPI1接口二、程序部分2.1、SPI初始化部分#include"main.h"uint16_t*lcd_data_buf;//LCD_RS--D7//LCD-RST--D6//LCD-CS--D10//LCD-BK--A3//TP-CS--D8//TP-INT--D9/***@briefinitializelcdspi1
- TL-LED 汽车电子
设计资源 培训 开发板 精华推荐
- INA219模块
- ADR441B 2.5 Vout 超低噪声、LDO XFET 电压基准的典型应用,具有电流吸收器和电流源
- 最丐61+3键机械键盘(外观)
- DC782A-H,LTC2227IUH 演示板,高速 ADC,VDD = +3.0V,40 Msps,12 位 1MHz
- AD8314-EVAL,AD8314 评估板,100MHz 至 2.7GHz,45dB 射频检波器/控制器
- LT1934IS6 环路供电 3.3V 电源的典型应用电路,具有额外的隔离输出
- 具有短路保护功能的 MC78M08CTG 8V 电流升压的典型应用
- 便携式辅助电源
- 使用 NXP Semiconductors 的 PCF8881 的参考设计
- AM1G-0518DZ ±18V 1 瓦 DC/DC 转换器的典型应用