U-Boot啟動過程可以分成兩個階段(stage)
下面是u-boot啟動過程的流程圖其中左右兩部分分別是啟動過程的兩個階段
第一階段(stage 1):
依賴於CPU體繫結構的代碼(如裝置初始化代碼等),一般用彙編語言來實現。主要進行以下方面的設定:設定ARM進入SVC模式、禁止IRQ和FIQ、關閉看門狗、屏蔽所有中斷。設定時鐘(FCLK,HCLK,PCLK)、清空I/D cache、清空TLB、禁止MMU和cache、配置記憶體控制器、為搬運代碼做準備、搬移uboot映像到RAM中(使用copy_loop實現)、分配堆棧、清空bss段(使用clbss_l實現)。
(1)具體設定與代碼實現:
ü 設定ARM進入SVC模式、禁止IRQ和FIQ
CPSR 寄存器(和儲存它的 SPSR 寄存器)中的位分配如下:
31 30 29 28 --- 7 6 - 4 3 2 1 0
N Z C V I F M4 M3 M2 M1 M0
0 0 0 0 0 User26 模式
0 0 0 0 1 FIQ26 模式
0 0 0 1 0 IRQ26 模式
0 0 0 1 1 SVC26 模式
1 0 0 0 0 User 模式
1 0 0 0 1 FIQ 模式
1 0 0 1 0 IRQ 模式
1 1 1 0 0 1 1 SVC 模式
1 0 1 1 1 ABT 模式
1 1 0 1 1 UND 模式
要設定成SVC模式,則要將先關中斷即將6位IRQ(中斷),7位(快速中斷)置位;
mrs r0,cpsr @將cpsr的值讀到r0中 bic r0,r0,#0x1f @清除M0~M4 orr r0,r0,#0xd3 @禁止IRQ,FIQ中斷,並將處理器置於管理員模式(SVC32 mode) msr cpsr,r0 @將r0的值返回到cpsr中 |
關閉看門狗、屏蔽所有中斷
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] mov r1, #0xffffffff ; all interrupt disabl ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3fff ;all sub interrupt disable ldr r0, =INTSUBMSK str r1, [r0] # endif |
對於S3C2440和S3C2410的WTCON寄存器的[0]控制允許或禁止看門狗定時器的複位輸出功能,設定為“0”禁止複位功能。通過設定INTMSK,INTSUBMSK的所有中斷位即可屏蔽所有中斷。
設定CPU:清空I/D cache、清空TLB、禁止MMU和cache
#ifndef CONFIG_SKIP_LOWLEVEL_INIT cpu_init_crit:
@初始化CACHES mov r0, #0 mcr p15, 0, r0, c7, c7, 0 mcr p15, 0, r0, c8, c7, 0 |
對於ARM副處理器的知識,參考ARM920T Technical Reference Manual(Rev 1)說明文檔解釋如下:
MCR與MRC是對ARM處理器的副處理器進行操作的指令;
MCR p15,0,Rd,c7,c7,0的操作原型如下:
Invalidate ICache and DCache|SBZ|MCR p15,0,Rd,c7,c7,0 |
這指令是讓ICache與DCache無效,其中ICache是指令緩衝器,DCache是資料緩衝器;對Rd的說明,SBZ(Should Be Zero),是使這個寄存器裡所有的位都為0,所以第一句語句是mov r0, #0。
MCR p15,0,r0,c8,c7,0的操作原型如下:
Invalidate TLB(s)|SBZ|MCR p15,0,Rd,c8,c7,0 |
這條指令就是讓TLB無效;也許讀者會問,那什麼是TLB呢?
TLB是Translation Lookaside Buffers的簡稱,即地址解碼的動作,可翻譯成“地址轉換遍曆緩衝”。對這種機制感興趣的讀者可以到官方下載ARM920T Technical Reference Manual(Rev 1)的說明文檔。
接下來我們來關閉MMU和CACHES
@關閉MMU和CACHES mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Align orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0
|
在ARM920T Technical Reference Manual(Rev 1)說明文檔中,可以查到如下的資訊:
MRC p15, 0, Rd, c1, c0, 0 ;讀控制寄存器 MCR p15, 0, Rd, c1, c0, 0 ;寫控制寄存器 |
第一條設定指令:0x00002300 = 10001100000000(B),第8,9,13位被清零,即S,R,V位被清零。經過查ARM920T說明文檔可知:S,R位被清零,表示任何對MMU的訪問操作都會產生域失敗(domain fault)。V位被清零,表示Base location of exception registers的地址,從0x0開始。
第二條設定指令:0x00000087 = 10000111(B),第0,1,2,7位被清零。即M,A,C,B被清零,分別表示MMU Disabled、Data address alignment fault checking、Fault checking disabled、DCache disabled、Little-endian operation。當你按下重啟鍵的時候,U-boot會檢查CPU的儲存類型,是大端儲存還是小端儲存,當第7位被設定為1,則為大端儲存,當第8位被設定為0,則為小端儲存。
第三條設定指令: 0x00000002 = 10(B),即第1位置1,表示又把相應的模式設定成了Data address alignment fault checking,Fault checking enabled狀態。
第四條設定指令:0x00001000 = 1000000000000(B),即第12位置1,表示可以開啟ICache,即開啟指令緩衝。然後mcr
p15, 0, r0, c1, c0, 0就是把相應的位操作結果寫到寄存器1中,使其生效。
註:對於第一階段時鐘初始化等在這兒不作講解。
第二階段(stage 2)通常用C語言來實現。
首先以start_armboot()函數為進入點,主要進行如下操作:
初始化(cpu, 板卡,中斷,串口,控制台等),開啟I/D cache。初始化FLASH,根據系統配置執行其他初始化操作。列印LOG,使能中斷,擷取環境變數,初始化網卡。最後進入main_loop()函數。在main_loop函數中會檢查BOOTDELAY和BOOTCMD環境變數,如果BOOTCMD已經設定過,則在等待BOOTDELAY個毫秒後會自動執行BOOTCMD。如果等待過程中被使用者中斷(ctl+c)或者BOOTCMD沒有設定,則會等待使用者輸入命令。
到此,U-boot就已經正常啟動起來了,如果讀者有進一步想瞭解U-Boot啟動,可以結合原始碼分析,本節將不作更具體的介紹了。