1. 程式人生 > >Omap138開發板下以uboot2012.04.01為例分析uboot執行(二)

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,就回到呼叫它的地方了。