一、8259a工作初始化的步驟
首先,外部中斷請求(IR0到IR7)傳輸?shù)絀MR,IMR根據(jù)此中斷請求是否被屏蔽,以決定是將其丟棄,還是放入IRR中等待進一步處理。當8259A等待到一個中斷時機時,優(yōu)先級仲裁單元會從所有放入IRR中的中斷請求中挑出一個優(yōu)先級最高的中斷,傳遞給CPU處理。值得注意的是中斷優(yōu)先級是隨著中斷請求號降低而提高的。在CPU的INTR引腳接收到8259A發(fā)送過來的信號后,CPU會暫停執(zhí)行下一條指令,并向8259A發(fā)送一個INTA信號。在 8259A接收到該信號后,就會將ISR中代表該中斷的位置1,并將IRR中相應的位清零。以表示該中斷正在被CPU處理。接著CPU會向8259A再發(fā)送一個INTA信號,向其請求中斷向量號。這時,8259A會根據(jù)先前設置好的起始向量號再加上中斷請求號計算出中斷向量號,并將其放入數(shù)據(jù)總線中。
這時候,如果8259A的EOI通知被設定為自動模式,那么8259A就會自動將ISR中剛才置1的位清零。在CPU獲得該中斷向量號后,就會轉(zhuǎn)去調(diào)用該中斷服務程序。在處理完該中斷后如果8259A的EOI通知被設定為人工模式,則還要向8259A發(fā)送一個EOI。通常來講,這一工作往往是在中斷服務程序中完成。在8259A接收到該EOI通知后,就會將ISR中剛才置1的位清零。
以上就是8259A處理一個中斷的整個過程的簡述。由于中斷請求存在著優(yōu)先級,因此,如果在一個中斷處理期間,8259A又收到了新的中斷請求,則首先跟當前處理的優(yōu)先級進行比較,如果新到的中斷請求的優(yōu)先級高于當前處理的中斷請求,則馬上處理新到的中斷請求,否則則將新到的中斷請求放入IRR。
對于8259A的操作,是通過端口進行的。其中, Master的端口地址為0x20, 0x21, Slave的端口地址位0xA0,0xA1。8259A具有兩種命令,一種是ICW,其作用是用來初始化8259A芯片。另一個是OCW,其作用是用來向 8259A發(fā)送命令。雖然在系統(tǒng)啟動后BIOS會自動初始化8259A,但這并不是我們所需要的。因為在進入保護模式后,我們要設置IDT,因此我們必須根據(jù)所設置的IDT去初始化8259A.
對8259A的操作有兩類命令,其中一類是ICW,另一類是OCW。ICW用來對8259A進行初始化,而OCW則用來在初始化后對8259A發(fā)布命令。有意思的是,8259A的兩個端口對于這兩類命令的發(fā)布是有固定安排的。對于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的倍數(shù)。
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,其原因在于我們要允許中斷請求的按優(yōu)先級搶占。如果我們將EOI通知設定為自動模式,那么在CPU發(fā)出第二個 INTA信號后,8259A中相應的ISR就會自動清零,而此時該中斷服務程序還沒有被調(diào)用。如果在該中斷服務程序被調(diào)用的過程中,8259A收到了優(yōu)先級比當前正在處理的中斷優(yōu)先級低的中斷請求,由于正在處理的中斷在ISR中相應的位已經(jīng)清零,因此這個新的中斷請求就完全可以搶占正在處理的優(yōu)先級比它高的中斷服務程序。
二、初始化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發(fā)送一個操作控制字。需要屏蔽哪個中斷請求就將該字上相應的位置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 &= ?。? 《《 IRQ);
outportb(PORT_INT_MASK_M, mask);
}
else
{
mask = inportb(PORT_INT_MASK_S);
mask &= ?。? 《《 (IRQ-8));
outportb(PORT_INT_MASK_S, mask);
}
}
OCW2:
如果OCW2中的bit6被設置為0,那么該命令將對整個8259A有效。否則,將針對bit2:0這3位所代表的IRQ進行操作。由于我們前面已經(jīng)將8259A設置為手動EOI模式,所以在這里我們要將bit7:5設置為(001)
OCW3:
四、8259A初始化編程
對8259的初始化一定要按規(guī)定的順序進行,假定8259占用的I/O地址為FF00和FF02H(奇地址):
MOV DX,0FF00H ;8259的地址A0=0
MOV AL,13H ;寫ICW1,邊沿觸發(fā),單片,
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文章
900瀏覽量
41578 -
初始化
+關注
關注
0文章
50瀏覽量
11910 -
8259A
+關注
關注
0文章
6瀏覽量
8283
發(fā)布評論請先 登錄
相關推薦
評論