U-boot-2009.03移植之六:對一些關鍵標號的理解以及start.s中代碼重定向原理

 

由於一個可執行的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:代碼搬運到內存中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章