详解8259A

时间:2024-10-23 09:33:16

详解8259A

可编程中断控制器

可编程中断控制器(PIC - Programmable Interrupt Controller)是微机系统中管理设备中断请求的管理者。当PIC向处理器的INT引脚发出一个中断信号时,处理器会立刻停下当时所做的事情并询问PIC需要执行哪个中断服务请求。PIC则通过向数据总线发出与中断请求对应的中断号来告知处理器要执行哪个中断服务过程。处理器则根据读取的中断号通过查询中断向量表(在32位保护模式下是中断描述符表)取得相关设备的中断向量(即中断服务程序的地址)并开始执行中断服务程序。当中断服务程序执行结束,处理器就继续执行被中断信号打断的程序。

8259A的级联

在80X86微机机系统中采用了8259A可编程中断控制器芯片。每个8259A芯片可以管理8个中断源。通过多片级联方式,8259A能构成最多管理64个中断向量的系统。

在PC/AT系列兼容机中,使用了两片8259A芯片,共可管理15级中断向量。其级连示意图如下
这里写图片描述

其中从芯片的INT引脚连接到主芯片的IR2引脚上,即8259A从芯片发出的中断信号将作为8259A主芯片的IRQ2输入信号。

IRQ9引脚的作用与IRQ2相同, 即PC/AT机利用硬件电路把IRQ2引脚重新定向到了PIC的IRQ9引脚上,并利用BIOS中的软件把IRQ9的中断int 71重新定向到了IRQ2的中断int 0x0A的中断处理过程。这样一来可使得任何使用IRQ2的PC/XT的8位设配卡在PC/AT机下面仍然能正常使用,做到了PC机的向下兼容。

为什么要把IRQ2重定向到IRQ9上?

早期的IBM PC/XT只有一个8259A,这样就只能处理8种IRQ。但很快就发现这根本不能满足需求,所以到了IBM PC/AT,又以级连的方式增加了一个8259A,这样就可以多处理7种IRQ。原来的8259A被称作Master PIC,新增的被称作Slave PIC。但由于CPU只有1根中断线,Slave PIC不得不级连在Master PIC上,占用了IRQ2,那么在IBM PC/XT上使用IRQ2的设备将无法再使用它,但新的系统又必须和原有系统保持兼容,怎么办?


由于新增加的Slave PIC在原有系统中不存在,所以,设计者从Slave PIC的IRQ中挑出IRQ9,要求软件设计者将原来的IRQ2重定向到IRQ9上,也就是说IRQ9的中断服务程序需要去掉用IRQ2的中断服务程序。这样,将原来接在IRQ2上的设备现在接在IRQ9上,在软件上只需要增加IRQ9的中断服务程序,由它调用IRQ2的中断服务程序,就可以和原有系统保持兼容。而在当时,增加的IRQ9中断服务程序是由PC开发商开发的BIOS提供的,不需要用户进行另外设置,所以就从根本上保证了兼容。

8259A的工作原理

在总线控制器控制下,8259A芯片可以处于编程状态和操作状态。编程状态是CPU使用IN或OUT指令对8259A芯片进行初始化编程的状态。一旦完成了初始化编程,芯片即进入操作状态,此时芯片即可随时响应外部设备提出的中断请求(IRQ0 -IRQ15),同时系统还可以使用操作命令字随时修改其中断处理方式。通过中断判优选择,芯片将选中当前最高优先级的中断请求作为中断服务对象,并通过CPU引脚INT通知CPU中断请求的到来,CPU响应后,芯片从数据总线D7-D0将编程设定的当前服务对象的中断号送出,CPU由此获取对应的中断向量值,并执行中断服务程序。

一个8259A芯片的逻辑框图如下:
这里写图片描述

图中,中断请求寄存器 IRR (Interrupt Request Register)用来保存中断请求输入引脚上所有请求,寄存器的8个比特位(D7—D0)分别对应引脚IR7—IR0。中断屏蔽寄存器 IMR (Interrup Mask Register)用于保存被屏蔽的中断请求线对应的比特位,哪个比特位被置1就屏蔽哪一级中断请求。即IMR对IRR进行处理,其每个比特位对应IRR的每个请求比特位。对高优先级输入线的屏蔽并不会影响低优先级中断请求线的输入。优先级解析器PR(Priority Resolver) 用于确定 IRR 中所设置比特位的优先级,选通最高优先级的中断请求到正在服务寄存器ISR (In-Service Register)中。ISR中保存着正在接受服务的中断请求。

来自各个设备的中断请求线分别连接到8259A的IR0—IR7引脚上。当这些引脚上有一个或多个中断请求信号到来时,中断请求寄存器 IRR 中相应的比特位被置位锁存。此时若中断屏蔽寄存器 IMR 中对应位被置位,则相应的中断请求就不会送到优先级解析器中。未屏蔽的中断请求被送到优先级解析器之后,优先级最高的中断请求会被选出。此时8259A就会向CPU发送一个INT信号,而CPU则会在执行完当前的一条指令之后向8259A发送一个INTA(INTERRUPT ACKNOWLEDGE)来响应中断信号。8259A在收到这个响应信号之后就会把所选出的最高优先级中断请求保存到正在服务寄存器ISR中,即ISR中对应比特被置位。与此同时,中断请求寄存器 IRR 中的对应比特位被复位,表示该中断请求开始被处理。此后,CPU会向8259A发出第2个INTA脉冲信号,该信号用于通知 8259A送出中断号。在该脉冲信号期间,8259A就会把一个代表中断号的8位数据发送到数据总线上供CPU读取。

这里写图片描述
到此为止,CPU中断周期结束。如果8259A使用的是自动结束中断(AEOI,Automatic End of Interrupt) 方式,那么在第2个 INTA 脉冲信号的结尾处正在服务寄存器 ISR 中的当前服务中断比特位就会被复位。若8259A 使用非自动结束方式,那么在中断服务程序结束时,程序就需要向8259A发送一个结束中断(EOI)命令以复位 ISR 中的比特位。如果中断请求来自级联的第2个8259A芯片,那么就需要向两个芯片都发送EOI命令。此后8259A就会去判断下一个最高优先级的中断,并重复上述处理过程。

8259A 的中断优先级

固定优先级方式

在固定优先级方式中,IR7~IR0 的中断优先级是由系统确定的。优先级由高到低的顺序是:IR0, IR1, IR2, …, IR7。其中,IR0的优先级最高,IR7的优先级最低。

自动循环优先级方式

在自动循环优先权方式中,IR7~IR0的优先级别是可以改变的,而且是自动改变。其变化规律是:当某一个中断请求IRi服务结束后,该中断的优先级自动降为最低,而紧跟其后的中断请求IR(i+1)的优先级自动升为最高。

例如,在初始状态IR4有请求,CPU为其服务完毕,IR4的优先级自动降为最低,而其后的IR5的优先级升为最高。看一张图,我们会更清楚:
这里写图片描述

开始的时候,优先级从高到低是IR0, IR1, IR2, …, IR7。某时刻,IR4正在被CPU处理。处理完成后,IR4的优先级变为最低,IR5的优先级变为最高,也就是说,新的优先级序列从高到低是IR5,IR6,IR7,IR0,IR1,IR2,IR3,IR4.

在自动循环优先级方式中,又分为 普通自动循环方式特殊自动循环方式 两种。

  1. 普通自动循环:IR0~IR7中的初始最低优先级由系统指定,即指定IR7的优先级最低。
  2. 特殊自动循环:IR0~IR7中的初始最低优先级由用户指定(通过OCW2)。

中断嵌套方式

8259A的中断嵌套方式分为普通嵌套(normal nested mode)和特殊完全嵌套(The Special Fully Nest Mode)两种。

普通嵌套方式

也叫做完全嵌套或者普通完全嵌套。此方式是8259A在初始化时默认选择的方式。其特点是:IR0优先级最高,IR7优先级最低。在CPU中断服务期间,若有新的中断请求到来,只允许比当前服务的优先级更的中断请求进入,对于“同级”或“低级”的中断请求则禁止响应。

特殊完全嵌套方式

