历史上的今天
今天是:2024年09月09日(星期一)
2021年09月09日 | S3c2440代码重定位详解2---链接脚本的引入与简单测试
2021-09-09 来源:eefocus
前面程序运行,发现从Nand Flash启动和从Nor Flash启动表现是不一样的。
设置成Nand Flash启动没有问题 显示ABCDE…
设置成NOor Flash启动则显示AAA…
这是什么原因呢?
Nor启动

Nor Flash就被认为是0地址,g_Char被放在0x700后面。CPU上电后从0地址开始执行,它能读取Nor Flash上的代码,打印出A,当进行g_Char++的时候,写操作操作无效,下次读取的数据仍然是A。
NAND启动

上电后,Nand Flash前4K代码就被自动的复制到SRAM里面,SRAM是CPU认为的0地址。CPU上电后从0地址开始执行,它读取SRAM上的代码,并g_Char++修改变量,下次读取的数据就依次增加了
为了解决Nor Flash里面的变量不能写的问题,我们把变量所在的数据段放在SDRAM里面,看行不行。
修改Makefile 指定数据段为0x30000000 -Tdata 0x30000000:
arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf
这样的话编译出来的bin文件 从0地址 到 0x30000000地址 文件大小有700多MB,代码段和数据段直接有间隔,称之为黑洞

解决黑洞有两个办法:
第一个方法:
①把数据段的g_Char和代码段靠在一起
②烧写在Nor Flash上面
③运行时把g_char(全局变量)复制到SDRAM,即0x3000000位置(重定位);
第一种办法如何实现
修改Makefile的代码段地址,使用链接脚本sdram.lds指定。
注释:#arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf
修改为: arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf
链接脚本的语法:
SECTIONS {
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region :phdr =fill
...
}
我们需要依次排列 代码段、只读数据段、数据段、.bss段、.common。
其中数据段放在0x800,但运行时在0x3000000:
SECTIONS {
.text 0 : { *(.text) }//所有文件的.text
.rodata : { *(.rodata) } //只读数据段
.data 0x30000000 : AT(0x800) { *(.data) } //放在0x700,但运行时在0x3000000
.bss : { *(.bss) *(.COMMON) }//所有文件的bss段,所有文件的.COMMON段
}
重新编译后烧写bin文件,发现启动后显示乱码。原因是我们从0x30000000处获取g_Char,但在这之前,并没有在0x30000000处准备好数据。因此需要重定位数据段,将0x700的数据移动到0x30000000处,在start.S加入:
bl sdram_init
/* 重定位data段 */
mov r1, #0x700
ldr r0, [r1]
mov r1, #0x30000000
str r0, [r1]
bl main
上面的这种方法,只能复制0x800处的一位数据,不太通用,下面写一个更加通用的复制方法:
链接脚本修改如下:
SECTIONS {
.text 0 : { *(.text) }
.rodata : { *(.rodata) }
.data 0x30000000 : AT(0x700)
{
data_load_addr = LOADADDR(.data);
data_start = . ;//等于当前位置
*(.data) //等于数据段的大小
data_end = . ;//等于当前位置
}
.bss : { *(.bss) *(.COMMON) }
}
修改start.S
bl sdram_init
/* 重定位data段 */
ldr r1, =data_load_addr /* data段在bin文件中的地址, 加载地址 */
ldr r2, =data_start /* data段在重定位地址, 运行时的地址 */
ldr r3, =data_end /* data段结束地址 */
cpy:
ldrb r4, [r1] //从r1读到r4
strb r4, [r2] //r4存放到r2
add r1, r1, #1 //r1+1
add r2, r2, #1 //r2+1
cmp r2, r3 //r2 r3比较
bne cpy //如果不等则继续拷贝
bl main
第二个方法
①让文件直接从0x30000000开始,全局变量在0x3……;
②烧写Nor Flash上 0地址处;
③运行会把整个代码段数据段(整个程序)从0地址复制到SDRAM的0x30000000(重定位);
这两个方法的区别是前者只重定位了数据段,后者重定位了数据段和代码段。
史海拾趣
|
MCU的未来之路如何发展? 微控制器(MCU)在实际应用、处理能力、架构以及与ASIC和SoC等其它半导体产品的融合方面已经有了很大的发展。那么,MCU未来还存在哪些挑战、又将如何发展呢?微控制器用户需要在越来越全球化及竞争日益激烈的环境中努力求生 ...… 查看全部问答> |
|
大家好,我想请教一个问题,我的低通滤波器工作正常,滤波效果还可以,信号直接接放大器,放大也正常,可把滤波器和放大器都接上后,放大器就不工作了,但滤波器能工作,谁知道这是什么原因啊?(放大器在滤波器后面),谢谢啊。下面是电路图:… 查看全部问答> |
|
Infineon - New .XT-technology from Infineon Significantly Increases Lifetime of IGBT Modules and Opens the Path for Higher Junction Temperature up to 200°C Infineon Technologies introduced an innovative IGBT internal packaging te ...… 查看全部问答> |
|
1、网络芯片换了,重新写了网络驱动,请问一下怎么样把这个网络驱动编译到linux内核中去?内核是2.6.30版本的。2、板子上有两个串口,有一个能用,另一个不能用,然后又重新写了另一个串口的驱动,这样把它编译到内核中是不是就可以使用第二个串口 ...… 查看全部问答> |
|
在这里先感谢下ID:wangjiafu1985 无私提供Keil 软件!可是这个用注册机注册了 还是提示2KB程序编译是出现警告,程序下载到实验板能正常工作,但是你们都是这样无视这个提示的吗? 有解决的办法吗? … 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 02:59 编辑 求助MSP430F149,金属物体探测定位器的程序代码 … 查看全部问答> |




