中断及共享中断概述

来源:互联网 发布:广东windows 98 编辑:程序博客网 时间:2024/05/16 16:59

大多数CPU核心有两种中断输入:一种提供给常规中断的;另一种提供给非屏蔽性中断(nonmaskable interrupts,NMIs)的。标准外围设备使用常规中断输入;而NMIs被用来应付危险的中断,这些中断不能被忽略或禁止,如:Watchdog 的超时设定。在多数设计中,NMI并没有被使用。

对于大多数系统来说,仅有一个常规中断是不足以应付那么多的中断资源,比如:计数器、DMAs和通信端口。而使用中断控制器可以使CPU核心和更多的中断资源相联系。

中断控制器允许CPU读取的每一个中断线(interrupt line)的状态,并产生中断,对中断设立优先级。例如:有选择性的避免个别的中断资源打扰CPU。中断控制器可以是独立的外部器件,也可以使运算器芯片的一部分。

中断控制器能处理两种中断方式:电平触发方式和边缘触发方式。

电平触发中断:当中断控制器探测到在中断线上有一个触发电平(满足一定电平高度)出现时,它就会请求一次CPU中断。然后,产生中断请求的外围设备就一直占据着中断线,等到CPU有所回应后,才会放开中断线。典型的做法是:由中断服务程序通知外围设备放开中断线。

边缘触发中断:又分为两种,在中断线上,由高电平到底电平转换的边缘触发,以及由低电平到高电平转换的边缘触发。能对中断线产生短暂的脉冲波的外部外围设备可以用这种方式。另外,一些兼容电平触发的外围设备也同样可以使用这种方式,它们占据着中断线,只有当软件处理中断后才会放开所占据的中断线。

使用共享中断
当多个中断资源共用一个中断线时,就有麻烦了。当你的中断控制器的输入不够多时,共享中断是很有必要的。在硬件上,只要使用线接或(或者,逻辑或)阵列,就可以达到目的。

共享中断比你想象中还要普遍。甚至即使电路设计者没有明确共用一个硬件中断线时,也会有共享中断的。

看看典型的外部通用异步收发器(UART):它只有一个中断输出,为不同的内部中断资源所共享,比如:接受中断和发送中断。这些中断在中断控制器内部用“或方式”有效的连接到一块了。

无论你何时共用中断线,必须要考虑的是:当两个或更多的中断信号同时产生或相继产生时,会出现什么样的状况?如果不能很好处理的话,你就有可能丢失中断信号以及锁定中断线
边缘触发中断的共享
共享边缘触发中断比较复杂。如果两个中断信号同时产生或相继产生,中断控制器就会只收到一个中断信号。要避免丢失中断信号,中断服务程序必须在离开当前命令行外壳之前检查所有中断资源。

但还不够:另外,要避免竞争,使得下一个中断信号丢失的竞争,中断控制器就必须等待着中断线的被放开。这种特殊的处理能使边缘触发中断的共享不但效率低下,而且容易产生bug。

丢失中断信号的结果可能很严重。如果外围设备依赖CPU来通知它放开它所占据的中断线,而中断控制器又没有收到中断信号的话,那么,这个中断线会被无限期的占据,换句话说,也就不会再有新的中断信号在这条中断线上产生了。

虽然上述情况发生的可能性很小,一旦发生,那就是一场又漫长又失败的调试会议了。因此,你要避免这种中断共享。

电平触发中断的共享
共享中断的最简单方式,就是使用电平触发中断类型。这种方式很安全,因为你是不可能丢失中断信号的。

例如,如果两个中断请求同时要求中断服务,你也只能处理其中一个,这时中断线是不会锁住,仍然能有效工作。而另一个中断请求会照常产生,等待你的处理。


在Linux内核中,request_irq() 函数是注册中断服务函数:函数的原型如下:


int request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long 

frags, const char *device, void *dev_id);

5个参数的含义如下:

第一个参数irq:申请的硬件中断号;

第二个参数handler:是一个函数指针,向系统登记的中断处理函数,是一个回调函数,当中断发生时,系统调用这

个函数,传入的参数包括中断设备 id,寄存器值。

第三个参数flags:指定了快速中断或中断共享等中断处理属性。

第四个参数devices:指定设备驱动程序的名称。

第五个参数dev_id:传入中断处理程序的参数,可以为NULL,在注册共享中断时,此参数不能为NULL,作为共享中断

时的中断区别参数。

返回值:

函数运行正常时返回 0 ,否则返回对应错误的负值。


原创粉丝点击