引言
- 为了让 CPU 获得每个外部设备的中断信号,最好的方式是在 CPU 中为每一个外设准备一个引脚接收中断,但这是不可能的,计算机中挂了很多外部设备,而且外设数量是没有上限的,无论 CPU 中准备多少引脚都不够用
- 对于外部的可屏蔽中断,CPU 上只有一根 INTR 引脚,但是需要产生中断信号的设备那么多,如何对众多的中断信号进行区分呢?
- 一般都是通过可编程中断控制器(Programmable Interrupt Controller, PIC),在计算机中使用最多的就是 8259A 芯片。
- 虽然现代计算机都已经是 APIC(高级可编程中断控制器) 了,但是由于 8259A 芯片是那么的经典,大部分描述外部中断的文章都会用它来举例
基础概念
- 8259A 是专门为处理器设计的中断管理芯片,其功能如下:
- 可通过编程对 8259A 进行功能配置
- 屏蔽外设中断,对中断进行优先级判决
- 向处理器提供中断向量
- 对 8259A 的编程控制是操作系统内核的重要工作
- 每一片 8259A 可以提供 8 个中断输入引脚,如果有中断数量超过 8 个,还可以对个芯片串联在一起使用,我们称之为级联。
- 如下图,两片芯片级联在一起,就可以提供 15 个中断信号:
- 主片的输出引脚 INT 连接到 CPU 的 INTR 引脚上
- 从片的输出引脚 INT 连接到主片的引脚 2 上
8259A 内部结构
- 想要搞清楚 8259A 工作流程,我们得先知道其内部结构,如下图
- 8259A 关键组成介绍
信号或寄存器 | 说明 |
INT | 选出优先级最高的中断请求后,发信号通知 CPU |
INTA | INT Acknowledge,中断响应信号。收来自 CPU 的 INTA 接口的中断响应信号 |
IMR | Interrupt Mask Register,中断屏蔽寄存器,宽度是 8 位,用来屏蔽某个外设的中断 |
IRR | Interrupt Request Register,中断请求寄存器,宽度是 8 位。它的作用是接受经过 IMR 寄存器过滤后的中断信号并锁存,此寄存器中全是等待处理的中断 |
PR | Priority Resolver,优先级仲裁器。当有多个中断同时发生,或当有新的中断请求进来时,将它与当前正在处理的中断进行比较,找出优先级更高的中断 |
ISR | In-Service Register,中断服务寄存器,宽度是 8 位。当某个中断正在被处理时,保存在此寄存器中 |
- 以上介绍的寄存器都是 8 位,这是有意这样做的,其原因是 8259A 共 8 个 IRQ 接口,可以用 8 位寄存器中的每一位代表 8259A 的每个 IRQ 接口
8259A 工作流程
- 当 8259A 收到一个中断后会发生什么呢?
- 8259A 首先检查 IMR 寄存器中是否已经屏蔽了来自该 IRQ 接口的 中断信号。IMR 寄存器中的对应的位为 1,则表示中断屏蔽,为 0,则表示中断放行
- 如果 IMR 相应位已经被置 1,即表示来自该 IRQ 接口上的中断已经被屏蔽了,则将该中断信号丢弃,否则,将其送入 IRR 寄存器,将该 IRQ 接口所在 IRR 寄存器中对应的 BIT 置 1。IRR 寄存器的作用“相当于”待处理中断队列。
- 在某个恰当时机,优先级仲裁器 PR 会从 IRR 寄存器中挑选一个优先级最大的中断。此处的优先级决判很简单,就是 IRQ 接口号越低,优先级越大,所以 IRQ0 优先级最大
- 之后,8259A 会在控制电路中,通过 INT 接口向 CPU 发送 INTR 信号
- 信号被送入了 CPU 的 INTR 接口后,于是 CPU 将手里的事情放下,马上通过自己的 INTA 接口向 8259A 的 INTA 接口回复一个中断响应信号,表示现在 CPU 我已准备好啦,8259A 你可以继续后面的工作
- 8259A 在收到这个信号后,立即将刚才选出来的优先级最大的中断在 ISR 寄存器中对应的 BIT 置 1,此寄存器表示当前正在处理的中断,同时要将该中断从“待处理中断队列”寄存器 IRR 中去掉,也就是在 IRR 中将该中断对应的 BIT 置 0
- 之后,CPU 将再次发送 INTA 信号给 8259A,这一次是想获取中断对应的中断向量号,就是我们前面所说的 0~255 的“整数”
- 由于大部分情况下 8259A 的起始中断向量号并不是 0(起始中断向 量号被修改,原因后面会说),所以用起始中断向量号+IRQ 接口号便是该设备的中断向量号,由此可见,外部设备虽然会发中断信号,但它并不知道还有中断向量号这回事,不知道自己会被中断代理(如 8259A)分配一个这样的整数。随后,8259A 将此中断向量号通过系统数据总线发送给 CPU
- CPU 从数据总线上拿到该中断向量号后,用它做中断向量表或中断描述符表中的索引,找到相应的中断处理程序并去执行
8259A工作方式
- 8259A 之所以可编程,就是因为其很多工作都可以软件配置,下面我们来看看 8259A 有哪些工作方式:芯片连接方式,中断触发方式,数据连接方式,中断优先级方式,中断嵌套方式,中断屏蔽方式,中断结束方式
芯片连接方式
- 单片工作
- 多片级联工作
中断触发方式
- 边沿触发(推荐):中断引脚电平变化的一瞬间认为中断申请到来(上升沿触发)
- 电平触发:中断引脚上的信号保持稳定电平一段时间后认为中断申请到来
数据连接方式
- 非缓冲方式:将 8259A 直接与数据总线相连
- 缓冲方式:将 8259A 通过总线驱动器与数据总线相连
中断优先级方式
- 固定优先级方式:优先级由高到低的顺序是:IRQ0, IRQ1, IRQ2, ... IRQ7
- 自动循环方式:某一中断请求被响应后,该中断源优先级自动变为最低
- 特殊循环方式:通过编程指定某个中断源优先级成为最低,其它中断源优先级自动改变
中断嵌套方式
- 完全嵌套方式(默认方式):执行中断服务程序期间,不响应同级或较低优先级的中断
- 特殊完全嵌套方式:执行中断服务程序期间,可响应同级别优先级中断,不响应较低优先级中断
中断屏蔽方式
- 普通屏蔽方式:将 IMR 中的某一位或几位置 1,屏蔽掉对应的中断请求
- 特殊屏蔽方式:未被屏蔽的中断源均可在中断服务程序执行期间中被响应,即低优先级中断可以打断正在服务的高优先级中断
中断结束方式
- 自动结束方式:8259A 自动清除 ISR 中已置位中的优先级最高的位,该方式只适用于非多重中断的情况
- 手动结束方式:在中断服务程序的最后,向 8259A 发送中断结束命令,将 ISR 中相应的位清零,表明中断服务程序已经完成