在学习重定位时遇到的问题,先贴出代码
main.c里定义了两个字符类型的全局变量,在主函数里分别+1然后串口输出,它们链接在.data段,对.data段进行重定位,出现问题
sdram.lds
SECTIONS{
.text 0 : {*(.text)}
.rodata : {*(.rodata)}
.data 0x30000000 :AT(0x800)
{
data_load_addr = LOADADDR(.data) ;
data_start = . ;
*(.data)
data_end = . ;
}
.bss : {*(.bss) *(.COMMON)}
}
uart.c
#include "s3c2440.h"
/* 设置引脚用于串口 */
void uart0_init()
{
GPHCON &= ~((3<<4)|(3<<6)); //清空GPH2,GPH3
GPHCON |= ((2<<4)|(2<<6)); //GPH2,GPH3用于TXD1,RXD1
GPHUP &= ~((1<<2)|(1<<3)); //使能内部上拉
UFCON0 = 0x0; //不使用FIFO
UMCON0 = 0x0; //不使用流控
ULCON0 = 0x3; //设置数据格式8n1:8位数据位,无校验位,1停止位
UCON0 = 0x5; //PCLK,中断/查询模式
UBRDIV0 = 26;//( (int)(50000000/16./115200+0.5) -1 );//设置波特率 115200
}
void sdram_init(void)
{
BWSCON = 0x22011110;
BANKCON6 = 0x00018005;
BANKCON7 = 0x00018005;
REFRESH = 0x008C04F4;
BANKSIZE = 0x000000B1;
MRSRB6 = 0x00000030;
MRSRB7 = 0x00000030;
}
int putc(int c)
{
while(!(UTRSTAT0 & 0x2));
UTXH0 = (unsigned char)c;
}
int getc(void)
{
while(!(UTRSTAT0 & 1));
return URXH0;
}
int puts(const char *s)
{
while(*s)
putc(*s++);
}
main.c
#include "s3c2440.h"
#include "uart.h"
char g_c1 = 'A';
char g_c2 = 'a';
int main(void)
{
int i;
uart0_init();
sdram_init();
for(i=0;i<10;i++){
putc(g_c1);
putc(g_c2);
g_c1++;
g_c2++;
}
return 0;
}
start.s
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]
/* 设置MPLL,FCLK */
/* CLKDIVN(0x4c000014) = 0x5 */
ldr r0, =0x4c000014
ldr r1, =0x5 /* HCLK = FCLK/4 = 100 MHz , PCLK = HCLK/2 = 50 MHz */
str r1, [r0]
/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
/* 设置MPLLCON(0x4c000004) = (92<<12)|(1<<4)|(1<<0) FCLK = 400 MHz*/
ldr r0, =0x4c000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1,[r0]
/* 分辨是nand/nor启动
* 设置内存:sp 栈
*/
mov r1, #0
ldr r0, [r1] /* 读出原来的备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2?如果相等表示是nand启动 */
ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
moveq sp, #4096 /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */
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]
strb r4,[r2]
add r1,r1,#1
add r2,r2,#1
cmp r2,r3
bne cpy
/*调用main*/
bl main
halt:
b halt
我把反汇编关于重定位的一小段单独贴出来
54: e59f1034 ldr r1, [pc, #52] ; 90 <halt+0x14>
58: e59f2034 ldr r2, [pc, #52] ; 94 <halt+0x18>
5c: e59f3034 ldr r3, [pc, #52] ; 98 <halt+0x1c>
00000060 <cpy>:
60: e5d14000 ldrb r4, [r1]
64: e5c24000 strb r4, [r2]
68: e2811001 add r1, r1, #1
6c: e2822001 add r2, r2, #1
70: e1520003 cmp r2, r3
74: 1afffff9 bne 60 <cpy>
78: eb000085 bl 294 <main>
0000007c <halt>:
7c: eafffffe b 7c <halt>
80: 4c000014 stcmi 0, cr0, [r0], {20}
84: 4c000004 stcmi 0, cr0, [r0], {4}
88: 0005c011 andeq ip, r5, r1, lsl r0
8c: 40001000 andmi r1, r0, r0
90: 30000800 andcc r0, r0, r0, lsl #16
94: 30000000 andcc r0, r0, r0
98: 30000002 andcc r0, r0, r2
可以看到0x90这个地址存放的是LOADADDR(0X800)的结果,是0x30000800,这显然是不对的,用jlink下载到nor flash里运行,结果串口输出乱码
将链接脚本更改为以下代码之后正常输出
SECTIONS{
.text 0 : {*(.text)}
.rodata : {*(.rodata)}
.data 0x30000000 :AT(ADDR(.rodata)+SIZEOF(.text))
{
data_load_addr = LOADADDR(.data) ;
data_start = . ;
*(.data)
data_end = . ;
}
.bss : {*(.bss) *(.COMMON)}
}
.data段的加载地址我还尝试写成AT(ADDR(.rodata)+1)也不行
请问这是什么原因?