其特点是:IR7~IR0 的优先级顺序与普通嵌套方式相同;不同之处是在CPU中断服务期间,除了允许高级别中断请求进入外,还允许同级中断请求进入,从而实现了对同级中断请求的特殊嵌套。

在多片8259A级联的情况下,主片通常设置为特殊完全嵌套方式,从片设置为普通嵌套方式。当主片响应某一个从片的中断请求时,从片中的 IR7~IR0 的请求都是通过主片中的某个IRi请求引入的。因此从片的 IR7~IR0 对于主片IRi来说,它们属于同级,只有主片工作于特殊完全嵌套方式时,从片才能实现完全嵌套。

这里写图片描述

我的理解是这样的:比如从片的INT连接到主片的IR2,假设此时CPU正在响应从片IR4的中断请求,在中断处理过程中,从片IR3的中断到来,于是主片IR2再次请求中断,理论上从片IR3的优先级高于IR4,也就是说CPU应该暂停从片IR4的中断处理过程,转而处理从片IR3的中断。但是从片的IR0~IR7都是通过主片的IR2引入的,因为CPU正在服务于主片的IR2,这时IR2再次请求中断,对于普通嵌套方式,CPU是不响应的,因为属于同一级,都是IR2.

如果想要从片的IR3中断嵌套进从片的IR4中断,就需要CPU允许同级中断,所以要把主片设置为特殊完全嵌套方式。这样,从片的高优先级才能“真正”嵌套进从片的低优先级。

书上的解释是:在特殊完全嵌套方式下,当从片发出的某个中断请求正被服务时,该从片并不会被主片的优先级排除。因此该从片发出的其他更高优先级中断请求将被主片识别,主片会立刻向CPU发出中断。而在上述普通嵌套方式中, 当一个从片中断请求正在被服务时,该从片会被主片屏蔽。因此该从片发出的更高优先级的中断请求就不能被处理。

中断屏蔽方式

中断屏蔽方式是对8259A的外部中断源 IR7~IR0 实现屏蔽的一种中断管理方式,有普通屏蔽方式和特殊屏蔽方式两种。

普通屏蔽方式

写入操作命令字 OCW1,将中断屏蔽寄存器(IMR)中的Di位置1,以达到对IRii=0~7)中断请求的屏蔽。

这里写图片描述

Mi=1,则屏蔽对应中断请求级IRi;若 Mi=0,则允许IRi. 另外,屏蔽高优先级并不会影响其他低优先级的中断请求。

特殊屏蔽方式

8259A工作在特殊屏蔽方式时,所有未被屏蔽的优先级中断请求(较高的和较低的)均可在某个中断过程中被响应,即低优先级别的中断可以打断正在服务的高优先级中断。

在特殊屏蔽方式中,可在中断服务子程序中用中断屏蔽命令屏蔽当前正在处理的中断级,同时可使其在ISR中的对应位清零,这样一来不仅屏蔽了当前正在处理的中断级,而且也真正开放了较低级别的中断请求。在这种情况下,虽然CPU仍然继续执行较高级别的中断服务子程序,但由于ISR中对应位已经清零,就如同没有响应该中断一样。所以,此时对于较低级别的中断请求,CPU可以响应。

中断结束方式

中断结束方式是指CPU为某个中断请求服务结束后,应及时清除中断服务标志位,否则就意味着中断服务还在继续,致使比它优先级低的中断请求无法得到响应。中断服务标志位存放在中断服务寄存器(ISR)中,当某个中断源IRi被响应后,ISR中的Di位被置1,服务完毕应及时清除。8259A提供了三种中断结束方式。

自动结束方式

当 ICW4 中的自动中断结束 (AEOI) 比特位置位时,通过CPU发出的第二个中断响应信号INTA脉冲的后沿,将ISR中的中断服务标志位清除。这种中断服务结束方式是由硬件自动完成的。

需要注意的是:ISR中为“1”位的清除是在中断响应过程中完成的,并非中断服务子程序的真正结束,因8259A并没有保存任何标志来表示当前服务尚未结束,此时,若有中断请求出现,且IF(x86的EFLAGS寄存器b9,中断允许位)=1,则无论其优先级如何(比本级高、低或相同),都将得到响应,尤其是当某一中断请求信号被CPU响应后,如不及时撤销,就会再次被响应(二次中断)。这样可能会打乱正在服务的程序。因此这种方式只适用在中断请求信号的持续时间有一定限制,且没有中断嵌套的场合。

