u-boot啟動流程分析之start.s,第一階段

文件:u-boot-1.1.6\cpu\arm920t\start.S

  1. reset部分代碼詳解
mrs指令語法
MRS{cond} Rd, psr
    Rd 是目標(biāo)寄存器。 Rd 不能為 r15。
    psr 是下列項之一:
        APSR 任何處理器,任何模式。
        CPSR 不提倡使用的 APSR 同義詞,用于調(diào)試狀態(tài),用于除
        ARMv7-M 和 ARMv6-M 之外的任何處理器。
        SPSR 用于除 ARMv7-M 和 ARMv6-M 之外的任何處理器,僅
可用于特權(quán)模式。
        Mpsr 僅用于 ARMv7-M 和 ARMv6-M 處理器。

關(guān)于arm寄存器的介紹

寄存器名字
Reg# APCS 意義
R0 a1 工作寄存器
R1 a2 "
R2 a3 "
R3 a4 "
R4 v1 必須保護(hù)
R5 v2 "
R6 v3 "
R7 v4 "
R8 v5 "
R9 v6 "
R10 sl 棧限制
R11 fp 楨指針
R12 ip 內(nèi)部過程調(diào)用寄存器
R13 sp 棧指針
R14 lr 連接寄存器
R15 pc 程序計數(shù)器
The following register names are predeclared:

r0-r15 andR0-R15
a1-a4 (argument, result, or scratch registers, synonyms for r0 to r3)
v1-v8 (variable registers, r4 to r11)
sb andSB (static base, r9)
ip andIP (intra-procedure-call scratch register, r12)
sp andSP (stack pointer, r13)
lr andLR (link register, r14)
pc andPC (program counter, r15).

CPSR寄存器介紹


格式(參考文檔

  1. ARM Architecture Reference Manual
    A2.5 Program status registers
  2. CPU三星S3C2440A芯片手冊
    THE PROGRAM STATUS REGISTERS
    )
ARM Architecture Reference Manual
CPU三星S3C2440A芯片手冊

mode bit各個對應(yīng)值的相關(guān)參考,其他各個位均可參考ARM Architecture Reference Manual,這里就不一一列出來.

The mode bits

bic指令語法
  BIC{<cond>}{S} <Rd>, <Rn>, <shifter_operand>
Rd = Rn AND NOT shifter_operand
bit 位清除指令 
      格式:BIC{<cond>}{S} <Rd>,<Rn>,<op2>; 
      功能:Rd=Rn AND (!op2) 用于清除寄存器Rn中的某些位,并把結(jié)果存放到目的寄存器Rd中
      例: 
        BIC R0,R0,#5 ;R0中第0位和第2位清0,其余位不變

ORR 邏輯或指令 
      格式:ORR{<cond>}{S} <Rd>,<Rn>,<op2>; 
      功能:Rd=Rn OR op2 一般用于設(shè)置Rn的特定幾位。
      例: 
        ORR R0,R0,#5  ;R0的第0位和第2位設(shè)置為1,其余位不變 
_start: b       reset


reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs r0,cpsr  //將cpsr寄存器的內(nèi)容放到r0寄存器中
    bic r0,r0,#0x1f //將r0的bit4-bit0清零
    orr r0,r0,#0xd3//r0的bit4-bit0 = 0xd3
    msr cpsr,r0  //將cpsr寄存器賦值為r0寄存器里的內(nèi)容,即設(shè)置為Supervisor模式,禁止IRQ和FIQ,運行于ARM stae
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    adr r0, _start      /* r0 <- current position of code   */
    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */
    cmp     r0, r1                  /* don't reloc during debug         */
    blne    cpu_init_crit
#endif

接著往后看,adr指令獲取_start符號的地址,因為adr是相對于pc進(jìn)行計算符號的地址的,所以如果是剛上電的還沒運行到sdram時PC的值是0,初始化完sdram把代碼拷到sdram時是鏈接地址TEXT_BASE=0x33F80000.
ldr指令(這里不是偽指令ldr)是取出_TEXT_BASE處存放的內(nèi)容(假如_TEXT_BASE的地址為0x10,里面存放的內(nèi)容是0x11.那么使用上述指令r1 = 0x10,使用adr的話r1 = 0x10)
  那么_TEXT_BASE處存放的是什么鬼?
//定義在satrt.S開頭處
_TEXT_BASE:
    .word   TEXT_BASE
那么問題來了_TEXT_BASE存放的是TEXT_BASE,那么他又等于什么

TEXT_BASE定義在
u-boot-1.1.6/board/100ask24x0/config.mk中,這里你肯定會有疑問,一個start.S源文件,一個是makefile文件.怎么聯(lián)系起來的,顯然肯定是有人使用了include指示符包含了這個config.mk

在/u-boot-1.1.6/config.mk中
#使用sinclude和include沒有區(qū)別,手冊上說是為了和別的make程序兼容
ifdef   BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk  # include board specific rules
endif

包含了之后就要使用該變量了

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)     \
    -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE)
使用了gcc -D選項定義了一個宏TEXT_BASE其值就等于0x33F80000..就是這么聯(lián)系起來的.
  所以上面那段代碼可以判斷程序是剛上電運行還是已經(jīng)運行到sdram里面了.還是寫的挺巧妙的..

進(jìn)行棧的設(shè)置

stack_setup:
    ldr r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot   */
    sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
    sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

初始化時鐘

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl clock_init
#endif  
    ldr pc, _start_armboot

_start_armboot: .word start_armboot

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容