Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Linux內核系列—8.操作系統開發之時鐘中斷,linux內核

Linux內核系列—8.操作系統開發之時鐘中斷,linux內核

編輯:關於android開發

Linux內核系列—8.操作系統開發之時鐘中斷,linux內核


外部中斷的情況復雜一些,因為需要建立硬件中斷與向量號之間的對應關系。外部中斷分為不可屏蔽中斷(NMI)和可屏蔽中斷兩種,分別由CPU的兩根引腳NMI和INTR來接收。如下圖所示:

可屏蔽中斷與CPU的關系是通過對可編程中斷控制器8259A建立起來的。8259A可以認為它是中斷機制中所有外圍設備的一個代理。在BIOS初始化它的時候,IRQ0~IRQ7被設置為對應向量號08h~0Fh,在保護模式下向量號08h~0Fh已經被占用了,所以我們不得不重新設置主從8259A。

對8259A的設置並不復雜,通過向相應的端口寫入特定的ICW來實現。主8259A對應的端口地址是20h和21h,從8259A對應的端口地址是A0h和A1h。ICW共有4個。初始化過程如下:

1.往端口20h(主片)或A0h(從片)寫入ICW1.

2.往端口21h(主片)或A1h(從片)寫入ICW2.

3.往端口21h(主片)或A1h(從片)寫入ICW3.

4.往端口21h(主片)或A1h(從片)寫入ICW4.

這4步的順序是不能顛倒的。

ICW格式如下

Init8259A:
	mov	al, 011h
	out	020h, al	; 主8259, ICW1.
	call	io_delay

	out	0A0h, al	; 從8259, ICW1.
	call	io_delay

	mov	al, 020h	; IRQ0 對應中斷向量 0x20
	out	021h, al	; 主8259, ICW2.
	call	io_delay

	mov	al, 028h	; IRQ8 對應中斷向量 0x28
	out	0A1h, al	; 從8259, ICW2.
	call	io_delay

	mov	al, 004h	; IR2 對應從8259
	out	021h, al	; 主8259, ICW3.
	call	io_delay

	mov	al, 002h	; 對應主8259的 IR2
	out	0A1h, al	; 從8259, ICW3.
	call	io_delay

	mov	al, 001h
	out	021h, al	; 主8259, ICW4.
	call	io_delay

	out	0A1h, al	; 從8259, ICW4.
	call	io_delay

	mov	al, 11111110b	; 僅僅開啟定時器中斷
	;mov	al, 11111111b	; 屏蔽主8259所有中斷
	out	021h, al	; 主8259, OCW1.
	call	io_delay

	mov	al, 11111111b	; 屏蔽從8259所有中斷
	out	0A1h, al	; 從8259, OCW1.
	call	io_delay

	ret

我們通過對端口21h和A1h的操作屏蔽了所有的外部中斷,寫入OCW,在以下兩種情況下用到它:

1.屏蔽或打開外部中斷。

2.發送EOI給8259A以通知它中斷處理結束。

若想屏蔽或打開外部中斷,只需要往8259A寫入OCW1就可以了。OCW1格式如下:

若想屏蔽某一個中斷,將對應那一位設成1就可以了。EOI就是當每一次中斷處理結束,需要發送一個EOI給8259A,以便繼續接收中斷。而發送EOI是通過往端口20h或A0h寫OCW2來實現的。OCW2的格式如上圖所示。

發送EOI給8259A可以由如下代碼完成:

mov al, 20h
out 20h或A0h, al

 

這次我們來打開時鐘中斷(IRQ0),外部可屏蔽中斷的發生受到兩個因素的影響,只有當IF位為1,並且IMR相應位為0時才會發生。

那麼,如果我們想打開時鐘中斷的話,一方面不僅要設計一個中斷處理程序,另一方面還要設置IMR,並且設置IF位。設置IMR可以通過寫OCW2來完成,而設置IF可以通過指令sti來完成。

先寫一個時鐘中斷處理程序

_ClockHandler:
ClockHandler	equ	_ClockHandler - $$
	inc	byte [gs:((80 * 0 + 70) * 2)]	; 屏幕第 0 行, 第 70 列。
	mov	al, 20h
	out	20h, al				; 發送 EOI
	iretd

修改初始化8259A的代碼,時鐘中斷不再屏蔽

mov	al, 11111110b	; 僅僅開啟定時器中斷
	;mov	al, 11111111b	; 屏蔽主8259所有中斷
	out	021h, al	; 主8259, OCW1.
	call	io_delay

	mov	al, 11111111b	; 屏蔽從8259所有中斷
	out	0A1h, al	; 從8259, OCW1.
	call	io_delay

修改IDT:

%rep 32
		Gate	SelectorCode32, SpuriousHandler,      0, DA_386IGate
%endrep
.020h:		Gate	SelectorCode32,    ClockHandler,      0, DA_386IGate
%rep 95
		Gate	SelectorCode32, SpuriousHandler,      0, DA_386IGate
%endrep
.080h:		Gate	SelectorCode32,  UserIntHandler,      0, DA_386IGate

運行結果:

 

一個碼農的日常 

源碼

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved