您的位置:首页 > 编程语言

ARM的step内存到SDRAM内存代码复制程序调试之罪魁祸首 ADR与LDR

2012-12-15 16:04 92 查看
start.S启动的汇编代码
#define S3C2440_MPLL_200MHZ ( (0x5C<<12)|(0x01<<4)|(0x02) )
#define MEM_CTL_BASE 0x48000000
.text
.global _start
_start:
/*1关看门狗*/
mov r0,#0x53000000
mov r1,#0
str r1,[r0]

/*2设置时钟*/
ldr r0,=0x4C000014
mov r1,#0x03
str r1,[r0]

mrc p15,0,r1,c1,c0,0
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0
ldr r0,=0x4C000004
ldr r1,=S3C2440_MPLL_200MHZ
str r1,[r0]
/*3初始化SDRAM*/
mov r0,#MEM_CTL_BASE
adr r1,sdram_config
add r3,r0,#(13*4)
1:
ldr r2,[r1],#4
str r2,[r0],#4
cmp r3,r0
bne 1b
/*4重定位:把代码从0内存复制到它的链接地址去*/
mov r0,#0;
ldr r1,=0x33f80000
mov r2,#4096
1:
ldr r3,[r0],#4
str r3,[r1],#4
cmp r2,r0
bne 1b
/*清bss段*/
/*5执行main函数*/
ldr sp,=0x34000000
ldr pc,=main
sdram_config:
.long 0x22011110
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00018005
.long 0x00018005
.long 0x008C04F4
.long 0x000000B1
.long 0x00000030
.long 0x00000030
init.c测试文件
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)

void delay(unsigned long dly)
{
for(;dly>0;dly--);
}

int main()
{
int i=0;
GPBCON = 1<<5*2 | 1<<6*2 | 1<<7*2 | 1<<8*2;
while(1)
{
delay(100000);
GPBDAT =(~(i<<5));
++i;
i %= 16;
}
return 0;
}
链接脚本
SECTIONS{
. = 0x33f80000;
.text : {*(.text)}

. = ALIGN(4);
.rodata : {*(.rodata*)}

. = ALIGN(4);
.data : {*(.data)}

. = ALIGN(4);
__bss_start = .;
.bss : {*(.bss) *(COMMON)}
__bss_end = .;
}
Makefile
objs := start.o init.o
boot.bin:$(objs)
arm-linux-ld -Tboot.lds -o boot_elf $^
arm-linux-objcopy -O binary boot_elf $@
arm-linux-objdump -D -m arm boot_elf >boot.dis
%.o : %.S
arm-linux-gcc -c -o $@ $<
%.o : %.c
arm-linux-gcc -c -o $@ $<
clean:
rm -f *.bin boot_elf *.o *.dis
调试了一个下午,在这段程序的运行过程中,发现程序总是无法点亮LED,也就是程序根本就没有
运行到main函数中。然后我就从后向前去找程序可能的出错地点。
1,刚开始 我怀疑是ldr pc,=main这句指令没有跳到地方。后来换用bl main。发现还是一样的结
果。查看反汇编,发现指令也是跳到了指定的位置了。于是,继续向上找。
2,后来觉得是不是/*2设置时钟*/ 这个有问题,于是把这段删除了,然后问题依然没有解决!
3,排除法,问题可能出在/*3初始化SDRAM*/!!!!但是查看反汇编,也没有找到问题的所在!
最后,通过对比以前写的汇编程序发现,程序的28行(原来写的是ldr r1,=sdram_config)改成
adr r1,sdram_config后程序正常了!
后来我在网上搜了下:ldr和adr的区别主要就是地址的位置无关性的差别。ldr伪指令操作,
一旦实际运行物理地址和期望运行物理地址存在差别,那就会造成程序运行错误。虽然adr有
这么多优点,但是adr的寻址空间只有前后4kb,而且必须在同一个代码段中,ldr就没有这些
要求。
我查看了这分别包含两条指令的程序的反汇编,也没有发现有什么大的分别!
比较搞笑的是这两都反汇编出的代码是一样的!但是两都的二进制文件却是不一样的
当使用adr对应的这个二进制指令为: e28f1034
当使用ldr对应的这个二进制指令为: e59f1074
这还是后来我写了个文件比较程序才发现的!这两个指令对应的汇编是什么,有待查证!待续。。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: