2021-05-12 14:32:11
u-boot 1.3.4原始碼分析詳細教學
每款MCU上電之後,並不是立即執行到主程式的,而是最先初始化整個系統資源,俗稱“Boot loader”。所以,u-boot是一種普遍用於嵌入式系統中的Boot loader,Boot loader是在作業系統執行之前執行的一小段程式,通過它,可以初始化硬體裝置、建立記憶體空間的對映表,從而建立適當的軟硬體環境,為最終呼叫作業系統核心做好準備。Boot loader的主要執行任務就是將核心映象從硬碟上讀到RAM中,然後跳轉到核心的入口點去執行,即開始啟動作業系統。系統在上電或復位時通常都從地址0x00000000處開始執行,而在這個地址處安排的通常就是系統的Boot Loader程式;所以了解了u-boot的啟動流程,就可以清楚知道linux啟動時列印的資訊是什麼意思。
那麼在介紹u-boot之前,先來認識一款軟體Source insight;由於從u-boot官網下載的u-boot1.3.4安裝包,它支援各大硬體平台,而且程式資料極多,在學習時,需要挑重點,找出符合位元組硬體的程式;所以source insight是一款相當不錯的軟體,當然像Slick edit也是一款很好的編輯器。
1 . Source Insight 使用
1.1 Source Insight工程建立
新建工程選單
工程設定介面
工程設定完成
工程檔案儲存路徑設定介面(預設)
原始碼新增介面
設定為新增子目錄檔案
新增檔案完成介面
關閉原始碼新增介面
檔案同步選單
同步設定
同步進行中
同步完成後介面
1.2常用操作介紹:
過濾檔案(輸入要檢視的檔名)
檢視目標檔案
檢視檔案中函數,變數,宏定義:
對於整個工程中只一個一份程式碼的函數或變數或宏,導航視窗會直接列出其定義,如下所示
對於有多個同名目標,則會以列表形式出現,讓使用者選擇:
搜尋功能:
給工程新增非預設型別檔案:
刪除檔案:
反向刪除:
同樣方法刪除CPU目錄下無關檔案。
2. u-boot目錄結構
board:存放資料夾的是具體開發板相關資料夾,有的目錄是公司名,裡面存放具體開發板的資料夾。有的直接開發板資料夾。其中存放的是板級相關檔案。
common:通用檔案,存放的是所有CPU共用的檔案,大部分是u-boot命令支援檔案。
像bootm, go,tftpboot ,help 等命令就是在這些檔案中實現。
CPU:存放晶片構架相關的檔案,一個資料夾代表一個型別的CPU核心。其中的資料夾存放整個核心通用的程式碼檔案以及具體的SOC資料夾。
Disk :硬體相關的支援程式碼。不用修改。
Doc :u-boot的使用說明書。不用修改。
Drivers :u-boot裝置驅動程式碼。
Fs :檔案系統程式碼,不用修改。
include:u-boot標頭檔案,包含有公用標頭檔案,裝置驅動相關標頭檔案,以及分體系構架相關的標頭檔案。
其中有一個資料夾是configs,比較重要,存放開發板設定標頭檔案,每個開發板對應一個標頭檔案,標頭檔案的名字就是開發板的名字。
lib_generic:通用庫檔案程式碼,整個u-boot共用檔案。不用修改。
lib*: 其他以lib開頭的是具體體系架構相關的庫檔案,整個個晶片構架共用的檔案。不用修改。
nand_spl:nand 驅動。
net:網路協定程式碼,一般不用修改。
post:一些開發板上電檢測程式碼,一般不用修改。
tool:編譯u-boot需要的一些工具程式碼,不用修改。
README:文字文件,u-boot的編譯,設定說明。
Makefile: 管理u-boot的Makefile檔案—移植u-boot時候要在這個檔案 新增一個自己的開發板設定選項。
3. u-boot 的啟動過程
3.1 u-boot 啟動階段
分兩部分:
1)組合部分—啟動程式碼;入口: cpu/構架資料夾/start.S
2) C語言程式碼部分。u-boot複雜功能都是這個階段實現。
入口:lib_*/board.c 中void start_armboot (void)函數。
任何一個開發板的u-boot都是從cpu/構架資料夾/start.S 檔案開始執行。
start.S:啟動程式碼,負責異常向量表定義,初始化CPU時鐘,記憶體設定,堆疊設定,複製程式碼到記憶體中,跳到到C程式碼階段。
3.2 start.S分析
以xyd2440為例子分析
入口檔案:start.S (cpuarm920t) 。
工作內容:
1. 異常向量表定義
2. 關看門狗
3. 關中斷
4. 設定時鐘
5. 設定記憶體控制器
6. 設定棧
7. 複製程式碼到記憶體
8. 清BSS段
9. 跳轉到C程式碼執行。
3.2.1 補充:GNU 組合知識
1)可以使用C的方法包含C語言標頭檔案,例如:
2).globl 關鍵字:宣告一個全域性的標號,全域性標號,其他可見,可以使用這個標誌。
.globl _start :把_start標號宣告為全域性的,其他的檔案 ,C,連結檔案,其他組合檔案都可見。
3)標號定義: “標號:” ,如: _start: ,定義一個_start標號。一個標號代表一個地址。
4).balignl關鍵字:在當前位置以指定對齊方式存放數位。
.balignl 16,0xdeadbeef 在當前程式碼所在的地址開始找到第一個16的整數倍地址存放0xdeadbeef
5).word關鍵字:在當前位置存放一個數值。如:
_TEXT_BASE:
.word TEXT_BASE
代表在當前地址存放 TEXT_BASE 所代表的數值。
6)可以使用C語言的預處理功能。
#if defined(CONFIG_xyd2440_LED_DEBUG)
…..
#endif
上面程式碼意思是如果定義了CONFIG_xyd2440_LED_DEBUG宏,就編譯其中包含的程式碼段。
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
上面使用C語言的宏定義功能定義數值。
7) 注釋:和C語言一樣。同時支援使用@注釋。 可用:// , /* */, @
8)組合程式碼專用宏定義:以 .macro 開頭 後接宏名,中間宏程式碼,最後是 .endm 做為結束。
.macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
ldmia r2, {r2 - r3} @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp
.endm
9) .align關鍵字: 控制程式碼對齊方式
ARM的.align 5就是2的5次方對齊,也就是4位元組對齊,
3.3 分析 :
//異常向量表定義
.globl _start //把 _start 宣告為全域性標號
_start: b start_code //第1條指令,復位異常
ldr pc, _undefined_instruction //未定義異常
ldr pc, _software_interrupt //軟中斷異常
ldr pc, _prefetch_abort //預取指中止異常
ldr pc, _data_abort //資料中止異常
ldr pc, _not_used
ldr pc, _irq //IRQ中斷異常
ldr pc, _fiq //FIQ中斷異常
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
當整個u-boot流程走完之後,就真正進入linux的啟動系統了。
所以,如果對u-boot整理流程通過軟體來認識一邊的話,就完全知道linux在啟動時,幹了哪些事。就像window啟動時,會出現一些資訊,告訴你當前執行到哪裡,執行了什麼事,一目了然。
本文永久更新連結地址:http://www.linuxidc.com/Linux/2017-07/145435.htm
相關文章