7.3.2 中断的处理过程

7.3.2 中断的处理过程

计算机处理中断的5个步骤为中断请求、中断源识别(中断判优)、中断的应、中断处理和中断返回。下面以硬件可屏蔽中断为例,简要介绍中断处理过程的5个步骤。

图7.10 中断嵌套

1.中断请求

当I/O 设备需要CPU 服务时,第一步要发出一个有效的中断请求信号送到CPU 的中断输入端。按照不同的触发方式,中断请求信号可分为边沿触发和电平触发。边沿触发指的是CPU 根据中断请求端上有无从低电平到高电平或从高电平到低电平的跳变来判断是否有中断请求信号;电平触发指的是CPU 根据中断请求端上有无稳定的电平信号(高电平或低电平)来判断是否有中断请求信号。通常,CPU 能够即时响应的中断可以采用边沿触发,CPU 不能即时响应的中断则应采用电平触发,否则中断请求信号就会丢失。8086/8088 CPU 对由NMI端传来的中断采用边沿触发,对由INTR端传来的中断采用电平触发。为了保证产生的中断能被CPU 处理,由INTR端传来的中断请求信号应保持到该请求被CPU 响应为止。CPU 响应中断后,还要及时清除INTR 信号,以免造成多次中断响应。

2.中断源识别(中断判优)

由于中断的产生具有随机性,当系统中的中断源多于1个的时候,就有可能在某一时刻有两个或多个中断源同时发出中断请求。而CPU 只有一条中断申请线,并且任一时刻只能响应并处理一个中断。这就要求CPU 能够识别中断源,找出中断优先级最高的中断源并响应之,在这个中断响应完成后,再响应级别较低的中断源的请求。中断源的识别及其优先级的顺序判定就是中断源识别(中断判优)要解决的问题。中断源识别(中断判优)的方法分为软件和硬件两种。

(1)软件判优

软件判优是指通过软件来排序各中断源的优先级别。当有中断申请发生时,CPU 响应中断,进入中断服务程序后首先查询是哪个中断源申请的中断。第一个被查询的中断源级别最高,若有中断申请,马上响应,处理第一个中断源所要求处理的事情。处理结束,再返回查询第二个中断源是否也有中断申请,若有则转去处理;若没有,再查询第三个中断源是否有中断申请,其他中断源以此类推。越先被查询的中断源级别越高,越后被查询的中断源级别越低。

使用软件判优法,也需要一定的硬件电路辅助,电路原理图如图7.11所示。在图中,I/O设备的中断请求信号IRQ 被锁存在中断请求寄存器中,并通过“或”门经过或运算后送到CPU 的INTR 端,同时把I/O 设备的中断请求状态经并行接口输入CPU。

图7.11 软件判优的电路原理

若一个或几个中断源发出中断请求,中断请求信号经过中断请求寄存器后,经“或”门连接到CPU 的INTR 引脚上。CPU 响应中断后进入中断处理程序,中断处理程序首先读取并查询并行输入接口的中断状态,查到哪个中断源有请求就调用哪个中断源的中断服务程序。软件查询中断源的次序就反映了各中断源优先级别的高低,先被查询的中断源优先级别最高,后被查询的中断源优先级依次降低。软件判优方法硬件电路简单、优先权安排灵活,但软件判优所花时间较长,在中断源较多的情况下会影响到中断响应的实时性。我们可以使用硬件判优来克服软件判优的缺点。

(2)硬件判优

硬件判优是指使用专用的硬件电路或控制器来排序各中断源的优先级别。硬件判优电路有很多种,下面介绍两种常用的硬件判优方法。

①中断控制器判优。中断控制器采用一个中断优先级判别器来判别哪个中断请求的优先级最高。当CPU 响应中断时,中断控制器将优先级最高的中断源所对应的中断类型码发送给CPU。中断类型码是为每一个中断源分配的一个编号,该编号乘以4,就等于中断源相对应的中断服务程序的入口地址。

