推迟中断事件到线程中处理是提高系统整体实时性的普遍做法,这种做法推迟非关键事件到线程中处理来保证关键中断事件的及时响应和处理。
mingdu.zheng at gmail dot com
有些中断因为事关实时事件的最后期限,因此必须在中断服务例程中立即处理。而有些中断则不需要实时处理而且中断处理比较复杂,例如以太网数据包中断,USB主机控制器中断等。一般而言,关乎实时性的中断都是比较简单,可以比较快速处理的,比较复杂的中断实时性要求一般都不会太高。
复杂的中断往往要与线程进行大量的数据交换,为了保证数据一致性,线程在处理与中断共享的数据结构时需要关中断。将中断推迟到线程中处理,可以避免中断服务例程和线程之间的数据共享,也就避免了关中断,正是因为减少了关中断,因此提高了其它关键中断的响应速度。
一般做法是,在中断服务例程中屏蔽外设中断,然后唤醒处理线程,线程处理完成后重新开启外设中断。
屏蔽中断有三种方式,一是屏蔽处理器的中断,二是通过设置中断控制器中对应外设的控制位来屏蔽指定外设的中断,三是通过外设寄存器的中断屏蔽寄存器屏蔽外设中断。显然不能采用屏蔽处理器中断的方式,因为这会屏蔽掉所有中断。通过中断控制器屏蔽外设中断的方式是可行的,因为屏蔽某一外设时不会影响其它外设的中断响应,但是如果外设传递给中断控制器的中断信号是电平触发而不是边沿触发,那么会产生重复中断的问题。在中断服务例程中屏蔽中断并退出中断服务例程后,因为实际并没有处理中断事件,因此传递给中断控制器的中断信号仍然是有效的,只不过中断被屏蔽而不响应中断,但是该中断立刻进入了挂起状态,在线程中处理完中断事件后,虽然中断信号已经失效,但是因为之前已经挂起了一个中断,因此开启中断后又立刻进入中断服务例程,这是一个重复的中断事件,是没有意义的。
最理想的办法是通过外设的中断屏蔽寄存器关闭中断。屏蔽外设中断后,外设传递给中断控制器的中断信号也是无效的,因此不会产生重复中断,无论传递给中断控制器的中断信号是电平触发的还是边沿触发的。
如外设有全局中断屏蔽位,那么设置或清除该控制位就可以屏蔽或开启外设中断。如果外设没有全局中断屏蔽位,那么需要定义一个变量来存储中断屏蔽寄存器的临时值,在平常的操作过程中,对中断屏蔽寄存器的操作实际上对该变量的操作,当处理线程处理完所有事件后需要重新开启外设中断时将该变量写入外设的中断屏蔽寄存器。中断服务例程中屏蔽中断时,则屏蔽所有的外设中断。