普通结束方式

普通结束方式是通过在中断服务子程序中编程写入操作命令字OCW2,向8259A传送一个普通中断结束(EOI,end of interrupt)命令(命令中不指定要复位的中断级)来清除ISR中优先级别最高的置位。

由于这种结束方式是清除ISR中优先权级别最高的那个置位,适合使用在完全嵌套方式下。因为在完全嵌套方式下,中断优先级是固定的,8259A总是响应优先级最高的中断,保存在ISR中的最高优先级的对应位,一定对应于正在执行的服务程序。

特殊结束方式

特殊结束方式是通过在中断服务子程序中编程写入操作命令字OCW2,向8259A传送一个特殊EOI命令(命令中指定出要复位的中断级)来清除ISR中的指定位。

在某些情况下,中断请求的响应顺序并不遵从固定的优先级。比如8259A工作在特殊屏蔽方式时,低优先级中断可以打断正在服务的高优先级中断,高优先级中断也可以打断正在服务的低优先级中断,此时,根据ISR的内容无法确定出刚刚所处理的中断。这就需要在EOI命令中指定出要复位的中断级。

中断触发方式

8259A中断请求输入端 IR7~IR0 的触发方式有电平触发和边沿触发两种,由初始化命令字ICW1中的LTIM位来设定。

电平触发方式

当 LTIM=1 时,为电平触发方式。当8259A检测到 IRii=0~7)端有高电平时产生中断。在这种触发方式中,要求触发电平必须保持到中断响应信号INTA有效为止。在CPU响应中断后,应及时撤销该请求信号,以防止CPU再次响应,出现重复中断现象。

边沿触发方式

当 LTIM=0 时,为边沿触发方式。当8259A检测到IRi端有由低到高的跳变(上升沿)信号时产生中断。

数据总线连接方式

8259A的数据线与系统数据总线的连接有缓冲和非缓冲两种方式。

这里写图片描述

缓冲方式

如果8259A通过总线驱动器和系统数据总线连接,则应选择缓冲方式。此时 EN 为输出引脚。在8259A输出中断类型号的时候,EN 输出一个低电平,用此信号作为总线驱动器的启动信号。

在缓冲方式下,由ICW4的M/S位来标识本8259A是主片还是从片。

这里写图片描述

非缓冲方式

如果8259A的数据线与系统数据总线直接相连,那么应选择非缓冲方式。此时SP为输入引脚,用其电平高低来标识本8259A是主片(SP=1)还是从片(SP=0)。

在非缓冲方式下,ICW4的BUF=0,M/S位无意义。

这里写图片描述

8259A的编程

初始化命令字

在8259A可以正常工作之前,必须首先设置初始化命令字 ICW (Initialization Command Words)寄存器组的内容。而在其工作过程中,则可以使用写入操作命令字 OCW (Operation Command Words)寄存器组来随时设置和管理8259A的工作方式。

A0线用于选择操作的寄存器。在PC/AT微机系统中,当A0=0时芯片的端口地址是0x20(主芯片)和0xA0(从芯片);当 A0=1时端口就是0x21(主芯片)和0xA1(从芯片)。

初始化命令字的编程操作流程如下图所示。由图可以看出,对 ICW1和 ICW2 的设置是必需的。而只有当系统中包含多片 8259A 芯片并且是级联的情况下才需要对 ICW3 进行设置。这需要在 ICW1 的设置中明确指出。 另外,是否需要对 ICW4 进行设置也需要在 ICW1 中指明。

这里写图片描述

ICW1

当发送的字节第 5 比特位(D4)=1,并且地址线 A0=0 时,表示是对 ICW1 编程。此时对于 PC/AT 微机系统的多片级联情况下,8259A 主芯片的端口地址是 0x20,从芯片的端口地址是 0xA0。

ICWl 的格如下:

这里写图片描述

再来一张比较简洁的图。