8086/8088系列微机中的8259A 芯片是一种可编程的中断控制器,通过级联使用,它可对多达64级的中断源进行优先级管理。

②链式判优。链式判优的基本思想是将所有的中断源构成一个链(称菊花链),利用I/O设备在系统中的物理位置来决定中断优先级。越排在链前面的中断源的优先级越高,高优先级别的中断会自动封锁低优先级别的中断。链式优先权排队电路如图7.12所示。该电路具备以下基本功能:

a.当有两个以上中断源申请中断时,能够响应最高级的中断,屏蔽低级的中断。

b.当响应较低级的中断时,如果有更高级的中断,可以暂停低级中断服务,立即响应高级别的中断。

图7.12 菊花链中断判优电路

【例7.4】 图7.12中4台设备分别为1#、2#、3#、4#,采用菊花链的方法向CPU 申请中断。1#设备在电路的最前面,级别最高,4#设备在电路的最后面,级别最低。假设1#、2#两台设备同时申请中断,INT1=1,INT2=1,先经过“或”门,使用INTR 线向CPU申请中断。如果此时CPU 的中断允许标志IF=1,则CPU 会在结束当前指令后响应中断请求,并通过线发出中断响应信号。这时,“与”门C1的输出FC1=∧INTA,由于=0,INTA=1,所以FC1=0。“与”门D1 的输出FD1=INT1∧INTA,由于INT1=1,INTA=1,所以FD1=1,1#三态缓冲器被选通,1#设备可以与CPU 进行数据交换,CPU 响应1#设备的中断申请。“与”门D2的输出FD2=FC1∧INT2,由于FC1=0,INT2=1,所以FD2=0,2#三态缓冲器无法选通,2#设备无法与CPU 进行数据交换。

由以上分析可以看出,如果1#设备与2#设备同时向CPU 发出中断请求,由于=0,致使FC1=0。这样就关闭了C1门,CPU 只能响应1#设备的中断申请,无法响应2#设备的中断申请,也就是说1#设备的中断优先级比2#设备要高。

当1#设备中断响应结束后,撤销中断申请信号,使INT1=0。此时,2#设备中断申请信号INT2并没有撤销,通过INTR 线再一次向CPU 发出中断请求。CPU 响应中断,通过线发出中断响应信号。这时,“与”门C1的输出FC1=∧INTA,因为=1,INTA=1,所以FC1=1。“与”门D2的输出FD2=FC1∧INT2,因为FC1=1,INT2=1,所以FD2=1,2#三态缓冲器被选通,2#设备可以与CPU 进行数据的交换,CPU 可响应2#设备的中断申请。当2#设备申请中断服务时,INT2=1,FC2=FC1∧,因为FC1=1,=0,所以FC2=0。因为FC2=0,经过分析即可得知此时3#设备即使有中断申请也不能得到CPU 的响应。

综上所述,菊花链硬件电路通过菊花链逻辑,实现了设备中断申请级别在电路中从前到后依次从高到低的排列。那么按照这个电路,高级别的中断能否打断低级别的中断呢? 假设当前正在响应2#设备的中断申请,进入了2#设备的中断服务程序,并执行了开中断的指令,IF=1。此时1#设备产生中断申请信号INT1,由前所述,中断申请信号INT1封闭C1门,关闭2#三态缓冲器,终止2#中断服务程序。INT1信号与INTA 信号通过与门(D1门)输出一信号启动1#三态缓冲器,CPU 可以与1#设备交换数据,执行1#设备的中断服务程序。因此我们看到,在菊花链电路中,高级别的中断能够打断低级别的中断。

(3)中断嵌套问题

中断嵌套与子程序嵌套相类似,即高优先级别的中断可以打断低优先级别的中断,出现一层套一层的现象。一般来说,中断控制电路在实现中断优先级的同时也实现了中断嵌套。中断嵌套的层数可以不受限制,但中断程序中的堆栈要足够大,因为每一层嵌套都要用堆栈来保护断点,这样使堆栈内容不断增加,如果堆栈空间太小,中断嵌套层次较多时就会产生堆栈溢出现象,使程序发生运行错误。

