程序主要运行过程:NAND flash启动,加载4K到片内sram,利用这4K代码,完成将这4K代码拷贝到SDRAM,并运行(这个程序小于4K)。
主程序:
.text
.global _start
_start:
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
bl memsetup @ 设置存储控制器
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
on_sdram:
ldr sp, =0x34000000 @ 设置堆栈
bl main
halt_loop:
b halt_loop
Makefile 版本1:
sdram.bin : head.S leds.c
arm-linux-gcc -c -o head.o head.S
arm-linux-gcc -c -o leds.o leds.c
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
arm-linux-objcopy -O binary -S sdram_elf sdram.bin
arm-linux-objdump -D -m arm sdram_elf > sdram.dis
clean:
rm -f sdram.dis sdram.bin sdram_elf *.o
反汇编版本1:
30000000 <_start>:
30000000: eb000005 bl 3000001c <disable_watch_dog>
30000004: eb000010 bl 3000004c <memsetup>
30000008: eb000007 bl 3000002c <copy_steppingstone_to_sdram>
3000000c: e59ff090 ldr pc, [pc, #144] ; 300000a4 <mem_cfg_val+0x34>
30000010 <on_sdram>:
30000010: e3a0d30d mov sp, #872415232 ; 0x34000000
30000014: eb000039 bl 30000100 <main>
30000018 <halt_loop>:
30000018: eafffffe b 30000018 <halt_loop>
..................
300000a4: 30000010 andcc r0, r0, r0, lsl r0
..................
Makefile 版本2:
sdram.bin : head.S leds.c
arm-linux-gcc -c -o head.o head.S
arm-linux-gcc -c -o leds.o leds.c
arm-linux-ld -Ttext 0x00000000 head.o leds.o -o sdram_elf
arm-linux-objcopy -O binary -S sdram_elf sdram.bin
arm-linux-objdump -D -m arm sdram_elf > sdram.dis
clean:
rm -f sdram.dis sdram.bin sdram_elf *.o
反汇编版本2:
00000000 <_start>:
0: eb000005 bl 1c <disable_watch_dog>
4: eb000010 bl 4c <memsetup>
8: eb000007 bl 2c <copy_steppingstone_to_sdram>
c: e59ff090 ldr pc, [pc, #144] ; a4 <mem_cfg_val+0x34>
00000010 <on_sdram>:
10: e3a0d30d mov sp, #872415232 ; 0x34000000
14: eb000039 bl 100 <main>
00000018 <halt_loop>:
18: eafffffe b 18 <halt_loop>
..............................
a4: 00000010 andeq r0, r0, r0, lsl r0
..............................
在链接地址为0x00000000和0x30000000的情况下产生的反汇编除了程序应该运行的地址是完全一样的。这也是
在Makefile中-Ttext 指定的链接地址。这就是 ldr pc, =on_sdram在片内4K代码段内能跳转到SDRAM中的原因。
从反汇编的
3000000c: e59ff090 ldr pc, [pc, #144] ;300000a4 <mem_cfg_val+0x34>
300000a4: 30000010 andcc r0, r0, r0, lsl r0
和
c: e59ff090 ldr pc, [pc, #144] ;a4 <mem_cfg_val+0x34>
a4: 00000010 andeq r0, r0, r0, lsl r0
可以看出:
on_sdram标号代表的是程序应该在的地址(即链接地址),而不是代码当前实际在的地址(片内4K代码段)。
指定-Ttext0x30000000时,ldr pc, =on_sdram 即是把0x30000010赋给PC,实现程序跳转到SDRAM中运行。
指定-Ttext0x00000000时,ldr pc, =on_sdram 即是把0x00000010赋给PC。
而 bl 是通过代码的相对位移(编译时自动计算)进行跳转,所以能在片内4K代码段内跳转到后面的代码段。
比如:30000004: eb000010 bl 3000004c,那么差即是3000004c-30000004=48
同理:00000004: eb000010 bl 0000004c,那么差即是0000004c-00000004=48
两者是一样的。