【发布时间】:2013-12-12 08:31:01
【问题描述】:
我知道 ARM926ej-s 正在使用 全降序 堆栈。现在我有了这个启动代码,我在与此问题相关的行上使用/**/ 进行了评论。
.global __start
.global arm926ejs_reset
.global dcache_flush
.global __gnu_bssstart
.global __gnu_bssend
.global __image_size
.EQU MODE_USR, 0x010
.EQU MODE_FIQ, 0x011
.EQU MODE_IRQ, 0x012
.EQU MODE_SVC, 0x013
.EQU MODE_SVC_NI, 0x0D3
.EQU MODE_ABORT, 0x017
.EQU MODE_UNDEF, 0x01b
.EQU MODE_SYSTEM, 0x01f
.EQU MODE_BITS, 0x01f
.EQU I_MASK, 0x080
.EQU F_MASK, 0x040
.EQU IF_MASK, 0x0C0
.EQU BROM_MMU_BASE_ADDR, 0x1201C000
.EQU MMU_DISABLE_MASK, 0xFFFFEFFA
.EQU MMU_ENABLE_MASK, 0x00001005
.EQU FIQ_STACK_SIZE, 128
.EQU IRQ_STACK_SIZE, 256
.EQU ABORT_STACK_SIZE, 32
.EQU UNDEF_STACK_SIZE, 32
.EQU SYSTEM_STACK_SIZE, 64
.text
.code 32
.align 2
__start:
arm926ejs_reset:
B arm926ejs_reset_handler /*reset vector*/
.word 0x41676d69
.word 0,0,0,0,0
image_type:
.word 0x0000000A
sizeOfPermanentCode:
.word (__image_size)
.word 0,0
bootparameter:
.word 0
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
arm926ejs_reset_handler:
MOV r0, #MODE_SVC_NI
MSR cpsr_cxsf, r0
MRC p15, 0, r1, c1, c0, 0
LDR r2,=MMU_DISABLE_MASK
AND r1, r1, r2
MCR p15, 0, r1, c1, c0, 0
MOV r1,#0
MCR p15, 0, r1, c8, c7, 0
MCR p15, 0, r1, c7, c7, 0
MRC p15, 0, r1, c1, c0, 0
LDR r2,=0x1000
ORR r1, r1, r2
MCR p15, 0, r1, c1, c0, 0
MVN r1, #0
MCR p15, 0, r1, c3, c0, 0
LDR r3, =BROM_MMU_BASE_ADDR
MCR p15, 0, r3, c2, c0, 0
LDR r5, =inVirtMem
MRC p15, 0, r1, c1, c0, 0
LDR r2,=MMU_ENABLE_MASK
ORR r1, r1, r2
MCR p15, 0, r1, c1, c0, 0
MOV pc, r5
NOP
NOP
NOP
inVirtMem:
ADR r3, arm926ejs_reset /*we store the reset vector address*/
SUB r3, r3, #4 /*why do we then substract 4 bytes?*/
MOV r1, #IF_MASK
ORR r0, r1, #MODE_FIQ /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
SUB r3, r3, #FIQ_STACK_SIZE
ORR r0, r1, #MODE_IRQ /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
SUB r3, r3, #IRQ_STACK_SIZE
ORR r0, r1, #MODE_ABORT /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
SUB r3, r3, #ABORT_STACK_SIZE
ORR r0, r1, #MODE_UNDEF /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
SUB r3, r3, #UNDEF_STACK_SIZE
ORR r0, r1, #MODE_SYSTEM /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
SUB r3, r3, #SYSTEM_STACK_SIZE
ORR r0, r1, #MODE_SVC /*sets stack for MCPU mode*/
MSR cpsr_cxsf, r0
MOV sp, r3
LDR r0, =__gnu_bssstart
LDR r1, =__gnu_bssend
MOV r2, #0
clearzi:
CMP r0, r1
BEQ clearzi_exit
STR r2, [r0]
ADD r0, r0, #4
B clearzi
clearzi_exit:
load_entry:
LDR pc, =c_entry
NOP
dcache_flush:
CMP r0, #0
BNE inval
flushonly:
MRC p15, 0, r15, c7, c10, 3
BNE flushonly
MOV pc, lr
inval:
MRC p15, 0, r15, c7, c14, 3
BNE inval
MOV pc, lr
.END
在上面的代码中,第一条注释显示了一个重置向量(一个分支指令B arm926ejs_reset_handler),紧接着是一个标题和一些准备 mcu 的命令...
现在看下一条注释,我们将复位向量的地址存储到寄存器r3 中,在下一行中,我们从该地址中减去4 字节。
Q1:我们为什么要这样做?这个地址现在是否显示在.word 0x41676d69 的位置?
在下一行中有多个类似的块,每个块都为不同的 mcpu 模式设置堆栈。让我们看一下第一个堆栈指针sp 与寄存器r3 一起加载,然后从这个地址中减去堆栈的大小,得到这个mcpu 模式的堆栈大小。
Q2:此堆栈是否会覆盖从.word 0x41676d69 开始的标头以及用于准备MCU 的所有指令?重置向量B arm926ejs_reset_handler 保持不变吗?为什么我们要重写标题?我们不再需要它了吗?
【问题讨论】: