无意中看到一个好贴,和大家分享一下
8259A可编程控制器在linux上的初始化
读核时碰到对8259A的初始化,不甚明了。记起两年前读过的接口技术的书籍,拿来一查。呵呵,这么多!当时怕也是不甚暸暸。温故而知新,不亦乐乎!
1.
因为8259A硬件的功能较多,需要多个命令来初始化,而I/O端口只有两个,所以命令格式教繁杂。只选择了相关的部分介绍。有特殊系统需要的朋友,可参看计算机接口方面的书籍。
1.1
硬件的外部连接概图:
========================================= 数据总线 /\ /\ || || ........ (接地) || +---+ || : : - || |CPU|<----+ +5v || : :INT |SP/EN \/D0~D7 +---+ |INT |SP/EN \/D0~D7 : +-+----+---------------+ +-+------+-------------+ : | cas0|<--------|cas0 | : ===>| 8259A 从片 cas1|<--------|cas1 8259A 主片 |<===其他 : 其他| cas2|<--------|cas2 | : +----------------------+ +----------------------+ : | | | | | | | | | | /\ | | | | | : | | | | | | | | | | : | | | | | : 8 9 10 11 12 13 14 15 0 1 :2 3 4 5 6 7 <--IRQ : IR0 . . . IR4 . . .IR7 IR0 : IR7 : : :.............................................:
1.2
8259A引脚概述:
PC使用两个8259A级联:主片使用I/O地址为20H,21H。从片使用I/O地址为A0H,A1H。
从片的INT(中断请求脚)连接主片的第2请求脚(IR2)。
INT >>>输出脚。中断申请。
CAS0~CAS2 >>>输入或输出脚。级联总线。主片向从片发送选择ID,(ID在从控的ICW3中 指定)
SP/EN >>>主从定义/缓冲器方向。
IR0~IR7 >>>输入脚。外设中断请求。
其他:
INTA >>>输入脚。中断响应。
CS >>>输入脚。用作地址选线。
A0 >>>输入脚。用作地址选线。
WR >>>输入脚。写(out操作)
RD >>>输入脚。读(in操作)
1.3
8259A的内部有三个8位的寄存器:IRR,ISR,IMR。
1.3.1
IRR:其寄存器的8位(D0~D7)对应IR0-IR7脚,当IRn脚有中断请求时,IRR寄存器的Dn位置1,并锁存。可用命令OCW3读取IRR的内容。
1.3.2
ISR:当IRR寄存器的对应位置1,且CPU响应时(INTA脚上有一个希望的脉冲),ISR对应位置1,表示正在进行的中断服务。在自动结束方式中,在受到CPU发送的第2个INTA的脉冲时ISR响应位清零。非自动结束方式,在中断服务程序中发送中断结束命令,使ISR中的相应位清零。注意中断可嵌套,在CPU接受中断申请时(可用汇编命令STI和CLI,控制CPU对INT的回应与否),更高级中断请求可以中断正在进行的中断服务程序,此时ISR中将有2个或多个位被置1。可用命令OCW3读取ISR的内容。
1.3.3
IMR:当IMR寄存器的(D0~D7)某位置1时,禁止IRn脚的中断请求。通过对IMR的操作,比使用STI或CLI命令提供了更大的灵活性。可随时向8259A的奇数I/O端口操作来读出IMR中的内容。
1.3.4
对8259A的初始化命令字有2~4个,用ICW1,ICW2,ICW3,ICW4代表;
8259A的初始化流程图:
+------+ +------+ +---------+ Y +------+ +-------+ Y +----+|送ICW1|-->|送 ICW2|-->|多片级联 ?|-->|送ICW3|-->|需ICW4?|-->|ICW4|-->接受中断+------+ +------+ +----+----+ +------+ A +---+---+ +----+ A |N | |N | | | | | +-----------------+ +--------------+
1.3.5
操作命令字有三个用OCW1,OCW2,OCW3代表。
操作命令字无须顺序发送。
1.3.6
写ICW1,OCW2,OCW3使用I/O端口20H,A0H。
写ICW2,ICW3,ICW4,OCW1使用端口21H, A1H.
2
下面重点介绍ICW和OCW
2.1
ICW1的数据结构以位来描述。具体格式如下:
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+------+--------+----+----+----+ | 0 | | 0 | 0 | 0 | 1 | LTIM | ADI|SNGL|ICW4| +------+ +----+----+----+------+--------+----+----+----+ I/O地址 | 无 效 |特征 位|电平 触发|无 效|单片|需 否| 低位 +--------------+------+--------+----+----+----+
D4为特征位,D4=1
D3(LTIM)决定触发方式:D3=1为电平触发;D3=0为边沿触发。
D1(SNGL)决定是否单独使用8259A:D1=1为单片使用;D1=0为多片级联使用。
D0(ICW4)决定是否使用ICW4: D0=1为需要使用;D0=0为不需要使用。
2.1.1
8259A有两种触发方式:电平触发方式,边缘触发方式。
在PC系统中,采用后者。外设连接到8259A的中断请求脚上有低->高的跃变请求。并在第一个INTA到来之前保持高电平,则IRR寄存器相应位置1。
电平触发方式中,不理会中断请求脚有无跃变,只要测到高电平,并在第一个INTA到来之前保持高电平,则IRR寄存器相应位置1。
2.1.2
因有两个8259A,所以要确定如何连接它们(虽然可能看不见它们,因已集成到其他芯片中去了)。有两种级联方式:主从方式,缓冲方式。在PC系统中,采用非缓冲主从方式。(物理联线决定:主片SP/EN引脚接高电平,从片SP/EN引脚接地)
2.1.3
PC系统中,需要使用ICW4来定义中断的结束方式。
2.2
ICW2的格式:
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+---+---+---+ | 1 | | T7 | T6 | T5 | T4 | T3 | 0 | 0 | 0 | +------+ +----+----+----+----+----+---+---+---+ I/O地址 | 中断类型号的高5位 | 无效 | 低位 +------------------------+-----------+
2.2.1
8259A向CPU提供的中断类型号是8位的。ICW2的高5位用来设置中断类型号,ICW2的低3位在16位以上的CPU是无效的。低3位的中断类型号由硬件线脚决定,如在第4脚产生中断请求,则低3位就是0100B。
2.2.2
在此需要提到的是,PC的BIOS将IRQ对应的中断类型号设置为08H-0FH,70H-77H。在LINUX中对8259A作了重新的初始化,修改了外部中断类型号的分配,20H-2FH,使之分配得更合理。
2.3
ICW3的格式在主片与从片是不同的。
2.3.1
8259A的SP/EN引脚接高电平为主片,主片的ICW3格式:
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 1 | | S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 | +------+ +----+----+----+----+----+----+----+----+ I/O地址 |在主片的IRn脚连接从控,则Sn=1; 否则Sn=0 | 低位 +---------------------------------------+
2.3.2
8259A的SP/EN引脚接地为从片,从片的ICW3格式:
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 1 | | - | - | - | - | - |ID2 |ID1 |ID0 | +------+ +----+----+----+----+----+----+----+----+ I/O地址 | 从控标志码 | 低位 +--------------+
从控标志码表示从片的INT(中断请求脚)被联接到哪个请求脚IRn。
2.4
ICW4的格式:
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 1 | | 0 | 0 | 0 |SFNM| BUF| M/S|AEOI| uPM| +------+ +----+----+----+----+----+----+----+----+ I/O地址 低位
2.4.1
D4=1,采用特定嵌套方式;D4=0,采用一般嵌套方式。
D3=1,8259A为缓冲器方式;D3=0,为非缓冲方式。
D2=1,(在缓冲器方式下)为主控;D2=0,为从控。在非缓冲器方式下,由8259A的SP/EN引脚的电位决定主从。
D1=1,采用自动结束方式,故无须发送中断结束命令EOI;D1=0,采取非自动结束方式,在中断服务程序完成后,要发送中断结束命令EOI。发送EOI命令,即是向I/O端口写操作命令字OCW2,来复位8259A中的中断服务寄存器。
D0=1,8259A用于X86系统;D0=0,8259A用于8080/8085系统。
2.4.2
在PC系统中,使用一般嵌套方式;采用非缓冲主从方式级联两片8259A,采用非自动结束式。
在一般嵌套方式中,8259A屏蔽所有同级或更低级的中断请求。从片上产生的所有申请在主片上都是同级申请。因主片使用一般嵌套方式,所以在从片有中断服务执行时,主片屏蔽从片的所有中断请求,从片中即使有更高级的中断请求,也不能得到响应。如果您有特别的系统需求,十分介意这点,可以考虑修改主片工作在特定嵌套方式下。这时同级的中断请求也被立即通知CPU。如果CPU此时容许中断(标志寄存器的IF=0),则将响应新的中断。
3.1
中断屏蔽操作OCW1
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 1 | | M7 | M6 | M5 | M4 | M3 | M2 | M1 | M0 | +------+ +----+----+----+----+----+----+----+----+ I/O地址 低位
Mn=1,屏蔽IRn脚的中断申请;Mn=0,开放IRn脚的中断申请。
3.2
中断结束操作&中断排队方式操作OCW2
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 0 | | R | SL | EOI| 0 | 0 | L2 | L1 | L0 | +------+ +----+----+----+----+----+----+----+----+ I/O地址 | 特征位 | 中断等级编码 | 低位 +---------+--------------+
因中断结束操作和中断排队方式操作都使用OCW2实现,所以它的功能位代表的功能重叠交叉,需要细心品味。8259A的功能强大,可以实现优先权的轮换。其中又可以分为两种方式。a自动轮换,即当执行完一中断源的服务之后,此中断源将被设为最低的优先权;b指定轮换,在程序中指定某个中断的优先权最低。
D7:优先权轮换操作位。R=1,则要轮换优先权;R=0,优先权固定。
D6:指定中断级别。SL=1,用L0~L2位指定某一中断等级;SL=0,L0~L1无效。
D5:EOI=1,本OCW2是一条EOI命令,如SL=1,则将寄存器ISR中,L0~L2中指定位的清零。
如SL=0,则寄存器ISR中最高的已被置1的位清零。
D3~D4:特征位,与OCW3区别。
D0~D2:用来指定中断等级(0~7)。用途有二:EOI=1,SL=1时,指定ISR位清零;当R=1
,SL=1时,指定某一中断的优先权为最低。
常用的中断结束命令即是一种OCW2。
.
.中断服务程序
.
mov AL,0x20 //OCW2,不指定级别的EOI
out 0x20,AL
IRET //中断返回命令
3.3
查询中断方式操作&特定屏蔽方式操作&读寄存器操作 OCW3
A0 D7 D6 D5 D4 D3 D2 D1 D0 +------+ +----+----+----+----+----+----+----+----+ | 0 | | -- |ESMM| SMM| 0 | 1 | P | RR | RIS| +------+ +----+----+----+----+----+----+----+----+ I/O地址 | 特征位 | 低位 +---------+
RIS=1,选读ISR;RIS=0,选读IRR。RIS的数据,仅在RR=1时有效。
RR=1,CPU按照RIS位选寄存器。RR=0,按照以前的选定(即上次RR=1时选定的寄存器)。
P=1,CPU将执行一条读查询字的命令。//不错,有此功能。这里不再介绍了。
SMM=1,设置特定屏蔽方式,在中断服务过程中,容许所有中断(包括低级中断)向CPU提出中断申请。这将打乱所有嵌套方式的优先权。//慎重使用。
ESMM=1,则SMM位的指定有效。ESMM=0,SMM位指定无效。
=================================================
说了这许多才入正题,现在看下面的程序应不成问题了:
//linux对8259A的初始化程序在/arch/i386/boot/setup.S中
mov al,#0x11 /*ICW1设为00010001B*/
out #0x20,al /*写主8259A*/
call delay /* I/O操作的延时要求 */
out #0xA0,al /*写从8259A*/
call delay
//接着送ICW2
mov al,#0x20
out #0x21,al //主片的中断类型号,被安排在20H-27H
call delay
mov al,#0x28
out #0xA1,al //从片的中断类型号,被安排在28H-2FH
call delay
//接着发送ICW3
mov al,#0x04 //主片的第2请求脚IR2联接从片
out #0x21,al
call delay
mov al,#0x02 //从片的中断请求脚,联接到主片的第2请求脚IR2
out #0xA1,al
call delay
//接着发送ICW4
mov al,#0x01 //一般嵌套;非缓冲;需要EOI;X86CPU
out #0x21,al //设置主片
call delay
out #0xA1,al //设置从片
call delay
//发送OCW1,因此时系统初始化未完成,不接受任何外部中断请求。
mov al,#0xFF //屏蔽所有中断
out #0xA1,al //设置从片
call delay
mov al,#0xFB //屏蔽除IR2外的所有中断
out #0x21,al //设置主片
至此8259A的初始化完成。在适当的时候,系统可以接受外部中断时,将再次发送OCW1
容许外部中断。
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |