複製鏈接
請複製以下鏈接發送給好友

8259A中斷控制器

鎖定
8259A芯片是一箇中斷管理芯片,中斷的來源除了來自於硬件自身的NMI中斷和來自於軟件的INT n指令造成的軟件中斷之外,還有來自於外部硬件設備的中斷,這些中斷是可屏蔽的。這些中斷也都通過可編程中斷控制器PIC(Programmable Interrupt Controller)進行控制,並傳遞給CPU
中文名
8259A中斷控制器
兼容性
PC/XT
工作原理
IMR
傳    遞
CPU

8259A中斷控制器總述

8259A中斷控制器前言

8259A芯片是一箇中斷管理芯片,通過8259A可以對單箇中斷源進行屏蔽。中斷的來源除了來自於硬件自身的NMI中斷和來自於軟件的INT n指令造成的軟件中斷之外,還有來自於外部硬件設備的中斷,這些中斷是可屏蔽的。這些中斷也都通過PIC(Programmable Interrupt Controller)進行控制,並傳遞給CPU
一個8259A芯片的可以接最多8個中斷源,但由於可以將2個或多個8259A芯片級連(cascade),並且最多可以級連到9個,所以最多可以接64箇中斷源。如今絕大多數的PC都擁有兩個8259A,這樣 最多可以接收15箇中斷源。

8259A中斷控制器寄存器 (Registers)

在一個8259A芯片有如下幾個內部寄存器
1. Interrupt Mask Register (IMR)
2. Interrupt Request Register (IRR)
3. In Service Register (ISR)
具體到每個寄存器的職責:
  1. IMR被用作過濾被屏蔽的中斷
  2. IRR被用作暫時放置未被進一步處理的Interrupt,
  3. 當一個Interrupt正在被CPU處理時,此中斷被放置在ISR中。

8259A中斷控制器Priority Resolver

除了這幾個寄存器之外,8259A還有一個單元叫做Priority Resolver,當多箇中斷同時發生時,Priority Resolver根據它們的優先級,將高優先級者優先傳遞給CPU。

8259A中斷控制器8259A工作原理

8259A工作原理 8259A工作原理
當一個中斷請求從IR0到IR7中的某根線到達IMR時,IMR首先判斷此IR是否被屏蔽,如果被屏蔽,則此中斷請求被丟棄;否則,則將其放入IRR中。
在此中斷請求不能進行下一步處理之前,它一直被放在IRR中。一旦發現處理中斷的時機已到,Priority Resolver將從所有被放置於IRR中的中斷中挑選出一個優先級最高的中斷,將其傳遞給CPU去處理。IR號越低的中斷優先級別越高,比如IR0的優先級別是最高的。
8259A通過發送一個INTR(Interrupt Request)信號給CPU,通知CPU有一箇中斷到達。CPU收到這個信號後,會暫停執行下一條指令,然後發送一個INTA(Interrupt Acknowledge)信號給8259A。8259A收到這個信號之後,馬上將ISR中對應此中斷請求的Bit設置,同時IRR中相應的bit會被reset。比如,如果當前的中斷請求是IR3的話,那麼ISR中的bit-3就會被設置,IRR中IR3對應的bit就會被reset。這表示此中斷請求正在被CPU處理,而不是正在等待CPU處理。
隨後,CPU會再次發送一個INTA信號給8259A,要求它告訴CPU此中斷請求的中斷向量是什麼,這是一個從0到255的一個數。8259A根據被設置的起始向量號(起始向量號通過中斷控制字ICW2被初始化)加上中斷請求號計算出中斷向量號,並將其放置在Data Bus上。比如被初始化的起始向量號為8,當前的中斷請求為IR3,則計算出的中斷向量為8+3=11。
CPU從Data Bus上得到這個中斷向量之後,就去IDT中找到相應的中斷服務程序ISR,並調用它。如果8259A的End of Interrupt (EOI)通知被設定位人工模式,那麼當ISR處理完該處理的事情之後,應該發送一個EOI給8259A。
8259A得到EOI通知之後,ISR寄存器中對應於此中斷請求的Bit會被Reset。
如果8259A的End of Interrupt (EOI)通知被設定位自動模式,那麼在第2個INTA信號收到後,8259A ISR寄存器中對應於此中斷請求的Bit就會被Reset。
在此期間,如果又有新的中斷請求到達,並被放置於IRR中,如果這些新的中斷請求中有比在ISR寄存中放置的所有中斷優先級別還高的話,那麼這些高優先級別的中斷請求將會被馬上按照上述過程進行處理;否則,這些中斷將會被放在IRR中,直到ISR中高優先級別的中斷被處理結束,也就是説知道ISR寄存器中高優先級別的bit被Reset為止。

8259A中斷控制器IRQ2/IRQ9 重定向

8259A中斷控制器兼容性

為什麼要將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的設備將無法再使用它;但新的系統又必須和原有系統保持兼容,怎麼辦?

8259A中斷控制器新增特性

由於新增加的Slave PIC在原有系統中不存在,所以,設計者從Slave PIC的IRQ中挑出IRQ9,要求軟件設計者將原來的IRQ2重定向到IRQ9上,也就是説IRQ9的中斷服務程序需要去掉用IRQ2的中斷服務程序。這樣,將原來接在IRQ2上的設備現在接在IRQ9上,在軟件上只需要增加IRQ9的中斷服務程序,由它調用IRQ2的中斷服務程序,就可以和原有系統保持兼容。而在當時,增加的IRQ9中斷服務程序是由PC開發商開發的BIOS提供的,不需要用户進行另外設置。所以就從根本上保證了兼容。

8259A中斷控制器8259A系列芯片的編程

每一個8259A芯片都有兩個I/O ports,程序員可以通過它們對8259A進行編程。
Master 8259A的端口地址是0x20,0x21;Slave 8259A的端口地址是0xA0,0xA1。

8259A中斷控制器8259As的口令

8259As的口令 8259As的口令
程序員可以向8259A寫兩種命令字:
Initialization Command Word (ICW);這種命令字被用作對8259A芯片的初始化。
Operation Command Word (OCW):這種命令被用來向8259A發佈命令,以對其進行控制。OCW可以在8259A被初始化之後的任何時候被使用。

8259A中斷控制器8259A主片

下表的內容是Master 8259A的I/O端口地址,以及通過它們所能操作的寄存器。
Address Read/Write Function
0x20 Write Initialization Command Word 1 (ICW1)
Write Operation Command Word 2 (OCW2)
Write Operation Command Word 3 (OCW3)
Read Interrupt Request Register (IRR)
Read In-Service Register (ISR)
0x21 Write Initialization Command Word 2 (ICW2)
Write Initialization Command Word 3 (ICW3)
Write Initialization Command Word 4 (ICW4)
Read/Write Interrupt Mask Register (IMR)
Addresses/Registers for Master 8259A

8259A中斷控制器8259A從片

下表的內容是Slave 8259A的I/O端口地址,以及通過它們所能操作的寄存器。
Address Read/Write Function
0xA0 Write Initialization Command Word 1 (ICW1)
Write Operation Command Word 2 (OCW2)
Write Operation Command Word 3 (OCW3)
Read Interrupt Request Register (IRR)
Read In-Service Register (ISR)
0xA1 Write Initialization Command Word 2 (ICW2)
Write Initialization Command Word 3 (ICW3)
Write Initialization Command Word 4 (ICW4)
Read/Write Interrupt Mask Register (IMR)
Addresses/Registers for Slave 8259A
由於8259A芯片不僅能夠用於IBM PC/X86,也可以被用作MCS-80/85,對於這兩者,在操作模式上有一些不一樣,對於某些寄存器的設置也有所不同。我們後面僅僅討論X86模式相關的內容。

8259A中斷控制器初始化

8259A中斷控制器初始化

主機上電或復位之後,必須對兩個8259A都進行初始化。事實上,BIOS已經這麼做了。但不幸的是,BIOS對其進行的初始化的結果並非我們所需要。比如,我們要開發保護模式下OS,我們要設置自己的IDT,那麼我們就不能使用BIOS設置的IVT,而在對8259A初始化操作中,我們需要告訴8259A,其相關中斷請求的起始向量號,而我們對IDT的中斷向量佈局和BIOS設置的IVT的中斷向量佈局可以是不一樣的。這樣,我們也需要對兩個8259A進行初始化。
任何時候,只要向某一個8259A的第一個端口(0x20 for Master,and 0xA0 for Slave)寫入的命令的bit-4(從0算起)為1,那麼這個8259A就認為這是一個ICW1;而一旦一個8259A收到一個ICW1,它就認為一個初始化序列開始了。你可以通過對照上邊的表和後面的表,第一端口可寫的有ICW1,OCW2和OCW3。而ICW1的bit-4要求必須是1,但OCW2和OCW3的bit-4要求必須是0。

8259A中斷控制器協議

8259A的初始化流程協議,程序員對其進行初始化時必須遵守此協議:
ICW1
Bit(s) Function
7:5 Interrupt Vector Addresses for MCS-80/85 Mode.
4 Must be set to 1 for ICW1
3 1 Level Triggered Interrupts
0 Edge Triggered Interrupts
2 1 Call Address Interval of 4
0 Call Address Interval of 8
1 (SINGL) 1 Single PIC
0 Cascaded PICs
0 (IC4) 1 Will be Sending ICW4
0 Don't need ICW4
Initialization Command Word 1 (ICW1)
對於X86,bit-0必須被設置為1;由於當今的IBM PC上都有兩個級連的8259A,所以bit-1應該被設置為0;由於bit-2是為MCS-80/85服務的,我們將其設置為0;bit-3也設置為0;bit-4被要求必須設置為1;bit5:7是為MCS-80/85服務的,對於X86,應將全部將其設為0。
所以,在X86系統上,ICW1應該被設置為二進制00010001 = 0x11。
ICW2
Bit 80x86 Mode
7 I7
6 I6
5 I5
4 I4
3 I3
2 0
1 0
0 0
Initialization Command Word 2 (ICW2)
ICW2被用作指定本8259A中的中斷請求的起始中斷向量,bit0:3必須被設為0;所以,其起始中斷向量必須是8的倍數。比如,我們的OS的設計講來自於Master 8259A的8箇中斷請求放在IDT的第32 (從0開始計)個位置到第39個位置,則我們應該將ICW2設為0x20。
這樣,當將來此8259A上接收到一個IRQ時,其低3位會被自動填充為IRQ號。比如,其收到一個IRQ6,將6自動填充到後3位,則生成的向量號為0x26。8259A會在收到CPU發來的第二個INTA信號之後,將生成的向量號放到Data Bus上。
ICW3
Master 8259A和Slave 8259A有不同的ICW3格式。
Bit Function
7 IR7 is connected to a Slave
6 IR6 is connected to a Slave
5 IR5 is connected to a Slave
4 IR4 is connected to a Slave
3 IR3 is connected to a Slave
2 IR2 is connected to a Slave
1 IR1 is connected to a Slave
0 IR0 is connected to a Slave
Initialization Command Word 3 for Master 8259A (ICW3)
Slave 8259A被接在Master 8259A的那個IRQ上,則相應的位就被設置為1,其餘的位都被設置為0。在IBM PC上,Slave 8259A被接在Master 8259A的IRQ2上,則此ICW3的值應該被設置為二進制00000100 = 0x04。
Bit(s) Function
7 Reserved. Set to 0
6 Reserved. Set to 0
5 Reserved. Set to 0
4 Reserved. Set to 0
3 Reserved. Set to 0
2:0 Slave ID
000 Slave 0
001 Slave 1
010 Slave 2
011 Slave 3
100 Slave 4
101 Slave 5
110 Slave 6
111 Slave 7
Initialization Command Word 3 for Slaves (ICW3)
Slave 8259A的ICW3的bit3:7被保留,必須被設為0;而bit0:2被設置為此Slave 8259A被接在Master 8259A的哪個IRQ上。比如,在IBM PC上,Slave 8259A被接在Master 8259A的IRQ2上,則此ICW3應被設為0x02。
ICW4
Bit(s) Function
7 Reserved. Set to 0
6 Reserved. Set to 0
5 Reserved. Set to 0
4 1 Special Fully Nested Mode
0 Not Special Fully Nested Mode
3:2 0x Non - Buffered Mode
10 Buffered Mode - Slave
11 Buffered Mode - Master
1 1 Auto EOI
0 Normal EOI
0 1 8086/8080 Mode
0 MCS-80/85
Initialization Command Word 4 (ICW4)
在80x86模式下,我們不需要使用8259A的特殊功能,因此我們將bit1:4都設為0,這意味使用默認的Full Nested Mode,不使用Buffer,以及手動EOI模式;我們只需要將bit-0設為1,這也正是我們ICW0處提到的我們為什麼必須要ICW4的原因。所以ICW4的值應該被設為0x01。
所以我們可以用下列代碼初始化2個8259A芯片:
inline void init_8259a(void)
{
/* icw1 */
outb( 0x20,0x11 ); /* master port A */
outb( 0xA0,0x11 ); /* slave port A */
/* icw2 */
outb( 0x21,0x20 ); /* master offset of 0x20 in the IDT */
outb( 0xA1,0x28 ); /* slave offset of 0x28 in the IDT */
/* icw3 */
outb( 0x21,0x04 ); /* slaves attached to IR line 2 */
outb( 0xA1,0x02 ); /* this slave in IR line 2 of master */
/* icw4 */
outb( 0x21,0x01 ); /* set as master */
outb( 0xA1,0x01 ); /*set as slave */
}

