Chinaunix首页 | 论坛 | 博客
  • 博客访问: 114474
  • 博文数量: 32
  • 博客积分: 1470
  • 博客等级: 上尉
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-13 21:27
文章分类

全部博文(32)

文章存档

2011年(5)

2010年(27)

我的朋友

分类: LINUX

2010-07-07 17:27:01

“中断屏蔽寄存器”(Interrupt Mask Register,简称IMR)用于屏蔽8259A的中断信号输入,每一位对应一个输入。当IMR中的bit[i](0≤i≤7)位被置1时,相对应的中断信号输入线IRi上的中断信号将被8259A所屏蔽,也即IRi被禁止。

当外设产生中断信号时(由低到高的跳变信号,80x86系统中的8259A是边沿触发的,Edge Triggered),中断信号被输入到“中断请求寄存器”(Interrupt Request Register,简称IRR),并同时看看IMR中的相应位是否已被设置。如果没有被设置,则IRR中的相应位被设置为1,表示外设产生一个中断请求,等待CPU服务。

然后,8259A的优先级仲裁部分从IRR中选出一个优先级最高中断请求。优先级仲裁之后,8259A就通过其INT引脚向CPU发出中断信号,以通知CPU有外设请求中断服务。CPU在其当前指令执行完后就通过他的INTA引脚给8259A发出中断应答信号,以告诉8259A,CPU已经检测到有中断信号产生。

8259A在收到CPU的INTA信号后,将优先级最高的那个中断请求在ISR寄存器(In-Service Register,简称ISR)中对应的bit置1,表示该中断请求已得到CPU的服务,同时IRR寄存器中的相应位被清零重置。

然后,CPU再向8259A发出一个INTA脉冲信号,8259A在收到CPU的第二个INTA信号后,将中断请求对应的中断向量放到数据总线上,以供CPU读取。CPU读到中断向量后,就可以装入执行相应的中断处理程序。

 

边沿触发方式

 

边沿触发方式也是在初始化8259A时,由相应的控制字决定的。它是采用IR输入信号的上升沿触发即信号由低电平跳转高电平时触发,当IR由低电平跳转为高电平后,一直保持高电平到中断被响应时止。当第一个中断响应脉冲INTA的下降沿出现后,边沿检测器的锁存作用被解除,只有当IR变为无效后,边沿检测器才能重新进入待命状态,接受其它中断请求。因此,边沿触发方式,最好用负脉冲的后沿实现触发,IR信号为高时,为保持态,以满足定时要求。如图8-11所示。

 

 

 

边沿触发方式常被用于不希望产生重复响应及中断请求信号是一个短暂脉冲的情况。如果边沿触发方式与自动EOI方式联合使用,不会发生"重复嵌套"现象。

中断,边沿触发,还是电平触发

  那天忽然被人问起:中断的触发方式又有哪些?
  我脱口而出:电平触发、边沿触发。
  又问:都用在什么情况下?
  我说:边沿触发主要用在多个设备共享中断的情况下,不共享就用电平触发。
  又问:这两种方式,各有什么有缺点?使用的时候应该注意什么问题?
  我想了想,无言以对。只好说:我们在项目中没有遇到这类问题,所以也没有做过深入思考,我不清楚。
  昨天仔细查了一下书,还是没搞懂他最后这个问题的意图,也不清楚他所设想的正确答案是什么。
 
  一般来说,x86外设的中断线都通过一个中断控制器连接到CPU,CPU和中断控制器之间只有一根信号线,中断控制器8259与之相连引脚的叫作INT,这个线是电平触发的。而外设和中断控制器之间的信号线有多根,分别用来连接不同的外设,只要任何一个外部设备发生中断,8259都会asserted他的INT,通过这个信号通知CPU有外部中断发生了,如果I386的flags寄存器中的中断位被置位(用STI指令),则I386在总线上启动一个中断交易,从8259中把中断向量的号码读出来,然后再产生一个软件中断,使软件进入中断服务程序的入口。软件处理完中断之后,向8259写一个特殊的命令,说明中断已经处理完成,这个时候8259会使INT信号无效。至此,一个完整的中断处理过程完成。  8259在收到软件的中断应答之前,INT一直是有效的。
也就是说,如果软件不发送这个命令,那么,INT一直是高高电平的,无法再发送新的中断给CPU,所以,为了接受接下来的中断,要使INT先无效,于是,必须发送一个命令给8259A,而这个软件的发送命令就是
 /* Start handling the irq */
 desc->chip->ack(irq);
这个函数的原型是
static void ack_apic_edge(unsigned int irq)
{
 irq_complete_move(irq);
 move_native_irq(irq);
 ack_APIC_irq();
}
 
static inline void ack_APIC_irq(void)
{
 /*
  * ack_APIC_irq() actually gets compiled as a single instruction:
  * - a single rmw on Pentium/82489DX
  * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC)
  * ... yummie.
  */
 /* Docs say use 0 for future compatibility */
 apic_write(APIC_EOI, 0);//其中APIC_EOI是宏,0XB0
}
 
static __inline void apic_write(unsigned long reg, unsigned int v)
{
 *((volatile unsigned int *)(APIC_BASE+reg)) = v;
}
其实,就是把0写入到端口地址APIC_BASE+APIC_EOI,这样,算是发出了eoi命令,OXB0是APIC的EOI寄存器的偏移地址,往里面写0表示将ISR中最高位的1置0,表示中断服务的结束,其实,没有结束,这样做只是为了让同级和下级中断能够发出INTR信号,因为ISR参与了中断判优。
  外设到8259之间的中断信号(IRx)可以设置为边沿触发,如果是边沿触发的中断,8259会监视中断信号线下降沿,当发生上升延的时候,8259把这个事件锁存在一个触发器中,如果无论该信号线是否变成了无效,这个状态都会被锁存在8259中,该状态使INT线一直处于有效状态,直到软件服务程序应答该中断。
  我们下面假设一种可能的故障模式:如果是电平触发,INT的状态与外设的中断线IRx的状态紧密关联的,如果外设中断线IRx有效之后,旋即变成无效,如果CPU还没有来的及相应中断,则中断就会丢失。不知道他说的“容易发生的问题”,是不就是指的这个问题。
  这种情况似乎不容易发生,除非外设工作不正常。一般来说,外设的中断线从有效变成无效,也是需要软件应答的。软件需要通知外设,已经处理完了,或者外设自己判断出软件已经处理完了。比如8250的接收FIFO被读空了之后,中断线才会变成无效。否则,几乎肯定会发生丢失中断的情况。即便是边沿触发,也需要中断线的有效时间保持一段时间,至少是触发器的SETUP时间,否则8259可能来不及锁存该中断信号,也会发生中断丢失的问题。
阅读(3887) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:中断

给主人留下些什么吧!~~