中断:
b.设置中断控制器(使能中断控制器的中断源组)
c.打开总开关(cpsr中的一个值)
在6410 arm体系中,有很多模块可以产生中断,比如GPIO,UART,TS等都可以产生。在这些模块和CPU之间还有一个中断控制器。这个中断控制器就是用于协调这些模块和CPU之间的交互的。比如:GPIO和UART同时发出中断请求,那么CPU来处理那个中断呢?这就需要用到中断控制器了。如下图所示:
从上图可以看到ARM1176中断控制器支持64组中断源。具体哪64组可以参考6410Datasheet。假如使用按键,则使用到的中断源为第0和第1组中断源
CPU在执行每一条指令之前,都会先判断有无中断发生,若有中断发生:
硬件上:
1.cpu进入IRQ模式
2.CPSR保存到SPSR_irq中
3.转换为R13_irq,R14_irq
4.把下一条指令的地址保存到R14_irq中
5.跳转到0x18地址执行
软件上:
1.保存现场
/* 1. 保存现场 */
ldr sp, =0x54000000
sub lr, lr, #4 /*减去4个字节的原因是当前指令没有执行就去执行中断处理了*/
stmdb sp!, {r0-r12, lr} /* lr就是swi的下一条指令地址 */
2.处理中断
a.分辨中断
b.调用相应的处理函数
c.处理完后清中断
/* 2.3 清中断 */
EINT0PEND = 0x3f; /* 清中断 */
VIC0ADDRESS = 0;
3.恢复现场
/* 3. 恢复现场 */
ldmia sp!, {r0-r12, pc}^ /* ^表示把spsr恢复到cpsr */
要想使用中断,该做那些工作?
1.初始化,比如按键(gpio),把按键设置为中断源
a.设置源头(按键)
代码如下:
/* 配置GPIO引脚为中断引脚 */
/* GPN0~5 设为中断引脚 */
GPNCON &= ~(0xfff);
GPNCON |= 0xaaa;
/* 设置中断触发方式为: 双边沿触发 */
EINT0CON0 &= ~(0xfff);
EINT0CON0 |= 0x777;
/* 使能中断 */
EINT0MASK &= ~(0x3f);
b.设置中断控制器(使能中断控制器的中断源组)
代码如下:
/* 在中断控制器里使能这些中断 */
VIC0INTENABLE |= (0x3); /* bit0: eint0~3, bit1: eint4~11 */
6个按键所属的中断源组为第0组和第1组
c.打开总开关(cpsr中的一个值)
代码如下:
mrs r0, cpsr
bic r0,r0,#0x9f /* 清cpsr的I位,M4~M0 */
orr r0,r0,#0x10
msr cpsr,r0 /* 进入user mode */