在之前学习计算机组成原理的时候就曾经研究过中断: TD-CMA下计算机组成实验:带中断的复杂模型机 | Finley’s Blog
今年学习了汇编和微机接口,这是一篇对中断机制和中断控制器 8259A 的总结性文章。
术语
- 中断:暂停当前程序,转去处理异常或外设请求程序
- 主程序
- 中断服务程序 ISR: Interrupt Service Routine
- 断点:中断时,主程序中被终止指令的下一条指令地址,被压入栈中进行保护。
- 中断源:引发中断的事件或设备。
- 内部中断: CPU执行程序错误,例如除法错
- 外部中断:CPU外部的中断,外设提出的中断,如电源故障
- 中断类型号:每个中断源分配一个编号,即中断类型号
- 中断接口:实现中断管理的逻辑电路被称为中断接口。8259A 可编程中断控制器
- 中断识别:CPU确定哪一个中断源发出中断请求的过程。找到中断源对应的中断服务程序的入口地址,转去进行处理
- 查询法: 软件查询,确定中断源
- 硬件法:硬件法,由可编程中断寄存器提供中断类型号
- 中断向量:中断服务程序的入口地址: CS:IP
- 中断向量表:将系统中的所有中断向量集中起来,按照中断类型号从小到大的顺序存放在内存某区域。(数据段0段中)
中断响应:收到中断请求,CPU满足响应条件则进入中断响应周期。接受响应的条件
- CPU当前指令执行结束
- 没有更高级的中断请求正在执行
- CPU处于开中断状态,(IF = 1)
改变 IF 的状态:
- STI 开中断 SeT Interrupt
- CLI 关中断 CLear Interrupt
中断响应周期需要完成的动作:(CPU 硬件自动完成)
- 清IF, TF标志
- 将 FLAGS、CS、IP 压桟保存
- 查找中断向量表,获得 ISR 入口地址,转而去执行 ISR
8086/8088 微机中断系统
8 位二进制数表示一个中断类型号
一共支持 256 个中断源, 放置在 0 数据段的 0 ~ 3FFH (1KB)
可以分为:
- 内部中断: CPU 内部的中断
- 外部中断: CPU外部(外设)
- 不可屏蔽中断请求 NMI2
- 可屏蔽中断 (8259A)
重点关注外部中断
外部中断也叫硬件中断 ,其中:
- 不可屏蔽中断:上升沿触发、不受标志位控制、类型号为2、无需应答
- 可屏蔽中断:高电平触发(必须保持到指令结束)、受到 IF 标志位控制
中断类型号 08~0FH, 070H ~ 077H, 当中断允许时,CPU 发出中断应答信号 INTA,并从 8259A 获得中断源的中断类型码
除单步中断外,内部中断高于外部中断
中断向量
中断向量的设置和修改
设置前先关闭中断,避免在设置或修改过程中被中断
写入位置为 4N,(n表示中断类型号)
设置中断向量:
- 直接写入法: 通过 MOV 指令写入向量对应单元(设置前要关中断,设置后开中断)
- 利用 DOS 功能调用: INT 21 的 25H 功能调用。DS = 中断服务程序的段地址,DX= 偏移地址, AL = 中断类型号 (注意保护 DS 寄存器)
中断向量表 DS = 0
INT 21H 的 35H 功能获取已知中断类型号的中断向量
AL = 中断类型号
出口: ES = 段基址,BX= 偏移地址
8259A 芯片编程
- $D_{0}-D_{7}$ 数据线
- $IR_{0} - IR_{7}$ 连接中断源 ( Interrupt Request),例如连接到一个按钮触发一次中断请求
- $CAS_{0} - CAS_{2}$ 级联标志
- $INTA$ 发送中断信号
- A0 有且只有的一条地址线
EN 通过译码电路连接
8259A 工作过程:
- 中断请求,IRR 相应的位置置1
- 对于未被屏蔽的请求进行优先权裁定
- INT信号发送到CPU
- 若允许中断,则当前指令结束后连续发出两个 $\overline{INTA}$
- 第一个 $\overline{INTA}$:CPU发送后,锁定总线 $\overline{LOCK}$。8259A 收到后,将最高中断对应的ISR 置1, 并对应的 IRR 清零
- 第二个 $\overline{INTA}$:CPU发送后,清空 $\overline{LOCK}$,地址允许信号ALE无效。8259A将相应的中断类型号置入数据线
- 若系统为 自动结束中断方式 AEOI,则在两个 $\overline{INTA}$ 后自动复位 ISR。若非自动结束中断方式 EOI,则保持 ISR,直到CPU给出 EOI 命令时才复位
中断级联
单片 8259A 最多支持响应8个中断,每个IR可以级联一个8259A。最多支持 64 级中断。
方式字
先向 8259A 写入 ICW 方式字,一共有四个方式字,如果是单片只需要写入 ICW1,2,4
ICW 方式字
方式字 | $A_{0}$ | $D_{7}$ | $D_{6}$ | $D_{5}$ | $D_{4}$ | $D_{3}$ | $D_{2}$ | $D_{1}$ | $D_{0}$ | 内容 |
---|---|---|---|---|---|---|---|---|---|---|
ICW1 | 0 | x | x | x | 1 | LTIM | ADI | SNGL | IC4 | 设置 8259A 芯片 |
ICW2 | 1 | T7 | T6 | T5 | T4 | T3 | x | x | x | 设置中断类型号 |
ICW3(主片) | 1 | S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 | 设置级联方式 |
ICW3 | x | x | x | x | x | x | ID1 | ID1 | ID0 | |
ICW4 | 1 | 0 | 0 | 0 | SFNM | BUF | M/S | AEOI | uPM | 设置缓冲方式、中断结束方式等 |
ICW1 标志位 | 1 | 0 |
---|---|---|
LTIM | 电平触发 | 边沿触发 |
SNGL | 单片 | 级联 |
IC4 | 存在ICW4 | 不存在ICW4 |
ADI | 8086不使用 | < |
- ICW2 设置中断类型号 低3位自动生成
- ICW3 (主片) 设置从片挂接位置
- ICW3 (从片) 设置挂接到了哪个引脚
ICW4 | 1 | 0 |
---|---|---|
SFNM | 特殊全嵌套 | 普通全嵌套 |
BUF | 缓冲方式 | 非缓冲方式 |
M/S | 主片 | 从片 |
AEOI | 自动结束 | 非自动结束 |
uPM | 8086 | 8080 |
OCW 方式字
- OCW1, 直接对 IMR 进行设置, 设置中断屏蔽字
- OCW2, 设置/修改优先级模式,发送 EOI 命令等
- OCW3 设置中断屏蔽方式,设置中断查询方式,发送读内部寄存器命令
OCW | $A_0$ | $D_{7}$ | $D_{6}$ | $D_{5}$ | $D_4$ | $D_3$ | $D_2$ | $D_1$ | $D_0$ |
---|---|---|---|---|---|---|---|---|---|
OCW1 | 1 | IMR7 | IMR6 | IMR5 | IMR4 | IMR3 | IMR2 | IMR1 | IMR0 |
OCW2 | 0 | R | SL | EOI | 0 | 0 | L2 | L1 | L0 |
OCW3 | 0 |
OCW2中
位 | 0 | 1 |
---|---|---|
R | 固定优先级 | 循环优先级 |
SL | 普通 | 特殊 |
EOI | 不发 | 发EOI命令 |
R,L两位决定优先级方式 |
R | SL | 功能 |
---|---|---|
0 | 0 | 固定优先级 |
0 | 1 | 固定优先级 |
1 | 0 | 普通循环优先级 |
1 | 1 | 特殊循环优先级 |
在非自动中断结束的情况下,使用 EOI = 1 发送中断结束命令使 ISR 复位
EOI | SL | 功能 |
---|---|---|
0 | X | 不发EOI命令 |
1 | 0 | 普通中断结束(将 ISR 优先级最高的中断位清0 |
1 | 1 | 特殊中断结束,将 L2-L0 中指定的中断位请0 |