U-Boot啓動的函數調用過程(以arm926ejs爲例)

調用鏈如下,後面是文字解說:

 reset -> cpu_init_crit -> lowlevel_init (板子相關)
           -> relocate (將U-boot重定位到RAM)
           -> stack_setup
           -> clear_bss
           -> start_armboot() (C程序) -> main_loop()

 

系統上電覆位後首先跳轉到一個指定的地址,ARM的話是0x00000000地址,即通常所說的復位異常向量地址。然後在這裏存放了一條指令b reset,即跳轉到reset過程執行。至於怎麼把這條指令放在這裏則是鏈接過程指定的。

reset過程會將首先將CPU設定爲SVC32模式,然後調用cpu_init_crit過程,這個過程對Cache和MMU進行一些操作,主要是沖刷Cache和關閉Cache和MMU。爲什麼要做這些呢,這主要是爲了將CPU設定到一個確定的狀態,因爲啓動的時候CPU處於什麼狀態是未知的,Cache裏面的內容也是不確定的,如果不關閉的話,可能會讓CPU取到錯誤的指令。

然後它會調用lowlevel_init過程,注意lowlevel_init過程是與特定板子相關的,是移植時需要實現的過程。它位於./board/<board_name>/lowlevel_init.S文件中,主要是初始化一些板上的硬件控制器等,lowlevel_init結束後返回cpu_crit_init, cpu_crit_init返回到reset,然後接着執行。

接下來要執行的是relocate過程,它負責把U-Boot從Flash從定位到RAM中,執行完之後接下來依次執行stack_setup,clear_bss。

這兩個都執行完畢,執行一條跳轉指令(採用ldr pc, <addr>的形式)跳轉到start_armboot執行。

 

在start_armboot之前都是arm彙編代碼,從start_armboot開始就進入了C語言過程。它按照順序執行一大堆初始化任務,這個和Linux內核的start_kernel有類似的地方。最後它調用main_loop()進入這麼個死循環中,此後的事情就暫且先不關心了。

 

關於relocate

這個直譯叫重定位,另外有一個remap,直譯爲重映射,要注意這兩者是不一樣的,這裏現來看看重定位。

首先,系統啓動時U-Boot的代碼是在FLASH上面的,所以在relocate之前的所有代碼都是在flash上面執行的,而且所有代碼都是位於FLASH上的。而relocate則是把FLASH上的的代碼搬移到RAM中。但是怎麼保證relocate之後執行的是RAM中的代碼而不是FLASH中的代碼呢?

這個待會兒說,似乎涉及到PIC,大意是程序中的指令偏移會被替換成重定位後正確的地址位置,注意這個過程是在鏈接時,而不是運行時。具體怎麼情況,稍後奉上。

 

關於remap

一般是CPU提供的硬件設置功能,它會允許把內存地址空間的某一段映射到某個位置,ARM中常見的是在上電覆位的時候自動把引導加載程序鎖在FLASH的地址映射到0x00000000,在引導加載的過程中由軟件通過設置某個內存重映射寄存器,然後把主存地址重映射到0x00000000。在這種重映射的情況下,訪問映射的地址相當於直接訪問對應的FLASH或者主存的地址。

 

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