Omap138開發板下以uboot2012.04.01為例分析uboot執行(二)
Omapl138記憶體和外設分佈圖
從下圖中的omapl138 top level memory map中可以看出: DSP專用的記憶體空間有: ARM專用的記憶體空間有:
Start.s程式碼分析
1.通過objdump可以檢視編譯好的反彙編程式碼,-S顯示原始碼和反彙編程式碼。
.globl _start _start: b reset c1080054<reset> c1080000 ea000013 c1080000是程式載入的地址,在MAKEFILE中定義的。 c1080054是由reset的機器指令而產生與之對應的彙編指令。 ldr pc,_undefined_instruction c1080004: e59ff014 ldr pc,[pc,#20];c1080020 <_undefined_instruction> 這句的意思是從當前跳轉20個位元組,執行_undefined_instruction。(再考慮到指令的流水線操作,要再加8,才是pc指向的位置) .global _TEXT_BASE _TEXT_BASE: .word CONFIG_SYS_TEXT(Uboot 被拷貝到DDR記憶體中的起始地址) c1080000 下面是uboot中一些段的位置 _bss_start_ofs: 0x00053da0 _bss_end_ofs: 0x00092330 _end_ofs: 0x0005adf8
2.reset指令及相關程式碼會使CPU為SVC32mode,一邊執行大多數的核心程式碼,禁止中斷和快速中斷。 3.巨集定義:CONFIG_SKIP_LOWLEVEL_INIT(ARM926EJ-S基於ARMv5TE架構)這個巨集定義在不同的boot loader中,狀況是不一樣的。它下面的函式:cpu_init_crit會執行一些非常底層的初始化過程。uboot分成了兩部分,一部分叫second program loader,一部分叫uboot的主體部分。當程式把自己載入到主記憶體DDR中執行的時候,底層的這些初始化過程就已經做了,就不需要執行這些東西了。在片內SRAM中執行的那一小段bootloader會執行這段程式碼。(bootloard引導Linux的過程如下:CPU當中固化的ROM一段小程式碼把FLASH中關於bootloader的一小段程式碼載入到RAM中,然後再把bootloader的大部分程式碼載入到RAM當中去執行。)
cpu_inti_crit()函式的作用如下:
(1) flush D Cache
(2) invalidate TLB
(3) invalidate I Cache
invalidate和flush的區別如下:
ICACHE中快取了很多條的資料,一條資料可能快取了128位,每當經過RAM讀取或者執行一條指令,都會快取到cache當中,CACHE中每條資料的最後設定了一個或者兩個位,標明這個CACHE是有效還是無效,invalidate就是把所有的這些資料條的最後一位設定位無效,就不會再從CACHE中取了,而是從RAM中取,然後放在CACHE中。flush就是把資料全部清空。
(4) disable MMU and D Cache, enable I Cache 4.
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
#ifdef CONFIG_NAND_SPL /* deprecated, use
instead CONFIG_SPL_BUILD */(沒有定義)
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#else
#ifdef CONFIG_SPL_BUILD(沒有定義)
ldr sp, =(CONFIG_SPL_STACK)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
#endif
bic sp, sp, #7 /* 8-byte alignment for ABI
compliance */彙編
ldr r0,=0x00000000
bl board_init_f
/跳轉到board_init_f/
頂層目錄下:arch/arm/lib/board.c
為什麼在呼叫C語言的函式之前要先設定好堆疊:
如果是組合語言的跳轉,把lr儲存起來即可,但是如果是向c語言的跳轉,不僅要儲存lr,比如有一個函式func(int a, int b){
int c;
char b;
…
return;
}
c語言中設定好堆疊,把第一個區域性變數放在r0中,第二個區域性變數放在r1中,把多餘的變數放在堆疊指標中,並進行下移。當把這些形參變數放完之後,把連結暫存器lr,放在緊接著的形參變數的下一個位置。然後開始放函式裡面定義的哪些變數,在函式執行完之後,通過pop指令將這些函式裡面定義的變數一個個彈出,指標就又指向了lr,然後把lr的值取出來,放回pc,就回到呼叫它的地方了。