由於一個可執行的Image必須有一個入口點,並且只能有一個全局入口,通常這個入口放在ROM(Flash)的0x0地址,因此,必須通知編譯器以使其知道這個入口,該工作可通過修改
連接器腳本來完成。
1. board/samsung/mini2440/uboot.lds: ENTRY(_start) ==> cpu/arm920t/start.o (.text)
以下附上board/samsung/mini2440/uboot.lds源碼
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
board/samsung/mini2440/lowlevel_init.o (.text)
board/samsung/mini2440/nand_read.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
_end = .;
}
2. uboot在ram的代碼區(TEXT_BASE = 0x33F80000)定義在board/samsung/mini2440/config.mk
以下附上源碼
# SMDK2410 has 1 bank of 64 MB DRAM
#
# 3000'0000 to 3400'0000
#
# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
# optionally with a ramdisk at 3080'0000
#
# we load ourself to 33F8'0000
#
# download area is 3300'0000
#
TEXT_BASE = 0x33f80000
從上面的源碼可以看出,RAM對應的地址範圍是3000'0000 to 3400'0000(針對64MRAM)
內核將被定位在30008000,這就是爲什麼後來我們使用UBOOT下載內核要指定這個地址的原因
UBOOT在RAM中被重定向在33F8'0000
這裏可以很好的理解start.s中判斷UBOOT是在flash中運行還是在ram中運行的原理,實際上是通過對比_start和TEXT_BASE
_start是個相對地址,它的值取決於start.o的第一句代碼此時在哪個地址,如果是在flash中運行,則等於0x000000,如果是在ram中運行,則等於TEXT_BASE
start.s中把u-boot.lds定義的text段,rodata段,data段,got段,__u_boot_cmd_start段搬移到ram區的代碼如下:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
放在flash中最前面地址的,是一箇中斷向量表,當發生異常或者中斷的時候,程序講跳轉到相應的中斷向量表中,而這些表中,存放的是一些地址,程序會繼而跑到相應地址執行
相應處理程序。其中,最特別的,就是重啓,可以認爲,重啓也是一箇中斷,當發生重啓時,程序將跳轉到向量表中的第一個,也就是,地址0,如果此時是在flash中運行,則是
0x00000000,如果是在ram中運行,則是0x33f80000,而這個地址中的內容則是跳轉到_start_code:(老版本的標號是reset)
start.S最前面的代碼爲:
.globl _start
_start: b start_code
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
跳轉到start_code之後,首先執行設置ARM進入管理員模式,就是svc32模式,然後開始整個啓動過程。
1:CPU進入管理模式;
2:關看門狗和中斷;
3:CPU的初始化
4:堆棧設置
5:時鐘的初始化
6:代碼搬運到內存中