目的:Norflash前4K的内容到SDRAM,并且成功点亮LED;
过程:
1.程序(main.c startup.s Makefile)
1.1.main.c
#define GPBCON (*(volatile unsigned long*)0x56000010)
#define GPBDAT (*(volatile unsigned long*)0x56000014)
#define GPB_OUTPUT 01
#define GPB_CONFIG(IO,CONFIG) (CONFIG << (IO*2))
int main()
{
GPBCON |= GPB_CONFIG(5,GPB_OUTPUT)
| GPB_CONFIG(6,GPB_OUTPUT)
| GPB_CONFIG(7,GPB_OUTPUT)
| GPB_CONFIG(8,GPB_OUTPUT);
GPBDAT = 0X00000000;
return 0;
}
1.2.startup.s
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text
.global _start
_start:
bl disable_watch_dog
bl sdram_init
bl copy_steppingstone_to_sdram
ldr pc, =on_sdram
on_sdram:
ldr sp, =0x34000000
bl main
halt_loop:
b halt_loop
disable_watch_dog:
mov r1, #0x53000000
mov r2, #0x0
str r2, [r1]
mov pc, lr
copy_steppingstone_to_sdram:
mov r1, #0
ldr r2, =SDRAM_BASE
mov r3, #1024*4
1:
ldr r4, [r1],#4
str r4, [r2],#4
cmp r1, r3
bne 1b
mov pc, lr
sdram_init:
mov r1, #MEM_CTL_BASE
adrl r2, mem_cfg_val
add r3, r1,#52
1:
ldr r4, [r2],#4
str r4, [r1],#4
cmp r1, r3
bne 1b
mov pc, lr
.align 4
mem_cfg_val:
.long 0x22011110;
.long 0x00000700;
.long 0x00000700;
.long 0x00000700;
.long 0x00000700;
.long 0x00000700;
.long 0x00000700;
.long 0x00018005;
.long 0x00018005;
.long 0x008c07a3;
.long 0x000000b1;
.long 0x00000030;
.long 0x00000030;
1.2.1.关看门狗;
1.2.2.初始化SDRAM;
1.2.3.复制Norflash前4K内容到SDRAM;
1.2.4.设置栈;
1.2.5.跳转到main
1.3.Makefile
Main.bin : startup.s main.c
arm-linux-gcc -g -c -o startup.o startup.s
arm-linux-gcc -g -c -o main.o main.c
arm-linux-ld -Ttext 0x30000000 startup.o main.o -o main_elf
arm-linux-objcopy -O binary -S main_elf main.bin
clean:
rm -f main.bin main_elf *.o
2.startup.s详解:
编译链接出来的文件main.bin是烧录到Norflash中0x00000000地址开始的一片内存,但是Makefile中指定的代码段链接地址为0x30000000,代码是如何被执行的?
位置无关的相对跳转指令概念:
1.位置无关的程序跳转。使用相对跳转指令实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。
2.位置无关的常量访问。在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。为增强程序的可读性,利用EQU伪指令对一些常量进行赋值,但在访问过程中,必须实现位置无关性。
3.使用绝对地址进行跳转,一般是在不同的位置无关代码段之间跳转。
代码:
bl disable_watch_dog //链接地址:0x30000000,位置无关型
bl sdram_init //链接地址:0x30000004,位置无关型
bl copy_steppingstone_to_sdram //链接地址:0x30000008,位置无关型
ldr pc, =on_sdram //链接地址:0x3000000b
on_sdram: //链接地址:0x30000010
ldr sp, =0x34000000
bl main
所以, 代码是经过一系列动作之后再跳转到0x30000010处的.其中经过关看门狗,初始化SDRAM,复制内容, 然后跳转,最后执行main函数中的点亮LED操作。
具体参考:
《嵌入式Linux应用开发完全手册》 http://www.linuxidc.com/Linux/2011-01/31114.htm
程序运行地址和加载地址-为什么使用位置无关指令 http://www.linuxidc.com/Linux/2015-12/126806.htm