8259A 可编程中断控制器

一 8259A 结构图

I. 主片结构 (IBM PC/XT)


II. 主从结构 (IBM PC/AT)

8259A 可编程中断控制器_第1张图片

III. 微机结构 (IBM PC/AT)

8259A 可编程中断控制器_第2张图片

二 8259A pin脚介绍

- CS:片选信号,只有CS有效时,CPU才能进行读写操作

- WR:写信号,当WR有效且CS有效时,wr使8259A接受CPU送来的命令字

- RD:读信号,当RD有效且CS有效时,使8259A将状态信息放到数据总线供CPU检测

- D7~D0:双向数据总线,用来传送控制字、状态字和中断类型号

- IR7~IR0:外部接口电路中断请求信号

- INT:向CPU发出中断请求信号

- INTA:中断响应信号,接受CPU发来的中断响应脉冲

- A0:地址输入信号,主片(偶地址为0x20,奇地址为0x21),从片(偶地址为0xA0,奇地址为0xA1)

- CAS2~CAS0:级联线,指定从片

- SP/EN:从片/允许缓冲器 信号,作为输入时,SP=1为主片,SP=0为从片;作为输出时,EN=1可以启动数据总线收发器(8286)

三 8259A 部件作用

- IRR(Interrupt Request Register):接受并锁存来自IR0~IR7的中断请求信号

- PR(Priority Resolver):把新进入的中断请求和当前正在处理的中断请求进行比较,以决定哪一个优先级更高

- ISR(In-Service Register):保存当前正在处理的中断请求

- IMR(Interrupt Mask Register):可以屏蔽IRR中的中断请求信号

- ICWs(Initialization Command words):初始化命令字,用于8259A芯片的初始化设定

- OCWs(Operation Command words):操作命令字,在8259A工作时可以对它进行动态管理和控制

四 8259A 中断处理过程

- 向CPU发送中断请求:IR0~IR7出现中断请求信号 -> IRR对应位置位 -> IMR相应位决定是否屏蔽此信号 -> 中断请求进PR -> PR把新进入的中断请求和ISR中当前正在进行处理的中断进行优先级比较 -> 若新进入的中断优先级高,则把该中断请求发送给CPU

8259A 可编程中断控制器_第3张图片

- CPU响应中断请求:若CPU的IF为1,则在完成当前指令后,相应中断请求,在INTA引脚上发出两个负脉冲,

  1. 收到第一个脉冲后:> IRR锁存允许,禁止来自IR0~IR7的中断请求,> ISR相应位置位,> IRR相应位复位

  2. 收到第二个脉冲后:> IRR锁存禁止,允许来自IR0~IR7的中断请求,> 把中断类型码寄存器(ICW2)的内容送到D7~D0数据总线上,> 若AEOI(自动结束中断)置位,则ISR中对应的位复位

五 8259A 工作方式

I. 中断优先级方式

- 全嵌套方式:固定优先级方式,IR0最高,IR7最低,禁止同级或低级的中断响应

- 特殊全嵌套方式:和全嵌套方式一样,但它允许同级的中断响应

- 优先级自动循环方式:优先级循环变化,开始时,优先级顺序为IR0 -> IR7,若此时IR3被PR选中发送了中断请求,那么优先级顺序变为IR4 -> IR7 -> IR3,即被响应的中断变成了最低级,而比它低一级的中断变成了最高级

- 优先级特殊循环方式:和优先级自动循环方式一样,但它允许设置开始时的最低优先级,如IR4被设为最低优先级,那么IR5就是最高优先级

II. 中断屏蔽方式

- 普通屏蔽方式:通过IMR来屏蔽,相应位置位则屏蔽相应的中断请求

- 特殊屏蔽方式:*

