一、8259a工作初始化的步骤
首先,外部中断请求(IR0到IR7)传输到IMR,IMR根据此中断请求是否被屏蔽,以决定是将其丢弃,还是放入IRR中等待进一步处理。当8259A等待到一个中断时机时,优先级仲裁单元会从所有放入IRR中的中断请求中挑出一个优先级最高的中断,传递给CPU处理。值得注意的是中断优先级是随着中断请求号降低而提高的。在CPU的INTR引脚接收到8259A发送过来的信号后,CPU会暂停执行下一条指令,并向8259A发送一个INTA信号。在 8259A接收到该信号后,就会将ISR中代表该中断的位置1,并将IRR中相应的位清零。以表示该中断正在被CPU处理。接着CPU会向8259A再发送一个INTA信号,向其请求中断向量号。这时,8259A会根据先前设置好的起始向量号再加上中断请求号计算出中断向量号,并将其放入数据总线中。
这时候,如果8259A的EOI通知被设定为自动模式,那么8259A就会自动将ISR中刚才置1的位清零。在CPU获得该中断向量号后,就会转去调用该中断服务程序。在处理完该中断后如果8259A的EOI通知被设定为人工模式,则还要向8259A发送一个EOI。通常来讲,这一工作往往是在中断服务程序中完成。在8259A接收到该EOI通知后,就会将ISR中刚才置1的位清零。
以上就是8259A处理一个中断的整个过程的简述。由于中断请求存在着优先级,因此,如果在一个中断处理期间,8259A又收到了新的中断请求,则首先跟当前处理的优先级进行比较,如果新到的中断请求的优先级高于当前处理的中断请求,则马上处理新到的中断请求,否则则将新到的中断请求放入IRR。
对于8259A的操作,是通过端口进行的。其中, Master的端口地址为0x20, 0x21, Slave的端口地址位0xA0,0xA1。8259A具有两种命令,一种是ICW,其作用是用来初始化8259A芯片。另一个是OCW,其作用是用来向 8259A发送命令。虽然在系统启动后BIOS会自动初始化8259A,但这并不是我们所需要的。因为在进入保护模式后,我们要设置IDT,因此我们必须根据所设置的IDT去初始化8259A.
对8259A的操作有两类命令,其中一类是ICW,另一类是OCW。ICW用来对8259A进行初始化,而OCW则用来在初始化后对8259A发布命令。有意思的是,8259A的两个端口对于这两类命令的发布是有固定安排的。对于0x20和0xA0端口,你可以向它们写入ICW1,OCW2,OCW3,读取IRR和ISR。对于0x21和0xA1端口,你可以向它们写入ICW2,ICW3,ICW4, 并能够读写IMR寄存器。
下面我们分别来讨论这几个命令
ICW1:该命令作为初始化序列的第一条命令,一旦向端口送入该命令,8259A就认为初始化序列开始。
在设置时,对于80x86的CPU,其应设置为(00010001),也就是0x11。
ICW2:该命令用来指定所初始化的8259A中断请求的起始向量。其中ICW2的低3位必须为0,其这么做的原因在于当该8259A接收到一个中断请求时,低3位会自动填充为所接受到的向量号。因此这也就决定了我们设置的起始中断向量,必须为8的倍数。
ICW3:Master PIC和Slave PIC对于ICW3命令具有不同的格式
对于Master PIC,Slave PIC被接到了Master PIC的哪个IRQ上,则ICW3中相应的位就置1。在8259A中,由于SlavePIC是级连在Master PIC的IRQ2上的,因此ICW3的值应该为(00000100),也就是0x04。而对于SlavePIC其高5位必须设置为零,低3位为该PIC被级连到哪个Master PIC的IRQ号,在8259A中,其SlavePIC的值为(00000010),即0x02。
ICW4:
在80x86模式下,我们采用默认的Full Nested Mode,将ICW4设置为(000000001),即0x01。
而我们之所以我们要采用NormalEOI,其原因在于我们要允许中断请求的按优先级抢占。如果我们将EOI通知设定为自动模式,那么在CPU发出第二个 INTA信号后,8259A中相应的ISR就会自动清零,而此时该中断服务程序还没有被调用。如果在该中断服务程序被调用的过程中,8259A收到了优先级比当前正在处理的中断优先级低的中断请求,由于正在处理的中断在ISR中相应的位已经清零,因此这个新的中断请求就完全可以抢占正在处理的优先级比它高的中断服务程序。
二、初始化8259A的代码
void init_8259A(byte master_vector,byte slave_vector)
{
outportb (PORT_8259A_M, 0x11);
outportb (PORT_8259A_S, 0x11);
outportb (PORT_8259A_M+1, master_vector);
outportb (PORT_8259A_S+1, slave_vector);
outportb (PORT_8259A_M+1, 1《《2);
outportb (PORT_8259A_S+1, 2);
outportb (PORT_8259A_M+1, 1);
outportb (PORT_8259A_S+1, 1);
}
三、如何通过OCW对8259A进行操作
OCW1:该命令用来屏蔽所设定的中断请求。其操作方式是,向你要屏蔽的中断请求所在的8259A发送一个操作控制字。需要屏蔽哪个中断请求就将该字上相应的位置1即可。
实例代码如下:
#define PORT_INT_MASK_M 0x21
#definePORT_INT_MASK_S 0xA1
void mask_IRQ(byte IRQ)
{
byte mask;
if(IRQ 》 15)
return;
if(IRQ 《 8)
{
mask = inportb(PORT_INT_MASK_M);
mask |= 1 《《 IRQ;
outportb(PORT_INT_MASK_M, mask);
}
else
{
mask = inportb(PORT_INT_MASK_S);
mask |= 1 《《 (IRQ-8);
outportb(PORT_INT_MASK_S, mask);
}
}
void unmask_IRQ(byte IRQ)
{
byte mask;
if(IRQ 》 15)
return;
if(IRQ 《 8)
{
mask = inportb(PORT_INT_MASK_M);
mask &= !(1 《《 IRQ);
outportb(PORT_INT_MASK_M, mask);
}
else
{
mask = inportb(PORT_INT_MASK_S);
mask &= !(1 《《 (IRQ-8));
outportb(PORT_INT_MASK_S, mask);
}
}
OCW2:
如果OCW2中的bit6被设置为0,那么该命令将对整个8259A有效。否则,将针对bit2:0这3位所代表的IRQ进行操作。由于我们前面已经将8259A设置为手动EOI模式,所以在这里我们要将bit7:5设置为(001)
OCW3:
四、8259A初始化编程
对8259的初始化一定要按规定的顺序进行,假定8259占用的I/O地址为FF00和FF02H(奇地址):
MOV DX,0FF00H ;8259的地址A0=0
MOV AL,13H ;写ICW1,边沿触发,单片,
OUT DX,AL
MOV DX,0FF02H ;8259地址A0=1
MOV AL,48H ;写ICW2,设置中断类型码
OUT DX,AL ;中断向量为48H-4FH(IR0-IR7)单片8259,不对ICW3设置
MOV AL,03H ;写ICW4,8086/88模式,自动中;断结束 (EOI),非缓冲,一般嵌套
OUT DX,AL
MOV AL,0E0H ;写OCW1,屏蔽IR5、IR6、 IR7中断源
OUT DX,AL ;(假定这3个中断输入未用),其它开中断
-
中断
+关注
关注
5文章
898浏览量
41470 -
初始化
+关注
关注
0文章
50浏览量
11850 -
8259A
+关注
关注
0文章
6浏览量
8276
发布评论请先 登录
相关推荐
评论