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

来源:互联网 发布:软件开发 等级 编辑:程序博客网 时间:2024/05/22 06:15

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
  这还是后来我写了个文件比较程序才发现的!这两个指令对应的汇编是什么,有待查证!待续。。。。。。