这里写图片描述

在 Linux-0.11 内核中,ICW1 被设置为 0x11。表示中断请求是边沿触发、多片 8259A 级联并且需要发送 ICW4。

ICW2

ICW2 用于设置芯片送出的中断号的高5位。在设置了 ICW1 之后,当 A0=1 时表示对 ICW2 进行设置。此时对于PC/AT微机系统的多片级联情况下,8259A主芯片的端口地址是0x21,从芯片的端口地址是0xA1。

ICW2 格式如下。

这里写图片描述

在使用 8086/88 处理器的系统或兼容系统中 T7~T3 是中断号的高5位,与 8259A 芯片自动设置的低3位(8259A 按 IR0~IR7 三位编码值自动填入)组成一个8位的中断号。8259A在收到第2个中断响应脉冲INTA时会把此中断号送到数据总线上,以供 CPU 读取。

一张图总结:

这里写图片描述

Linux-0.11 系统把主片的 ICW2 设置为 0x20,表示主片中断请求0~7级对应的中断号是 0x20~0x27;把从片的 ICW2 设置成 0x28,表示从片中断请求8~15级对应的中断号是 0x28~0x2f

ICW3

这里写图片描述

主芯片的端口地址是0x21,从芯片的端口地址是0xA1。

对于主片,Si=1,表示IRi接从片的INT引脚。说得啰嗦点,就是主片 S7~S0 各比特位对应级联的从片。哪位为1则表示主片的该中断请求引脚IR上信号来自从片, 否则对应的IR引脚没有连从片。

对于从片,ID2~ID0 三个比特位对应各从片的标识号,即连接到主片的中断级。当某个从片接收到级联线(CAS2—CAS0)输入的值与自己的 ID2~ID0 相等时,表示此从片被选中。此时该从片应该向数据总线发送自己当前被选中的中断请求的中断号。

Linux-0.11 内核把8259A主片的 ICW3 设置为 0x04,即 S2=1,其余各位为0。表示主芯片的 IR2 引脚连接一个从芯片。从芯片的 ICW3 被设置为 0x02,即其标识号为2。表示此从片连接到主片的IR2引脚。 因此,中断优先级的排列次序为:0级最高,1级次之,接下来是从片上的 8~15 级,最后是主片的 3~7 级。

ICW4

当 ICW1 的位0 (IC4)置位时,表示需要 ICW4。地址线 A0=1,主芯片的端口地址是0x21,从芯片的端口地址是0xA1。

这里写图片描述

再来一张简洁的图:

这里写图片描述

Linux-0.11内核送往8259A主芯片和从芯片的 ICW4 命令字的值均为 0x01。表示 8259A 芯片被设置成普通全嵌套、非缓冲、非自动结束中断方式,并且用于 8086 及其兼容系统。

操作命令字

在对 8259A 设置了初始化命令字后,芯片就已准备好接收设备的中断请求信号了。但在 8259A 工作期间,我们也可以利用操作命令字 OCW1~OCW3 来监测 8259A 的工作状况,或者随时改变初始化时设定的 8259A 的工作方式。

需要说明的是,与初始化命令字ICW1~ICW4需要按规定的顺序进行设置不同,操作命令字OCW1~OCW3的设置没有规定其先后顺序,使用时可根据需要灵活选择不同的操作命令字写入到8259A中。

OCW1

OCW1 用于对 8259A 中中断屏蔽寄存器 IMR 进行读/写操作。地址线A0需为1。

这里写图片描述

Mi=1,则屏蔽对应中断请求级IRi;若 Mi=0,则允许IRi. 另外,屏蔽高优先级并不会影响其他低优先级的中断请求。

在 Linux-0.11 内核初始化过程中,代码在设置好相关的设备驱动程序后就会利用该操作命令字来修改相关中断请求屏蔽位。例如在软盘驱动程序初始化结束时,为了允许软驱设备发出中断请求,就会读端口0x21以取得 8259A 芯片的当前屏蔽字,然后与上~0x40 来复位M6(软盘控制器连接到了中断请求IR6上),最后再写回中断屏蔽寄存器中。

OCW2

这里写图片描述

