本文参考韦东山嵌入式视频
一、ARM体系CPU工作模式
1、用户模式(usr)
2、快速中断模式(fiq)
3、中断模式(irq)
4、管理模式(svc)
5、数据访问终止模式(abt)
6、系统模式(sys)
7、未定义指令中止模式(und)
①每种工作模式有不同的寄存器:一共有37个32位寄存器(以ARM920T CPU为例,在ARM状态下(ARM体系的CPU有两种工作状态)),
所谓备份寄存器是指当前工作模式下独有的。除了系统模式和用户模式,其他模式下都有自己独立的寄存器。
②有不同的权限 :配合MMU使用
③有不同的出发条件:例如上电后处于管理模式 发生中断进入irq模式等
二、异常与中断
1、异常
中断是属于异常的一种,发生异常之后,CPU进入异常模式,PC = 异常地址入口(固定地址)如下:
b Reset
@ 0x04: 未定义指令中止模式的向量地址 一个地址占32位 所以这里的地址就是4==
HandleUndef:
b HandleUndef 这个一个死循环,表明程序并没有对这种异常进行处理,下面同理
@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
b HandleSWI
@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort
@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
b HandleDataAbort
@ 0x14: 保留
HandleNotUsed:
b HandleNotUsed
@ 0x18: 中断模式的向量地址
b HandleIRQ
@ 0x1c: 快中断模式的向量地址
HandleFIQ:
b HandleFIQ
Reset: @一上电进入Reset **上电和复位的时候是管理模式**
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
msr cpsr_c, #0xd2 @ 进入中断模式
ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xd3 @ 进入管理模式
ldr sp, =4096 @ 设置管理模式栈指针, **片内内存的顶端**
@ 其实复位之后,CPU就处于管理模式,
@ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
***************因为中断模式和管理模式的sp(栈指针,r13)是各自独有的sp,所以要对两种模式的sp进行设置*************
**************CPSR寄存器是当前程序状态寄存器,见下面图所示********************************
bl init_led @ 初始化LED的GPIO管脚
bl init_irq @ 调用中断初始化函数,在init.c中 包括对硬件设置(GPIO引脚使能中断) 屏蔽中断寄存器设置 中断优先级设置等
msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @ 计算返回地址 处理完这个中断后得返回,要先计算返回地址,以便到时候返回继续执行原有程序
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
@ 注意,此时的sp是中断模式的sp
@ 初始值是上面设置的3072
ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的返回地址
ldr pc, =EINT_Handle @ 调用中断服务函数,在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr
2、中断
中断发生处理流程:
进入IRQ模式:切换sp寄存器,这个寄存器是IRQ自己的栈寄存器;
PC= IRQ入口地址
b HandleIRQ :
计算返回到“被中断”处的地址
保存现场:即一系列寄存器
调用中断处理函数(C实现):Ⅰ、分辨中断源INTOFFSET寄存器(对于s3c2440)
Ⅱ、处理
Ⅲ、清除中断:EINTPEND寄存器 SRCPND 寄存器
恢复被中断的程序,继续执行
下图是上面代码的中断执行过程图解: