文件:u-boot-1.1.6\cpu\arm920t\start.S
- 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寄存器介紹
格式(參考文檔
- ARM Architecture Reference Manual
A2.5 Program status registers - CPU三星S3C2440A芯片手冊
THE PROGRAM STATUS REGISTERS
)


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

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