Uboot的啟動流程分為兩個階段,第一階段主要是匯編語言編寫,第二階段是C語言編寫,每個階段所做的工作不同,這篇文章分析的是uboot 2010版,以tiny4412的uboot為例。
啟動過程涉及的主要文件:
arch/arm/cpu/armv7/start.S
board/samsung/myboard/lowlevel_init.S
arch/arm/lib/crt0.S
arch/arm/lib/board.c
arch/samsung/myboard/myboard.c
第一階段 uboot的入口的地址是arch/arm/cpu/armv7/start.S, 這可以從相同路徑下的連接腳本u-boot.lds 中知道。 arch/arm/cpu/armv7 /start.S 平臺相關,CPU工作模式設為SVC模式,關MMU,關icahce(CPU相關) board/samsung/fs4412/lowlevel_init.S 開發板相關:關看門狗,內存初始化,時鐘初始化,串口初始化(board相關,初始化最基本的硬件環境)
第二階段 arch/arm/lib/crt0.S _main 函數所在處,初始化SP,為C語言準備,代碼重定位,清BSS,設置R0 R1 R2 R8相應寄存器 arch/arm/lib/board.c board_init_f 函數 ,填充GD結構體,初始化外設, main_loop()函數超循環
第一個階段:
在這個階段主脈絡就是:部分硬件初始化—》加載完整的uboot到RAM—》跳轉到第二階段入口開始執行。
整個過程涉及兩個重要的文件:start.S和lowlevel_init.S。Start.S涉及到特定硬件設備的讀寫寄存器操作以及特定體系結構的匯編語言;lowlevel_init.S,涉及的操作和文件名吻合,完成底層的初始化
執行上面的_start: b reset 后跳轉到下面這段代碼繼續運行:
繼續往下分析:
程序跳轉到這個函數里,我們進去看看:
上面的lowlevel_init在board/samsung/myboard/lowlevel_init.S
之后回到start.S執行
上面的代碼完成了gt結構體部分成員賦值
程序往下執行到relocate_code:
經過上面的操作,uboot已經把字節從SD卡拷貝到SDRAM中,并且為之后的執行準備好了各種參數,最終跳轉到第二部分的入口board_init_r
從上面可以總結出:
1.Bootloader第一階段的功能:
- 硬件設備初始化。
- 為加載Bootloader的第二階段代碼準備RAM空間。
- 設置CPU的速度、時鐘頻率及終端控制寄存器
- 初始化內存控制器
- 復制Bootloader的第二階段代碼到RAM空間中。
- 設置好棧。
- 跳轉到第二階段代碼的C入口點。
在第一階段進行的硬件初始化一般包括:關閉WATCHDOG、關中斷、設置CPU的速度和時鐘頻率、RAM初始化等。這些并不都是必需的,比如S3C2410/S3C2440的開發板所使用的U-Boot中,就將CPU的速度和時鐘頻率的設置放在第二階段。
甚至,將第二階段的代碼復制到RAM空間中也不是必需的,對于NOR FLASH等存儲設備,完全可以在上面直接執行代碼,只不過相比在RAM中執行效率大為降低。
第二階段分析:
- 初始化本階段要使用的硬件設備。
- 檢測系統內存映射(memory map)。
- 將內核映像和根文件系統映像從FLASH上讀到RAM空間中。
- 為內核設置啟動參數。
- 調用內核。
C語言代碼部分 arch/arm/lib/board.c中的board_init_f是C語言開始的函數也是整個啟動代碼中C語言的主函數,同時還是整個u-boot的主函數,該函數只要完成如下操作:
1)調用一系列的初始化函數。
2)初始化Flash設備。
3)初始化系統內存分配函數。
4)如果目標系統擁有NAND設備,則初始化NAND設備。
5)如果目標系統有顯示設備,則初始化該類設備。
6)初始化相關網絡設備,填寫IP、MAC地址等。
7)進去命令循環(即整個boot的工作循環),接受用戶從串口輸入的命令,然后進行
U-Boot的啟動順序流程圖: