三、中断分类
1. 中断源硬件中断(Hardware Interrupt)可屏蔽中断(maskable interrupt)。硬件中断的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。非可屏蔽中断(non-maskable interrupt,NMI)。硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断(一个硬件时钟以恒定频率—如50Hz—发出的中断)。处理器间中断(interprocessor interrupt)。一种特殊的硬件中断。由处理器发出,被其它处理器接收。仅见于多处理器系统,以便于处理器间通信或同步。伪中断(spurious interrupt)。一类不希望被产生的硬件中断。发生的原因有很多种,如中断线路上电气信号异常,或是中断请求设备本身有问题。软件中断(Software Interrupt)
软件中断SWI,是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态的子例程,它常被用作实现系统调用(System call)。
外部中断I/O设备:如显示器、键盘、打印机、A / D转换器等。数据通道:软盘、硬盘、光盘等。数据通道中断也称直接存储器存取(DMA)操作中断,如磁盘、磁带机或CRT等直接与存储器交换数据所要求的中断。实时时钟:如外部的定时电路等。在控制中遇到定时检测和控制,为此常采用一个外部时钟电路(可编程)控制其时间间隔。需要定时时,CPU发出命令使时钟电路开始工作,一旦到达规定时间,时钟电路发出中断请求,由CPU转去完成检测和控制工作。用户故障源:如掉电、奇偶校验错误、外部设备故障等。产生于CPU内部的中断源由CPU得运行结果产生:如除数为0、结果溢出、断点中断、单步中断、存储器读出出错等。执行中断指令swi非法操作或指令引起异常处理。2. 中断类型
GIC 中断类型有3种:SGI(Software-generated interrupt)、PPI(Private peripheral interrupt )、SPI(Shared peripheral interrupt)。
SGI: SGI为软件可以触发的中断,统一编号为0~15(ID0-ID7是不安全中断,ID8-ID15是安全中断),用于各个core之间的通信。该类中断通过相关联的中断号和产生该中断的处理器的CPUID来标识。通常为边沿触发。
PPI: PPI为每个 core 的私有外设中断,统一编号为 16-31 。例如每个 CPU 的 local timer 即 Arch Timer 产生的中断就是通过 PPI 发送给 CPU 的(安全为29,非安全为30)。
通常为边沿触发和电平触发。
SPI: SPI 是系统的外设产生的中断,为各个 core 公用的中断,统一编号为 32~1019 ,如 global timer 、uart 、gpio 产生的中断。通常为边沿触发和电平触发。
Note:电平触发是在高或低电平保持的时间内触发, 而边沿触发是由高到低或由低到高这一瞬间触发;在GIC中PPI和SGI类型的中断可以有相同的中断ID。
3. 中断分派模式
1-N mode (SPIs using the GIC 1-N model)表示中断可以发给所有的CPU,但只能由一个CPU来处理中断;换句话说,这种类型的中断有N个目标CPU,但只能由其中一个来处理;当某一个处理器应答了该中断,便会清除在所有目标处理器上该中断的挂起状态。
N-N mode (PPIs and SGIs using the GIC N-N model)表示中断可以发给所有CPU,每个CPU可以同时处理该中断。当该中断被某一个处理器应答了,这不会影响该中断在其他CPU接口上的状态。
举两个例子说明:
1)UART 接收到一包数据,产生了一个中断给GIC,GIC可以将该中断分配给CPU0-7中任何一个处理;假设该中断分配给CPU0处理了,那么在中断处理函数里面会把接收到的数据从UART FIFO读出。可以想象一下,如果CPU0在读数据时,另外一个CPU也在处理该中断,恰巧也在读数据,那么CPU0读到的数据是不全的。这就是1-N model中断,或者说SPI中断。
2)比如CPU0给CPU1-7发送中断,想告知对方自己正在处理某个进程A。这种场景下,CPU1-7都接收到中断,都进入中断处理函数,CPU1-7获取到CPU0的信息后,在进程调度时,就可以绕开进程A,而自己调度其他进程。
注:这个例子只是说明N-N model,实际上进程调度不都全是这样的。
4. 通用中断处理
当GIC接收到一个中断请求,将其状态设置为Pending。重新产生一个挂起状态的中断不影响该中断状态。
中断处理顺序:
① GIC决定该中断是否使能,若没有被使能对GIC没有影响;
② 对于每个Pending中断,GIC决定目标处理器;
③ 对于每个处理器 ,Distributor根据它拥有的每个中断优先级信息决定最高优先级的挂起中断,将该中断传递给目标CPU Interface;
④ GIC Distributor将一个中断传递给CPU Interface后,该CPU Interface决定该中断是否有足够的优先级将中断请求发给CPU;
⑤ 当CPU开始处理该异常中断,它读取GICC_IAR应答中断。读取的GICC_IAR获取到中断ID,对于SGI,还有源处理器ID。中断ID被用来查找正确的中断处理程序。
GIC识别读过程后,将改变该中断的状态:
a) 当中断状态变为active时,如果该中断挂起状态持续存在或者中断再次产生,中断状态将从Pending转化为pending & active
b) 否则,中断状态将从pending状态变为active
⑥ 当中断完成中断处理后,它需要通知GIC处理已经完成。这个过程称为 priority drop and interrupt deactivation:
a) 总是需要向EOIR寄存器写入一个有效的值(end of interrupt register)b) 也需要接着向GICC_DIR写入值(deactivate interrupt register)
5. 中断优先级
软件可以通过给每一个中断源分配优先级值来配置中断优先级。优先级的值是个8位的无符号二进制数,GIC支持最小16和最大256的优先级级别。
如果GIC实现的优先级少于256,那么优先级字段的低阶位为RAZ/WI。这就意味着实现的优先级字段个数范围是4~8,如下图所示:
Effect of not implementing some priority field bits
Note:
1)、如何确定优先级字段所支持的优先级位?通过软件往可写GICD_IPRIORITYn优先级字段写入0XFF,然后回读出该字段的值便可以确定优先级字段所支持的优先级位(因为有些位没实现是RAZ/WI)
2)、ARM 推荐在检查中断优先级范围之前先:? 对于外设中断,软件先禁用该中断? 对于SGI,软件先检查该中断确定为inactive
6. 中断抢占
在一个active中断处理完之前,CPU interface支持发送更高优先级的挂起中断到目标处理器。这种情况必要条件如下:
该中断的优先级高于当前CPU interface 被屏蔽的优先级该中断的组优先级高于正在当前CPU interface处理的中断优先级7. 中断屏蔽
CPU interface的GICC_PMR寄存器定义了目标处理器的优先级阀值,GIC仅上报优先级高于阀值的pending中断给目标处理器。寄存器初始值为0,屏蔽所有的中断。
四、FS4412中断外设-key
下面我们来分析FS4412开发板的第一个中断设备按键。
1. 电路图
key
由该电路图可得:
按键k2 连接在GPX1_1引脚
控制逻辑k2 按下 ---- K2闭合 ---- GPX1_1 低电压k2 常态 ---- K2打开 ---- GPX1_1 高电压
以下是key2与soc的连接,
key与soc的连接
可以看到key2复用了GPIX1_1这个引脚,同时该引脚还可以作为中断【XEINT9】使用。
顺便看下GPXCON寄存器的配置
GPX1CON
由上图所示,
GPX1CON地址为0x1100C20;key2如果要做为输入设备,只需要将GPX1CON[7:4]设置为0x0;key2如果要做为中断信号,只需要将GPX1CON[7:4]设置为0xf。2. key中断处理中断配置
key与soc的关系图如下图所示:
按键中断寄存器配置流程
由上图所示:
按键是直接连到GPIO控制器的EXT_INT_CON用来设置按键中断的触发方式,下降沿触发GPX1CON寄存器用于设置该GPIO位中断信号输入EXT_INT_MASK用于使能该中断ICDISER用于使能相应中断到分配器ICDDCR分配器开关ICDIPTR选择CPU接口ICCPMR设置中断屏蔽优先级ICCICR打开CPU开关,把CPU接口内的中断能够送到相应的CPU清中断
CPU处理完中断,需要清除中断,对于按键来说,有3个寄存器需要操作:
清中断