1. 程式人生 > >uboot啟動流程詳解(2)-reset

uboot啟動流程詳解(2)-reset

1、原始碼及註釋

  reset是uboot最先執行的程式碼,接下來我們來看看reset的具體流程。

reset:
    /*如果沒有重新定義save_boot_params,則使用<arch/arm/cpu/armv7/start.S>
    中的save_boot_params。其不做任何事情,直接返回。*/
    bl  save_boot_params
    /*
     * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
     * except if in HYP mode already
     */
mrs r0, cpsr /*將cpsr暫存器的內容傳送到r0暫存器*/ and r1, r0, #0x1f /*標誌位清零*/ teq r1, #0x1a /*測試處理器是否處於HYP模式, HYP是armv-7a為cortex-A15處理器提供硬體虛擬化引進的管理模式。*/ bicne r0, r0, #0x1f /*工作模式位清零*/ orrne r0, r0, #0x13 /*設定成SVC管理模式*/ orr r0, r0, #0xc0 /*關閉FIQ和IRQ中斷*/ msr cpsr,r0 /*將r0的值賦給cpsr*/ /* * Setup vector: * (OMAP4 spl TEXT_BASE is not 32 byte aligned. * Continue to use ROM code vector only in OMAP4 spl) */
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) /**************************************************************** 設定異常向量的基地址,正常異常模式下異常向量的基地址為0x00000000,高異常模式下 異常向量的基地址為0xffff0000,這裡V=0設定成正常異常模式。CP15協處理器的操作及 相關知識可以看另一篇文章。 *****************************************************************/
/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */ mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register bic r0, #CR_V @ V = 0 mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register      /*********************************************      重新設定異常向量的基地址,只有上面V=0的情況下,這裡才能去重新      配置異常向量表的基地址!      **********************************************/ /* Set vector address in CP15 VBAR register */ ldr r0, =_start mcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif /* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_cp15 //初始化協處理器,具體流程請看另一篇文章 bl cpu_init_crit //初始化記憶體和鎖相環,具體流程請看另一篇文章 #endif bl _main //呼叫c程式碼,具體流程請看另一篇文章。

2、CPSR暫存器介紹

這裡寫圖片描述
  通過向模式位M[4:0]裡寫入相應的資料切換到不同的模式,在對CPSR,SPSR暫存器進行操作不能使用mov,ldr等通用指令,只能使用特權指令msr和mrs。
這裡寫圖片描述
  在ARM處理器中,只有MRS(Move to Register from State register)指令可以對狀態暫存器CPSR和SPSR進行讀操作。通過讀CPSR可以獲得當前處理器的工作狀態。讀SPSR暫存器可以獲得進入異常前的處理器狀態(因為只有異常模式下有SPSR暫存器)。
  除了使用者模式和系統模式,其餘模式下都有一個私有SPSR儲存狀態暫存器,用來儲存切換到該模式之前的執行狀態,之所以使用者模式和系統模式沒有SPSR是因為,通常CPU大部分時間執行在使用者模式下,當產生異常或系統呼叫時會分別切換進入另外幾種模式,儲存使用者模式下的狀態,當切換回原先模式時,直接回復SPSR的值到CPSR就可以了,因此,使用者模式和系統模式下不需要SPSR。

3、相關彙編指令介紹

  1. mrs
      將狀態暫存器的內容傳送至通用暫存器。
  2. teq
      TEQ R1,R2 ;將暫存器R1的值與暫存器R2的值按位異或,並根據結果設定CPSR的標誌位。該指令通常用於比較運算元1和運算元2是否相等。常與EQ和NE條件碼配合使用,當兩個資料相等時,條件碼EQ有效,否則條件碼NE有效。
  3. bic
      指令格式:BIC{cond}{S} Rd,Rn,operand2
      BIC指令將Rn 的值與運算元operand2 的反碼按位邏輯”與”,結果存放到目的暫存器Rd 中。
      指令示例:BIC R0,R0,#0x0F ;將R0最低4位清零,其餘位不變。
  4. orr
      指令格式:orr {cond}{S} Rd,Rn,operand2
      orr指令將運算元operand2 與Rn 的值按位邏輯"或",結果存放到目的暫存器Rd 中。
      指令示例:orrs R1,R1,R2 ;R1=R1|R2,並根據運算的結果更新標誌位。
           orr R0,R0,#0x0F ;R0=R0|0x0F,將R0最低4位置1,其餘位不變。

4、處理器模式介紹

這裡寫圖片描述

5、ARM通用暫存器介紹

  在ARM處理器內部有37個使用者可見的暫存器:30個通用暫存器,6個狀態暫存器(1個專用於記錄當前狀態,5個專用於記錄模式切換前的狀態),1個程式計數器PC。在不同的工作模式和處理器狀態下,程式設計師可以訪問的暫存器也不盡相同。
