/*本文中部分程序省略,只分析异常处理部分*/
.globl _start
_start:/* 0 地址 */
b reset /* 复位时,cpu跳到0地址 */
ldr pc, =undefined_instruction /* cpu遇到不能识别的指令时 */
ldr pc, _vector_swi /* 当执行swi指令时, 进入SVC模 式 */
@ldr pc, _prefetch_abort /* 预取中止异常 */
@ldr pc, _data_abort /* 数据访问异常 */
@ldr pc, _not_used /* 没用到 */
@ldr pc, _irq /* 中断异常 */
@ldr pc, _fiq /* 快中断异常 */
/*当发生中断时,
1.cpu进入IRQ模式
2.r13,r14切换到IRQ模式下的R13_irq,R14_irq
3.程序跳到0x18处执行,即执行ldr pc,_irq,程序跳转
*/
/*当cpu碰到一条自己不认识的指令时
1.cpu进入Undefine模式
2.r13,r14切换到R13_und,R14_und
3.程序跳到0x04处执行,即执行ldr pc, =undefined_instruction
*/
/*当执行到swi ,*/
_vector_swi:
.word vector_swi
vector_swi:
/* 1. 保存现场 */
ldr sp, =0x56000000 /* sp,r13, r13_svc */
stmdb sp!, {r0-r12, lr} /*把,r0-r12,lr都入栈*/
/* 2. 处理异常 */
mrs r0, cpsr
ldr r1, =swi_str
bl print_cpsr
/* 3. 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^表示把spsr恢复到cpsr ,r0-r12出栈,lr也出栈,把lr的值赋给pc,程序执行bl hello*/
swi_str:
.word 0x00697773 /* swi */
undefined_instruction:
/* 1. 保存现场 */
ldr sp, =0x55000000
stmdb sp!, {r0-r12, lr}
/* 2. 处理异常 */
mrs r0, cpsr
ldr r1, =und_str
bl print_cpsr
/* 3. 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^表示把spsr恢复到cpsr,出栈,把lr的值赋给pc,lr也出栈,把lr的值赋给pc,程序跳到swi_ret处继续执行 */
und_str:
.word 0x00646e75 /* und */
usr_str:
.word 0x00727375 /* usr */
reset:
/* 硬件相关的设置 */
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
/* 设置栈 */
ldr sp, =8*1024
/* 设置时钟 */
bl clock_init
bl ddr_init
bl init_uart
/* 把程序的代码段、数据段复制到它的链接地址去 */
adr r0, _start /* 获得_start指令当前所在的地址 : 0*/
ldr r1, =_start /* _start的链接地址 0x51000000 */
ldr r2, =bss_start /* bss段的起始链接地址 */
sub r2, r2, r1
cmp r0,r1
beq clean_bss
bl copy2ddr /*r0作为函数copy2ddr的第一个参数,r1作为第二个参数,r2作为第三个参数*/
cmp r0, #0 /*返回结果存在r0中*/
bne halt
/* 清BSS */
/* 把BSS段对应的内存清零 */
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr /*代码已经都复制到了ddr中,从片内内存跳到ddr中的on ddr处执行*/
on_ddr:
mrs r0, cpsr /*mov register,r0*/
bic r0,r0,#0x1f
orr r0,r0,#0x10
msr cpsr,r0 /* 进入user mode */
ldr sp, =0x57000000
ldr r1, =usr_str
bl print_cpsr
swi 0 /*
* cpu进入svc模式
* 把之前的cpsr保存到spsr_svc
* 切换到r13_svc, r14_svc
* 把swi的下一条指令(即bl hello)的地址存到r14(lr)_svc
* 跳到地址8
* 以上几条都是系统自己做的事
*/
bl hello
undef:
.word 0xff000000 /*
* cpu进入Undefined模式
* 把之前的cpsr保存到spsr_und
* 切换到r13_und, r14_und
* 把下一条指令(即swi_ret)的地址存到r14(lr)_und
* 跳到地址4
*/
swi_ret:
bl main
halt:
b halt
/*小结:
在实际开发中,通常用未定义指令来做调试,开发者可以在程序中加入未定义指令,在未定义指令的异常处理部分通过串口输出些字符,从而跟踪程序的运行
*/