1.ARM的7种模式、2种状态
对于异常与中断的概念,不难理解,中断属于异常,但两者都是不可预见的。
对于ARM的中断/异常的使用过程,看下图
备注:下面的程序就是根据这样的主线编程,这也是这篇文章的核心。
OK,那ARM下有哪些模式呢? 如下图所示
补充:CPSR:Current program status register 当前程序状态寄存器
SPSR:Store program status register: 存储程序状态寄存器
除了ARM state外,还有另一种state,如下
OK, 介绍完ARM的7种状态和2种State,接下来看看实际进入中断和退出中断有哪些硬件操作
2 undefied 指令模式
故意制造一条未定义执行,由此进入und 异常模式,并进行相应中断处理,如下
start.S 代码如下
_start:
b reset /* vector 0 : reset */
ldr pc, und_addr /* vector 4 : und */
und_addr:
.word do_und
do_und:
/* 执行到这里之前:
* 1. lr_und保存有被中断模式中的下一条即将执行的指令的地址
* 2. SPSR_und保存有被中断模式的CPSR
* 3. CPSR中的M4-M0被设置为11011, 进入到und模式
* 4. 跳到0x4的地方执行程序
*/
/* sp_und未设置, 先设置它 */
ldr sp, =0x34000000
/* 保存现场 */
/* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */
/* lr是异常处理完后的返回地址, 也要保存 */
stmdb sp!, {r0-r12, lr}
/* 处理und异常 */
mrs r0, cpsr
ldr r1, =und_string
bl printException
/* 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */
und_string:
.string "undefined instruction exception"
.align 4
reset:
/*一些初始化(sdram_init)、nor/nand启动选择等, 无关紧要的代码这里忽略*/
/* ... */
/* 故意加入一条未定义指令 */
und_code:
.word 0xdeadc0de /* 未定义指令 */
ldr pc, =main /* 绝对跳转, 跳到SDRAM */
3 swi 软中断(IRQ的一种)
跟und 同理,先故意制作swi,再进入异常模式
start.S
_start:
b reset /* vector 0 : reset */
ldr pc, und_addr /* vector 4 : und */
ldr pc, swi_addr /* vector 8 : swi */
.align 4 // 注意:这里一定要4字节对齐
do_swi:
/* 执行到这里之前:
* 1. lr_svc保存有被中断模式中的下一条即将执行的指令的地址
* 2. SPSR_svc保存有被中断模式的CPSR
* 3. CPSR中的M4-M0被设置为10011, 进入到svc模式
* 4. 跳到0x08的地方执行程序
*/
/* sp_svc未设置, 先设置它 */
ldr sp, =0x33e00000
/* 保存现场 */
/* 在swi异常处理函数中有可能会修改r0-r12, 所以先保存 */
/* lr是异常处理完后的返回地址, 也要保存 */
stmdb sp!, {r0-r12, lr}
mov r4, lr
/* 处理swi异常 */
mrs r0, cpsr
ldr r1, =swi_string
bl printException
sub r0, r4, #4
bl printSWIVal
/* 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^会把spsr的值恢复到cpsr里 */
swi_string:
.string "swi exception"
.align 4
reset:
/* .... */
swi 0x123 /* 执行此命令, 触发SWI异常, 进入0x8执行 */
ldr pc, =main /* 绝对跳转, 跳到SDRAM */