中断是一个过程,是CPU在执行当前程序的过程中因硬件或软件的原因插入了另一段程序运行的过程。因硬件原因引起的中断过程的出现是不可预测的,即随机的,而软中断是事先安排的。引起中断的信号源称之为中断源。根据中断源的来源将中断分为外部中断和内部中断。中断源来自SoC内部(内部外设)的中断称为内部中断。中断源来自SoC外部,通过中断对应的GPIO引脚产生的中断称为外部中断。中断有四种状态:
Inactive(不激活):没有被激活或挂起的中断
Pending(挂起):这个中断可以被硬件识别或是由软件产生的,正处於等待处理器处理。
Active(激活):中断被处理器从通用中断控制器中的中断源中识别了出来,并且正在处理这个中断,且没有处理完成。
Active and pending(激活和挂起):处理器正在处理某个中断,且通用中断控制器有一个挂起的中断。
S5PV210共有4个向量中断控制器,支持93个中断源。
主要向量中断控制寄存器:
VIC0INTENABLE:中断使能
VIC0INTENCLEAR:中断禁止
VIC0INTSELECT:中断选择,IRQ/FIQ
VIC0IRQSTATUS:IRQ中断状态寄存器
VIC0FIQSTATUS:FIQ中断状态寄存器
VIC0VECTADDR:中断源对应的ISR地址
VIC0ADDRESS:向量地址寄存器,当有中断发生时,硬件上会将当前中断的中断服务例程ISR地址从寄存器VICVECTADDR自动拷贝到寄存器VICDDR中
S5PV210在BL0阶段关闭了FIQ和IRQ,因此程序开始时需要手动打开IRQ。
// 开中断
mov r0, #0x13
msr CPSR_cxsf, r0
S5PV210中断处理流程:
A、初始化中断控制器
外部中断的中断控制器的初始化包括:外设相应GPIO引脚设置为外部中断模式、外部中断控制寄存器的初始化、中断向量控制寄存器的初始化。
内部中断的中断控制器的初始化包括:中断向量控制寄存器的初始化
B、绑定中断源的ISR到向量中断控制器的VICnVECTADDR
C、使能中断源中断
A、异常向量表跳转到IRQ入口
CPU处理常规任务时收到中断的通知,于是S5PV210根据iROM固化代码跳转到iRAM的异常向量表的IRQ异常向量地址。一般将负责保护现场、处理中断、恢复现场的汇编代码段的起始地址赋值给IRQ异常向量地址,作为处理中断的入口。
B、保护中断现场
处理中断之前先要保护现场,主要工作是:设置IRQ模式下的栈,将R0-R12,LR压栈保存(由于流水线的原因,LR一般为当前执行的指令地址加8,LR减去4就是下一条要运行指令的地址)。
C、执行中断处理程序
查看VICnADDR寄存器是否有ISR函数地址,如果有,执行ISR。一般在中断发生之前已经绑定好ISR到VICnVECTADDR。
D、恢复现场
执行ISR后,将栈中的R0-R12,LR分别出栈R0-R12,PC,程序将根据PC的值自动跳转会到常规任务执行。
中断处理的一般模型如下:
#define IRQ_STACK (0xD0037F80)
.global irq_exception
irq_exception:
//设置IRQ模式下的栈
ldr sp,=IRQ_STACK
//保护现场
//保存LR
sub lr,lr,#4
//保存R0~R12
stmfd sp!,{r0-r12,lr}
bl irq_handler//中断处理程序
//恢复现场
ldmfd sp!,{r0-r12,pc}^
中断处理程序和中断服务例程ISR是两个非常容易混淆的概念,但两者是两个不同的概念。内核中的中断处理程序与中断服务例程的关系如下图:
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M01/82/87/wKioL1dX6hvzjFDSAAFX-pO4MLY260.png" title="图片1.png" alt="wKioL1dX6hvzjFDSAAFX-pO4MLY260.png" />
每一个触发中断的中断源对应一个中断处理程序,每一个中断处理程序对应多个中断服务例程。对中断服务例程进行注册后中断服务例程就会挂在中断请求队列中。中断处理程序是中断向量的处理程序,如果多个设备共享一个中断源,中断处理程序必须要调用每个设备的中断服务例程ISR。
在裸机中,由于每个中断源(终端编号)只有一个对应的中断向量地址寄存器VICVECTADDR,所以每一个中断处理程序只有一个中断服务例程。
中断处理的编程模型:
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M00/82/89/wKiom1dX6UHyOpmkAAOQORa0UDA119.png" title="图片2.png" alt="wKiom1dX6UHyOpmkAAOQORa0UDA119.png" />
A、查阅底板电路图按键相关部分:
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M01/82/89/wKiom1dX6WLSu5AAAAA4jfpEcC8668.png" title="图片3.png" alt="wKiom1dX6WLSu5AAAAA4jfpEcC8668.png" />
Smart210开发板共有四个用户按键,对应引脚为XEINT16——XEINT19
B、查阅核心板电路原理图按键相关部分:
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M00/82/89/wKiom1dX6YnD0h7jAAFZG63ejTY828.png" title="图片4.png" alt="wKiom1dX6YnD0h7jAAFZG63ejTY828.png" />
按键引脚XEINT16——XEINT19对应的GPIO引脚为GPH2_0——GPH2_3
#define GPH2CON ( *((volatile unsigned long *)0xE0200C40) )
//设置K1--K4按键的GPIO引脚为外部中断模式
GPH2CON |= 0xFFFF<<0;
S5PV210的外部中断通过外部中断对应的GPIO产生,外部中断寄存器位于文档中GPIO部分。
外部中断的主要寄存器:
EXT_INT_N_CON:设置外部中断的触发方式
EXT_INT_N_PEND:中断挂起寄存器,32位,每位对应一个外部中断源,
EXT_INT_N_MASK:中断掩码控制寄存器
四个用户按键的外部中断号为EXT_INT16——EXT_INT19,选择第二组外部中断控制寄存器。
//中断触发模式
// 低电平触发
//EXT_INT_2_CON &= ~(0xFFFF);
//下降沿触发
//EXT_INT_2_CON |= (0x2<<0 | 0x2<<4 | 0x2<<8 | 0x2<<12);
//双边沿触发
EXT_INT_2_CON |= (0x4<<0 | 0x4<<4 | 0x4<<8 | 0x4<<12);
//打开外部中断
EXT_INT_2_MASK &= ~(0xF<<0);
//清除挂起,清除时需要写1
EXT_INT_2_PEND |= 0xF<<0;
// 禁止所有中断
VIC0INTENCLEAR = 0xffffffff;
VIC1INTENCLEAR = 0xffffffff;
VIC2INTENCLEAR = 0xffffffff;
VIC3INTENCLEAR = 0xffffffff;
// 选择中断类型为IRQ
VIC0INTSELECT = 0x0;
VIC1INTSELECT = 0x0;
VIC2INTSELECT = 0x0;
VIC3INTSELECT = 0x0;
// 清VICxADDR
// VICxADDR:当前正在处理的中断的中断处理函数的地址
VIC0ADDR = 0;
VIC1ADDR = 0;
VIC2ADDR = 0;
VIC3ADDR = 0;
设置好GPIO外部中断模式、外部中断控制寄存器、向量中断控制寄存器后,外部中断就能到达CPU内部了。对于内部中断来说,无需设置GPIO、外部中断控制器,只需要设置向量中断控制寄存器,中断就能到达CPU。
CPU收到中断通知后就可以按照中断处理流程处理中断了。
工程源代码见附件,工程编译后在Smart210正常烧录运行。
开机串口打印数字,按下K1-K4按键时打印信息。
参考博文:
三星S5PV210(ARM-Cortex A8)中断过程图解 (CSDN Im刘北席)
中断处理程序&中断服务例程(chinaunix Helianthus_lu)
本文出自 “生命不息,奋斗不止” 博客,转载请与作者联系!