III. 中断结束方式(END OF INTERRUPT - EOI

- 中断自动结束方式(AEOI):在INTA的第二个脉冲的后沿把对应的ISR位复位

- 常规中断结束方式:通过向8259A发送常规中断结束命令,适用于全嵌套方式,因为只需把ISR中最高优先级复位

- 特殊中断结束方式:和常规中断结束方式一样,但可以指定复位ISR中的哪一位

IV. 中断触发方式

- 电平触发方式:*

- 边沿触发方式:*

V. 连接系统总线方式

- 缓冲方式:8259A通过总线驱动器(8286)和数据总线相连,EN=1有效,由ICW4的M/S位来标识是主片还是从片

- 非缓冲方式:8259A直接与数据总线相连,SP=1为主片,SP=0为从片

六 8259A 控制字编程

I. 初始化命令字


- ICW1:A0=0,D4=1


  D0. IC4:初始化时是否写入ICW4,0不写入,1写入

  D1. SNGL:是否使用级联,0为级联方式同时要写入ICW3,1为单片方式不要写入ICW3

  D2. ADI:*

  D3. LTIM:中断触发方式,0为边沿触发,1为电平触发

  D4=1

  D7~D5. A5~A7:*

8259A 可编程中断控制器_第4张图片

- ICW2:A0=1

  D2~D0. :中断类型码的低3位,表示IR0~IR7

  D7~D3. :中断类型码的高5为,初始时设定


- ICW3:A0=1,只在级联方式中使用

  1. 对于主片:表示IR0~IR7中哪些引脚接有从片,那么相应位置位

  2. 对于从片:用D2~D0位来表示接到主片的哪一根IR引脚上

8259A 可编程中断控制器_第5张图片

- ICW4:A0=1,80x86系统中必须设定它

8259A 可编程中断控制器_第6张图片

  D0. uPM:规定是哪种系统,0为8080/8085,1为80x86系统

  D1. AEOI:中断结束方式,0为非自动结束方式,1为自动结束方式

  D3,D2. BUF,M/S:> BUF=1,缓冲方式,EN=1启动数据总线收发器,M/S决定使用主片还是从片,1是主片,0是从片,> BUF=0,非缓冲方式,SP=1为主片,SP=0为从片,M/S位无效

  D4. SFNM:中断优先级方式,0为全嵌套方式,1为特殊全嵌套方式

  D7~D5. :0

8259A 可编程中断控制器_第7张图片

II. 操作命令字

8259A 可编程中断控制器_第8张图片

- OCW1:A0=1

  D7~D0. M7~M0:中断屏蔽码,对应IR7~IR0

8259A 可编程中断控制器_第9张图片

- OCW2:A0=0,D4=0,D3=0

8259A 可编程中断控制器_第10张图片

  D7. R:中断优先级方式是否按循环方式设置,1为循环方式,0为非循环方式

  D6. SL:表示L2~L0是否有效,1为有效,0为无效

  D5. EOI:中断结束命令(中断非自动结束方式),EOI=1把ISR中对应位复位

  D4=0

  D3=0

  D2~D0. L2~L0:选择结束哪个中断

8259A 可编程中断控制器_第11张图片

8259A 可编程中断控制器_第12张图片

- OCW3:A0=0,D4=0,D3=1

8259A 可编程中断控制器_第13张图片

  D7. :0

  D6,D5. ESMM,SMM:ESMM特殊屏蔽方式允许位,SMM特殊屏蔽方式位

  D4=0

  D3=1

  D2. P:查询命令,P=1读中断状态字

  D1,D0. PR,RIS:11表示读ISR,10表示读IRR

III. 读取命令字

- IMR:用奇地址直接读取,比如’in $0x21,al‘读取主片的IMR

- IRR:设置OCW3中PR=1,RIS=0,在用偶地址直接读取,比如’in $0x20,al‘读取主片的IRR

- ISR:设置OCW3中PR=1,RIS=1,在用偶地址直接读取,比如'in $0x20,al'读取主片的ISR

- 中断状态字:设置OCW3中P=1,在用偶地址直接读取,比如’in $0x20,al‘读取主片的中断状态字

8259A 可编程中断控制器_第14张图片

七 code部分

- boot/setup.S

# well, that went ok, I hope. Now we have to reprogram the interrupts :-(
# we put them right after the intel-reserved hardware interrupts, at
# int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
# messed this up with the original PC, and they haven't been able to
# rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
# which is used for the internal hardware interrupts as well. We just
# have to reprogram the 8259's, and it isn't fun.

# initialization start

# ICW1 for master, A0=0, D4=1
# D7~D5=0
# D4=1
# D3=0, LTIM=0, edge trigger
# D2=0, ADI=0
# D1=0, SNGL=0, multichip
# D0=1, IC4=1, ICW4 need
	mov	$0x11,%al		# initialization sequence
	out	%al,$0x20		# send it to 8259A-1
# 'eb 00': jmp rel8, mean that jmp to [IP+0](the next assembly instruction)
	.word	0x00eb,0x00eb		# jmp $+2, jmp $+2
# ICW1 for slaver
	out	%al,$0xA0		# and to 8259A-2
	.word	0x00eb,0x00eb

# ICW2 for master, A0=1
# D7~D3 + D2~D0 = 0x20 + IRx
	mov	$0x20,%al		# start of hardware int's (0x20)
	out	%al,$0x21
	.word	0x00eb,0x00eb
# ICW2 for slaver, A0=1
# D7~D3 + D2~D0 = 0x28 + IRx
	mov	$0x28,%al		# start of hardware int's 2 (0x28)
	out	%al,$0xA1
	.word	0x00eb,0x00eb
	
# ICW3 for master, A0=1
# D2=1, IR2 pin connects slaver
	mov	$0x04,%al		# 8259-1 is master
	out	%al,$0x21
	.word	0x00eb,0x00eb
# ICW3 for slaver, A0=1
# D2~D0=2, slaver is connectted to IR2 pin of master
	mov	$0x02,%al		# 8259-2 is slave
	out	%al,$0xA1
	.word	0x00eb,0x00eb

# ICW4 for master, A0=1
# D7~D5=0
# D4=0, SFNM=0, fully nested mode
# D3=0, BUF=0, non-buffer mode
# D2=0, M/S=0, no use because of BUF=0
# D1=0, AEOI=0, non-automatic EOI
# D0=1, uPM=1, 8086 system
	mov	$0x01,%al		# 8086 mode for both
	out	%al,$0x21
	.word	0x00eb,0x00eb
# ICW4 for slaver, A0=1
	out	%al,$0xA1
	.word	0x00eb,0x00eb

#initialization end

# OCW1 for master, A0=1
# D7~D0=0xff, all mask for IRR
	mov	$0xFF,%al		# mask off all interrupts for now
	out	%al,$0x21
	.word	0x00eb,0x00eb
# OCW1 for slaver, A0=1
	out	%al,$0xA1

- kernel/traps.c

void trap_init(void)
{
	int i;

	set_trap_gate(0,÷_error);
	set_trap_gate(1,&debug);
	set_trap_gate(2,&nmi);
	set_system_gate(3,&int3);	/* int3-5 can be called from all */
	set_system_gate(4,&overflow);
	set_system_gate(5,&bounds);
	set_trap_gate(6,&invalid_op);
	set_trap_gate(7,&device_not_available);
	set_trap_gate(8,&double_fault);
	set_trap_gate(9,&coprocessor_segment_overrun);
	set_trap_gate(10,&invalid_TSS);
	set_trap_gate(11,&segment_not_present);
	set_trap_gate(12,&stack_segment);
	set_trap_gate(13,&general_protection);
	set_trap_gate(14,&page_fault);
	set_trap_gate(15,&reserved);
	set_trap_gate(16,&coprocessor_error);
	set_trap_gate(17,&alignment_check);
	for (i=18;i<48;i++)
		set_trap_gate(i,&reserved);
	set_trap_gate(45,&irq13);
	outb_p(inb_p(0x21)&0xfb,0x21); /* 0b1111 1011 unmask IR2 pin of master */
	outb(inb_p(0xA1)&0xdf,0xA1);  /*  0b1101 1111 unmask IR5 pin of slaver */
	set_trap_gate(39,¶llel_interrupt);
}


你可能感兴趣的:(8259A 可编程中断控制器)