名称 含义
7 R 中断优先级是否按循环方式设置。R=1表示采用循环方式,R=0表示采用非循环方式。
6 SL OCW2中的L2~L0是否有效。SL=1表示有效,SL=0表示无效。
5 EOI 中断结束命令位。EOI=1使当前ISR寄存器的相应位清0。当ICW4中的AEOI为0时,ISR中的相应置位就要由该命令位来清除。
4-3 必须为00,00是OCW2的标识位。
2-0 L2-L0 在SL=1时配合R、SL、EOI的设置,用来确定一个中断优先级的编码。L2、L1、L0 的8种编码000~111分别与IR0~IR7相对应。


OCW2 Commands
R SL EOI 优先级管理方式 中断结束方式
0 0 1 固定优先级 一般EOI
0 1 1 固定优先级 特殊EOI ,ISR(L2~L0)复位。
1 0 1 自动循环 一般EOI
1 0 0 设置自动循环方式(在AEOI模式下)
0 0 0 清除自动循环方式(在AEOI模式下)
1 1 0 设置优先级命令
1 1 1 特殊循环,置IR(L2~L0)优先级为最低 特殊EOI ,ISR(L2~L0)复位。
0 1 0

Linux-0.11 内核仅使用该操作命令字在中断处理过程结束之前向 8259A 发送结束中断(EOI)命令。所使用的OCW2 值为 0x20,表示固定优先级、一般EOI(对应上表的第一行)。

OCW3

OCW3用于设置或清除特殊屏蔽方式和读取寄存器状态(IRR 和 ISR)。当 D4D3=01,且地址线 A0=0 时,表示对OCW3进行编程。在Linux-0.11 内核中并没有用到该操作命令字。

这里写图片描述

名称 含义
D7 恒为0
D6 ESMM SMM使能位。 ESMM=0,SMM的值不起用;ESMM=1,由SMM位决定是否工作在特殊屏蔽方式。
D5 SMM ESMM=1,SMM=0时,复位特殊屏蔽(表示8259A不是工作在特殊屏蔽方式);ESMM=SMM=1,设置特殊屏蔽。
D4-D3 恒为01,是OCW3的特征位
D2 P 查询命令(Poll Command)标识位。P=1,查询;P=0,不查询。
D1-D0 RR,RIS RR(read register command)=1,表示读ISR或IRR。RR=1,RIS=0时,读取IRR;RR=1,RIS=1时,读取ISR。

英文熟练的可以看这张图。

这里写图片描述

例如,设8259A的两个端口地址为20H和21H,OCW3、ISR和IRR共用一个地址20H。

MOV AL, 0000_1011B  ; 设置好“读ISR命令”
OUT 20H, AL     ; 写入OCW3
IN AL, 20H       ; 读ISR内容至AL中
POLL Mode

当INT输出引脚不使用或者CPU内部中断允许标志为0时,外部设备无法向CPU传递有效的中断请求信号。在这种情况下,可以采用查询模式。还有,当系统的中断源很多,超过了64个,也可以使用查询方式。

在使OCW3的P位置为1后的下一个读命令,8259A看作是CPU的中断响应信号,8259A把IRR相应位清0,ISR对应位置1,并把查询字送到数据总线。读命令从数据总线上读取查询字,其格式为:

这里写图片描述
D7位I =0:表示没有中断。

D7位I =1:表示此片8259A有中断请求,W2~W0即为最高优先级中断源的编码。

命令字端口地址速查表

对于每个命令字的端口,我列了一张速查表。

命令字 A0 主片端口地址 从片端口地址 备注
ICW1 0 0x20 0xA0 D4 = 1
ICW2 1 0x21 0xA1
ICW3 1 0x21 0xA1
ICW4 1 0x21 0xA1
OCW1 1 0x21 0xA1
OCW2 0 0x20 0xA0 D4:D3 = 00
OCW3 0 0x20 0xA0 D4:D3 = 01

–【全文完】–


参考资料

[1] /article/

[2] /jimp/310/slides/8086_interrupts.html

[3] /book/09-06/

[4] /u013007900/article/details/50194401

[5] /2014/09/