目的: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
關於相對跳轉與絕對跳轉指令的部分內容 http://www.linuxidc.com/Linux/2015-12/126807.htm