中断
中断源管理
中断是一种异步异常,CPU需要处理很多来自设备的中断请求,而CPU引出的line只有IRQ线和FIQ线,所以就得引入中断控制器帮助CPU搞清楚是中断的来源。
MINI2440的中断控制器,可以接受来自60个中断源的请求。提供这些中断源的是内部外设,如DMA 控制器、 UART、IIC 等等。在这些中断源中,UARTn、AC97 和EINTn 中断对于中断控制器而言是“或”关系。
当从内部外设和外部中断请求引脚收到多个中断请求时,中断控制器在仲裁步骤后请求ARM920T 内核的FIQ 或IRQ。
中断控制器对于中断源的是层次化的,因为中断源很多,而中断源寄存器的位数是有限的,无法表达过多的中断源。每个bit都表达一个中断源,而多个子中断源对应中断源寄存器的同一个bit:
同样的,多个外部中断源,对应同一个bit:
中断过程
根据中断类型,SRCPND的置位过程有些不同:
- 子中断。中断发生后SUBSRCPND相应位置1,如果没有INTSUBMASK屏蔽,那么SRCPND相应的bit被置1,表示挂起等待处理。
- 不带子中断。中断发生后SRCPND相应位置1,如果没有被INTMSK屏蔽,那么SRCPND相应的bit被置1,表示挂起等待处理。
- 外部中断。EINT0-EINT3发生后SRCPND相应位置1,如果没有被INTMSK屏蔽,那么等待进一步处理。EINT4-EINT23发生后EINTPEND相应位置1,如果没有被EINTMASK屏蔽,那么SRCPND相应位EINT4-7或EINT8-23置1,如果没有被INTMSK屏蔽,等待进一步处理。
SRCPND中有bit被置位,根据对应的MASK bit是否被置位,判断是否发给CPU处理,fip和irq都是可以被屏蔽的。
如果没有被屏蔽,那么看中断模式: - 快中断,直接把信号送到FIQ线上
- 普通中断,SRCPND可以有多位置1(FIQ 只能有一个),多置位情况下,需要经过priority选出一个最高优先级的去执行,选出的中断的INTPND的对应bit置1.
注意,这个过程都是硬件完成,软件的职责是读取INTPND,分清哪个中断源触发了中断,然后让CPU执行到正确的,响应的,处理函数。
开启中断
- 如果是不带子中断的内部中断,只需设置INTMSK,让它不屏蔽中断就可以了;
- 如果是带子中断的内部中断,需设置INTSUBMSK和INTMSK,让它门不屏蔽中断就可以了;
- 如果是外部中断,对于EINT4-23需要设置EINTMASK和INTMSK。对于EINT0-EINT3只需设置INTMSK;
注意,Arm Core中CPSR寄存器的I位和F位,是决定中断是否有效的总开关。
清除中断
- 如果是不带子中断的内部中断,只需清除SRCPND、INTPND,注意清除需对应位写1。
- 如果是带子中断的内部中断,需清除SRCPND和SUBSRCPND、INTPND,注意先清除SUBSRCPND,再清除SRCPND。 因为,如果你先清除SRCPND的话,然后在清除SUBSRCPND的过程中,SRCPND会以为又有中断发生, 又会置1,也就是说一次中断会响应两次。所以必须先掐断源头。
- 如果是外部中断,对于EINT4-23需要清除EINTPEND和SRCPND、INTPND(同样注意顺序)。对于EINT0-EINT3只需清除SRCPND、INTPND。
外部中断源,次级中断源,主中断源的关系
平级映射
S3C2440A的中断控制器所能提供的信息只是哪个主中断源上来了中断,例如,28号主中断源上来了中断,还需要进一步确定到底是哪一个次级中断源上(INT_RXD0、INT_TXD0、INT_ERR0)来了中断。
因为有多个中断源,自然用数组表示最方便直观,并且这个数组包含在LMOSEM内核的可执行文件中。IRQ_MAX定义为71。为什么是71,不是只有60个中断源吗?因为我们为了直接用数组下标寻找intfltdsc_t结构,采用了平级映射的方法,例如,28号主中断源发生了中断,发现它其中包含有3个次级中断源,就用28加上一个次级偏移量:SINT_OFFSET(32),找到相应的intfltdsc_t结构。再如,5号主中断源发生了中断,发现它其中包含有16个外部中断源,就用5加上一个外部次级偏移量EINT_OFFSET(47),找到相应的intfltdsc_t结构。不难发现,数组下标031对应的是主中断源,数组下标3246对应的是次级中断源,数组下标47~70对应的是外部中断源。
HAL_DEFGLOB_VARIABLE(intfltdsc_t,machintflt)[IRQ_MAX]; //71