8259A中斷控制器操作

8259A中斷控制器操作

一旦按照初始化協議初始化完成之後,程序員就可以在任何時候,以任何順序向8259A發送操作控制字OCW了。
OCW1
Bit PIC 2 PIC 1
7 Mask IRQ15 Mask IRQ7
6 Mask IRQ14 Mask IRQ6
5 Mask IRQ13 Mask IRQ5
4 Mask IRQ12 Mask IRQ4
3 Mask IRQ11 Mask IRQ3
2 Mask IRQ10 Mask IRQ2
1 Mask IRQ9 Mask IRQ1
0 Mask IRQ8 Mask IRQ0
Operation Control Word 1 (OCW1)
OCW1是用來做中斷請求屏蔽用的操作控制字。如果你想屏蔽那個IRQ,只需要對照上表將相應的Bit置為1,然後發送給相應的8259A就可以了。比如我想屏蔽IRQ10,我只需要將0x0A寫到端口0xA1。對應代碼如下:
outb(0x0A,0xA1);
OCW2
Bit(s) Function
7:5 000 Rotate in Auto EOI Mode (Clear)
001 Non Specific EOI
010 Reserved
011 Specific EOI
100 Rotate in Auto EOI Mode (Set)
101 Rotate on Non-Specific EOI
110 Set Priority Command (Use Bits 2:0)
111 Rotate on Specific EOI (Use Bits 2:0)
4 Must be set to 0
3 Must be set to 0
2:0 000 Act on IRQ 0 or 8
001 Act on IRQ 1 or 9
010 Act on IRQ 2 or 10
011 Act on IRQ 3 or 11
100 Act on IRQ 4 or 12
101 Act on IRQ 5 or 13
110 Act on IRQ 6 or 14
111 Act on IRQ 7 or 15
Operation Control Word 2 (OCW2)
通過將bit3:4設置為0,以説明這是一個OCW2。如果bit-6被設為1,則bit0:2有效,其操作則是面向某個IRQ的;否則將bit0:2設為0,其操作是面向整個8259A的所有IRQ的。我們一般只會用到No Specific EOI——因為我們在初始化8259A時,制定的EOI Mode為手動模式,所以當每次對應某個8259A芯片的IRQ的中斷服務程序ISR執行結束後,都需要向8259A發送一個EOI,其對應的OCW2的值為0x20。需要注意的是,由於IBM PC有2個級連的8259A,所以我們每次必須分別給兩個都發一個。
比如下面示例代碼用來向兩個8259A芯片發送EOI,它需要在針對來自於兩個8259A芯片的中斷的服務程序ISR末尾處被調用:
inline void send_eoi(void)
/* Send EOI to both master and slave */
outb( 0x20,0x20 ); /* master PIC */
outb( 0xA0,0x20 ); /* slave PIC */
OCW3
Bit(s) Function
7 Must be set to 0
6:5 00 Reserved
01 Reserved
10 Reset Special Mask
11 Set Special Mask
4 Must be set to 0
3 Must be set to 1
2 1 Poll Command
0 No Poll Command
1:0 00 Reserved
01 Reserved
10 Next Read Returns Interrupt Request Register
11 Next Read Returns In-Service Register
Operation Control Word 3 (OCW3)
通過將Bit-3設為1,Bit-4設為0,以讓8259A知道這是一個OCW3。OCW3中對我們最有意義的位是bit0:1,我們可以通過將bit-1設為1來通知8259A,下一個讀端口的動作將要讀取IRR或ISR寄存器的內容。
比如下面示例C++代碼用來讀取Master 8259A的IRR寄存器內容到__irr變量中:
void read_irr(unsigned char& __irr)
{
outb(0x02,0x20);
inb(&__irr,0x20);
}