3.中断响应

经中断优先级排序后,CPU 的中断请求输入引脚上将收到一个优先级最高的中断请求信号。CPU 并不是在任何情况下都能对中断请求进行响应。CPU 要响应中断请求,必须满足以下4个条件。

①当前指令执行结束。CPU 在当前指令执行的最后一个时钟周期对中断请求进行检测,当满足本条件和下述3个条件时,当前指令执行一结束,CPU 即可响应中断。

②CPU 的中断标志位为1。只有当CPU 的IF=1,即CPU 处于开中断状态时,CPU才能响应可屏蔽中断(INTR)请求,但对与非可屏蔽中断(NMI)及软件中断无此要求。

③在当前没有发生复位、保持、软件中断和非可屏蔽中断请求时方可响应可屏蔽中断(INTR)请求。当CPU 处于复位或保持状态时,CPU 不工作,不能响应中断请求;而非可屏蔽中断(NMI)的优先级比可屏蔽中断(INTR)高,当两者同时产生时,CPU 会响应非可屏蔽中断而不响应可屏蔽中断。

④如果正在执行的指令是开中断指令(STI)或中断返回指令(IRET),则等到它们执行完后再执行一条指令,CPU 才能响应INTR 中断请求。对于前缀指令,如LOCK、REP等,CPU 会把它们和它们后面的指令看作一个整体,直到这个整体指令执行完,方可响应INTR 中断请求。

中断响应时,CPU 除了要向中断源发出中断响应信号()外,还要做下面4 项工作。

①保护硬件现场,即将标志寄存器FLAGS压栈保存。

②保护断点。将断点的段地址(CS值)和偏移量(IP值)压入堆栈,以保证中断结束后能正常返回到被中断的程序。

③获得中断服务程序入口地址。

④转移到中断服务程序。

4.中断处理

中断处理由中断服务程序完成。中断服务程序在形式上与一般的子程序基本相同,不同之处在于:中断服务程序只能是远过程调用(类型为FAR);中断服务程序要用IRET 指令返回中断主程序。在一般情况下,中断服务程序要做以下几项工作。

(1)保护软件现场

CPU 响应中断时自动完成CS和IP寄存器以及标志寄存器FLAGS的压栈,但主程序中使用的寄存器的保护则由用户按照需要而定。由于中断服务程序中也使用某些寄存器,若对这些寄存器在中断前的值不加以保护,中断服务程序会将其修改,这样中断服务程序返回主程序后,主程序就不能正确执行。对现场的保护,实际上是通过执行PUSH 指令将需要保护的寄存器内容推入堆栈而完成的。

(2)开中断

CPU 接收并响应一个中断后自动关闭中断,这样做的好处是不允许其他的中断来打断它。但有时,会有比该中断优先级更高的中断要处理,此时,应停止对该中断的服务而转入优先级更高的中断处理,故需要再开中断(即执行STI指令)。

(3)中断服务

中断服务就是对某些中断情况进行处理,例如,处理溢出错误、传送数据,处理掉电紧急保护,各种报警状态的控制处理等。

(4)关中断

因为有上述的开中断,所以在此处安排一个关中断过程(即执行CLI指令),以便恢复现场的工作顺利进行不被打断。

(5)恢复软件现场

为了中断返回后能继续正确执行主程序,在返回主程序前要将用户保护的寄存器内容从堆栈中弹出。恢复现场使用POP指令,弹出堆栈内容。应该注意的是,堆栈为先进后出型数据结构,寄存器的入栈次序与出栈次序是相反的。

5.中断返回

中断返回通过执行中断返回指令IRET 实现,其操作正好是CPU 硬件在中断响应时自动保护硬件现场和断点的逆过程,CPU 自动从现行堆栈中弹出CS、IP 和标志寄存器FLAGS的内容,以便继续执行主程序。

从发出中断请求,到该中断请求全部处理完成所经过的主要过程的流程如图7.13所示。