
前言
以前接觸到的u-boot啟動方式只有Flash和Nand Flash這兩種方式,最近接觸是SD卡啟動方式,SoC是S5P4418,啟動方式也第一次接觸到,根據S5P4418用戶手冊可以找到系統使用SD卡啟動時,片內iROM內固化的代碼會自動映射到0x00地址,也被稱為第一階段引導程式,該程式會檢測啟動引腳配置,然后從SD卡讀取block1~block32內的程式到內置SRAM中執行,讀取出來并執行的這段程式被稱為第二階段引導程式,由于其最大為16KB,無法存放完整的u-boot,以上兩個引導程式均由芯片廠商提供,沒有原始碼,不開源,第二階段引導程式從SD卡中加載u-boot到DRAM中執行,至此u-boot才開始登場,
SDHCBOOT --> 2nboot --> u-boot
代碼分析
程式入口
由于S5P4418采用的指令集為ARMv7,通常應該去該檔案arch/arm/cpu/armv7下尋找該SoC,然而并沒有,通過查看board.cfg可以看到它的CPU型別被定義為了slsiap,通過查看arch/arm/cpu/slsiap也確實存在s5p4418檔案夾,
# Status, Arch, CPU:SPLCPU, SoC, Vendor
Active arm slsiap s5p4418 s5p4418
接下來就是找到第一個執行的程式在哪里檔案里,即找到程式入口,查看slsiap下的鏈接檔案
.text :
{
*(.__image_copy_start)
SDIR/start.o (.text*)
*(.text*)
}
而SDIR是什么并不知道,打開同檔案夾下的config.mk
SDIR=arch/arm/cpu$(if $(CPU),/$(CPU),)$(if $(SOC),/$(SOC),)
替換變數之后
SDIR=arch/arm/cpu/slsiap/s5p4418
即第一個檔案是arch/arm/cpu/slsiap/s5p4418/start.S
start.S
不同 CPU 的改檔案大致功能都大同小異,設定中斷向量表,將 CPU 設定為 SVC 模式,然后設定 CP15,設定 Cache,初始化記憶體,然后對代碼進行重定位,之后開始清理 bss 段,為準備 C 語言運行環境,然后設定堆疊指標,執行 board_init_f 函式填充 global_data 結構體資料,最后執行 board_init_r,離開start.S不再回傳,
board_init_r
該函式中呼叫的兩個有意思的函式:serial_initialize、mmc_initialize,
void serial_initialize(void)
{
mpc8xx_serial_initialize();
...省略若干類似函式...
s5p_serial_initialize();
...省略若干類似函式...
arc_serial_initialize();
}
可以看到,該函式中不加判斷的把各種種類的串口初始化都給寫上,也沒有使用宏去自動選擇使用哪個,給人的第一感覺就是這不是浪費存盤空間么,繼續查看該函式所在檔案其他代碼可以發現
/**
* serial_initfunc() - Forward declare of driver registration routine
* @name: Name of the real driver registration routine.
*
* This macro expands onto forward declaration of a driver registration
* routine, which is then used below in serial_initialize() function.
* The declaration is made weak and aliases to serial_null() so in case
* the driver is not compiled in, the function is still declared and can
* be used, but aliases to serial_null() and thus is optimized away.
*/
#define serial_initfunc(name) \
void name(void) \
__attribute__((weak, alias("serial_null")));
serial_initfunc(mpc8xx_serial_initialize);
...省略若干類似函式...
serial_initfunc(s5p_serial_initialize);
...省略若干類似函式...
serial_initfunc(arc_serial_initialize);
英文注釋說的很清楚了,這是在利用編譯器特性進行自動優化的,使用 __weak 屬性先宣告驅動程式,因為編譯程式之前會先配置程式,在編譯的時候在配置階段產生的宏在預編譯階段會決定哪些驅動程式被編譯進來,比如 S5P4418 被選擇時,相關的串口驅動 s5p_serial_initialize 就會編譯進來,由于其宣告為 __weak 屬性,編譯時會自動覆寫掉前項宣告的函式,這樣函式 serial_initialize 就不會出現把不必要的程式編譯進來的情況了,
mmc_initialize 函式的分析見下回分解吧~
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/4944.html
標籤:嵌入式
上一篇:初級模擬電路:4-9 級聯系統