-31個通用暫存器:
 R0~R15;
 R13_svc、R14_svc;
 R13_abt、R14_abt;
 R13_und;R14_und;
 R13_irq、R14_irq;
 R8_fiq-R14_fiq
-6 個狀態暫存器:
 CPSR、SPSR_svc、SPSR_abt、SPSR_und、SPSR_irq和SPSR_fiq
這裡寫圖片描述

5.1 通用暫存器

通用暫存器包括R0~R15,可以分為三類:
 ─ 未分組暫存器R0~R7
 ─ 分組暫存器R8~R14
 ─ 程式計數器PC(R15)
  (1)未分組暫存器R0~R7
  在所有的執行模式下,未分組暫存器都指向同一個物理暫存器,他們未被系統用作特殊的用途,是真正的通用暫存器。因此,在中斷或異常處理進行執行模式轉換時,由於不同的處理器執行模式均使用相同的物理暫存器,可能會造成暫存器中資料的破壞,這一點在進行程式設計時應引起注意。
  (2)分組的暫存器R8~R14
  對於R8~R12,每一次所訪問的物理暫存器,與處理器當前的工作模式有關。
  一、R8~R12
  當處理器工作於fiq模式時,訪問的暫存器為R8_fiq~R12_fiq;
  除fiq模式以外的其他模式,訪問的暫存器為R8_usr~R12_usr。
  二、R13和R14:
  每個暫存器對應6個不同的物理暫存器,其中的一個是使用者模式與系統模式共用,另外5個物理暫存器,對應於其他5種不同的異常模式。
  R13:暫存器R13在ARM指令中常用作堆疊指標SP。但這只是一種習慣用法,使用者也可使用其他的暫存器作為堆疊指標。而在Thumb指令集中,某些指令強制性的要求使用R13作為堆疊指標。
  R14:暫存器R14也稱作子程式連結暫存器(Subroutine Link Register)或連結暫存器LR。當執行BL子程式呼叫指令時,R14中得到R15(程式計數器PC)的備份。其他情況下,R14用作通用暫存器。與之類似,當發生中斷或異常時,對應的分組暫存器R14_svc、R14_irq、R14_fiq、R14_abt和R14_und用來儲存R15的返回值。
  (3)程式計數器PC(R15)
  暫存器R15用作程式計數器(PC)。在ARM狀態下,位[1:0]為0,位[31:2]用於儲存PC;在Thumb狀態下,位[0]為0,位[31:1]用於儲存PC。
  使用R15時注意:雖然R15可以用作通用暫存器,但是有一些指令在使用R15時有一些特殊限制,若不注意,執行的結果將是不可預料的。所以,一般不這麼使用。
  關於PC的值:由於ARM採用多級流水線技術,所以PC總是指向正在取指的指令,而不是正在執行的指令。也即PC總是指向當前指令的下兩條指令的地址。因此,對於ARM指令集而言,PC的值為當前指令的地址值加8個位元組。

5.2 狀態暫存器

  在ARM微處理器中,有CPSR和SPSR兩種程式狀態暫存器。
  1、當前程式狀態暫存器 CPSR (Current Program Status Register)用來儲存當前程式狀態的暫存器。所有處理器模式下都可以訪問當前程式狀態暫存器CPSR。僅一個CPSR。
  2、儲存程式狀態暫存器SPSR_mode (Saved Program Status Register)SPSR_mode用來進行異常處理,其功能包括:
  ─ 儲存ALU中的當前操作資訊,當異常發生時, 用來儲存CPSR的值,從異常返回時,將 SPSR_mode複製到CPSR中,恢復CPSR的值。
  ─ 控制允許和禁止中斷 修改SPSR的值
  ─ 設定處理器的執行模式 修改SPSR的值
問題:一共有多少個SPSR?為什麼?
  ARM狀態暫存器的格式
這裡寫圖片描述
1、條件碼標誌位(儲存ALU中的當前操作資訊)
 N:正負號/大小 標誌位
 0表示:正數/大於;1表示:負數/小於
 Z:零標誌位
 0表示:結果不為零;1表示:結果為零
 C:進位/借位/移出位
 0表示:未進位/借位/移出0;1表示:進位/未借位/移出1
 V:溢位標誌位
 0表示:結果未溢位;1表示:結果溢位
2、控制位
 I、F中斷控制位——控制允許和禁止中斷
  I=1 禁止IRQ中斷 I=0 允許IRQ中斷
  F=1 禁止FIQ中斷 F=0 允許FIQ中斷
 T控制(標誌)位——反映處理器的執行狀態
  T=1時,程式運行於Thumb狀態
  T=0時,程式運行於ARM狀態
 M控制位——決定了處理器的執行模式
  當發生異常時這些位被改變。如果處理器執行在特權模式,這些位也可以由程式修改。