8259A中斷控制器Full Nested Mode

為了讓我們更加理解8259A的中斷控制機理,我們需要説明一下Full Nested Mode。在我們初始化時,只需要將ICW4的bit-4設為0,我們就選擇了Full Nested Mode。
Full Nested Mode其實就是實現按照中斷請求的優先級別進行搶斷處理的機制——如果當前一個IRQ正在被CPU處理,也就是説,當前CPU正在調用其中斷服務程序ISR;這時8259A又接到了新的IRQ,如果此IRQ的優先級大於正在處理的IRQ,那麼,此IRQ就會被提交給CPU以優先處理;否則此IRQ則被放置在IRR中,直到所有的高優先級中斷被處理結束為止。

8259A中斷控制器處理過程

其處理過程大致如下:
在ISR寄存器中有一個8-bit的字節,範圍為bit[0,7];每一個bit對應一個IRQ(IRQ0-IRQ7對應bit[0,7])。當一個IRQ被提交給CPU之後(收到來自於CPU的第一個INTA信號之後),其對應的bit會被設置為1。比如IRQ6被提交給CPU之後,IS Register的bit-6會被設置為1。當此8259A收到一個EOI之後(對於手動模式,這意味着一個優先級別最高的中斷請求被處理結束),會將IS Register中被設置的最高優先級IRQ的對應的bit清為0。比如在收到一個EOI時,發現IS Register的bit-3,bit-5,bit-6被設置,那麼被清除的則是bit-3(越小優先級別越高)。在清除優先級最高的bit之後,8259A會到IRR中察看是否有優先級別高於當前正在處理的IRQ中優先級別最高的IRQ,如果有,則將此IRQ提交給CPU處理,同時設置相應的bit。還以上面的例子為例,當bit-3被清除之後,如果發現在IRR中有一個IRQ4等待被處理,則將其提交給CPU,在收到來自於CPU的第一個INTA信號之後,則將IS Register的bit-4置為1。
在此過程中,如果8259A接到更高優先級別的IRQ,則將其立即提交給CPU。比如,當前正在處理的IRQ為IRQ3,IRQ5,那麼IS Register中被設置的bit為bit-3,bit-5;如果此時接到一個IRQ1,則立即將其提交給CPU,在收到來自於CPU的第一個INTA信號之後,則將IS Register的bit-1置為1。
由此過程我們也可以看出,為了實現這種優先級機制,必須將EOI設為手動模式,也就是説必須將ICW4的bit-1設為0。因為,對於自動EOI模式,8259A會在收到來自於CPU的第2個INTA信號之後,就自動將IS Register中此IRQ對應的bit清0,而事實上,這個時候此IRQ對應的中斷服務程序還沒有被CPU調用,也就是説此IRQ還沒有被處理結束,而由於此IRQ對應的bit已經被清除,如果此IRQ是一個優先級很高的話,那麼此IRQ的處理完全可以被一個優先級別更低的IRQ所中斷。這不是我們所需要的。