中断的处理流程与异常的处理流程类似,当中断发生时,以下操作将由硬件执行:
- 保存被中断的下一条指令地址到LR_异常,在ARM State下保存的是PC+8,在Thumb State下保存的是PC+4;
- 把CPSR存入SPSR_异常;
- 修改CPSR的[M4:M0]进入异常模式;
- 跳到向量表。
但中断是由中断源产生的,这与其他异常稍有差别。比如,中断的触发方式有很多种,当中断发生时,我们是通过中断标志位来判断是哪种中断发生了;中断处理完成后,需要清楚对应的中断标志位来表示已经处理该中断请求。
与异常类似(中断也属于一种异常),中断的退出流程大致如下:
- 将LR_异常减去offset,得到的值赋给PC(offset的取值如下表)。
- CPSR = SPSR_异常,将SPSR_异常的值赋回给CPSR。
- 如果有中断标志位的话,清除中断标志位。
如上图所示,中断的处理流程主要有三步:
- 中断初始化,主要是a.设置中断,让它能够发出中断信号;b.设置中断控制器,让它能够发出中断给CPU;c.设置CPU,CPSR有I位,它是总开关,我们需要把它清零以使能中断,让CPU可以处理中断。
- 处理中断,处理时要分辨中断源。
- 处理完中断,要清中断。
其中,中断初始化主要是: - 中断源:设置按键为中断引脚(这里我们设置为双边沿触发)
- 配置中断控制器
- 设置CPSR,使能中断(将CPSR的I为清0)
通过上图,我们知道,按键S2和S3接到分别接到GPF0和GPF2,同理,S4和S5分别是GPG3和GPG11。所以把GPF0和GPF2设置为0b10。
首先,配置GPIO为中断引脚,然后设置中断触发方式为双边沿触发, 需要注意的一点是,eint11和19的中断信号有可能被屏蔽,即无法送达中断控制器,这里要将它们设置为enable interrupt,eint0和eint2则无法被屏蔽,这可以通过中断控制器的流程图等相关信息获取。 配置函数如下:
设置好中断源,接着要设置中断控制器,下图是S3C2440的中断流程示意图。
上图中可以看到,中断源被分为两类,一类叫做Sources,一类叫做Sub Sources,它们的区别是Sub Sources的中段信号传导SRCPND之前,还要经过SUBSRCPND和SUBMASK,而Sources则可以直达SRCPND。
下图可以看到,EINT0,EINT2,EINT11和EINT19都是Source,其中EINT11和19是通过同一条中断线,EINT8~23。
还有一些则是Sub Source。
它的信号进来,会经过SRCPND(用来显示哪个中断产生了, 需要清除对应位),MASK(用来屏蔽中断, 1-masked),Priority(多个中断发生时,通过优先级来选择优先响应哪个中断),INTPND(用来显示当前优先级最高的、正在发生的中断, 需要清除对应位。也可以INTOFFSET来找到INTPND中哪一位被设置为1,这个会由硬件清0)。
所以,SRCPND和INTPND是在中断处理的过程中判断要处理哪个中断的,这不需要设置,我们只需要设置MASK将中断服务打开就可以了。