中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 操作系统 > Linux > Linux综合
外部中断原理分析
作者:未知 时间:2005-09-13 22:46 出处:Blog.ChinaUnix.net 责编:chinaitpower
              摘要:外部中断原理分析
      linux的外部中断分为固定部分和可变部分,固定部分为0~~15号的系统本身定义的中断,而可变部分则是提供给用户自己定义设备驱动的中断相应的,前两天稍微写了一点这方面的分析

外部中断可变部分描述:

irq_desc[]数组描述

Irq_desc_t:

typedef struct {

       unsigned int status;        /* IRQ status */

       hw_irq_controller *handler;

       struct irqaction *action;  /* IRQ action list */

       unsigned int depth;        /* nested irq disables */

       spinlock_t lock;

} ____cacheline_aligned irq_desc_t;

 

 

Irq状态是由以下各标志组合的:

unsigned int status;        /* IRQ status */

#define IRQ_INPROGRESS 1     /* IRQ handler active - do not enter! */

#define IRQ_DISABLED      2     /* IRQ disabled - do not enter! */

#define IRQ_PENDING       4     /* IRQ pending - replay on enable */

#define IRQ_REPLAY   8     /* IRQ has been replayed but not acked yet */

#define IRQ_AUTODETECT       16    /* IRQ is being autodetected */

#define IRQ_WAITING 32    /* IRQ not yet seen - for autodetection */

#define IRQ_LEVEL     64    /* IRQ level triggered */

#define IRQ_MASKED 128  /* IRQ masked - shouldn't be seen again */

#define IRQ_PER_CPU 256  /* IRQ is per CPU */

 

struct irqaction *action;  /* IRQ action list */

描述外部中断的可变部分,对一个外部中断的所有处理将以irqaction结构挂在action队列上

Interrupt.hàirqaction:

struct irqaction {

       void (*handler)(int, void *, struct pt_regs *);

       unsigned long flags;

       unsigned long mask;

       const char *name;

       void *dev_id;

       struct irqaction *next;

};

Handler中断处理函数,dev_id设备标识,用于标记多个设备共享同一个irq

 

时间中断处理程序为timer_interrupt

 

外部设备的驱动程序在初始化时都要创建自己的irqaction结构

Irq.càrequest_irq:

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

               unsigned long irq_flags, const char * devname, void *dev_id)

{

       unsigned long retval;

       struct irqaction *action;

 

       if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||

           (irq_flags & SA_SHIRQ && !dev_id))

              return -EINVAL;

 

       action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);

       if (!action)

              return -ENOMEM;

 

       action->handler = handler;

       action->flags = irq_flags;

       action->mask = 0;

       action->name = devname;

       action->next = NULL;

       action->dev_id = dev_id;

 

       retval = setup_arm_irq(irq, action);

 

       if (retval)

              kfree(action);

       return retval;

}

 

调用setup_arm_irq向内存申请一块内存填写irqaction结构,返回irq

该函数完成以下工作:

(1)       在数组irq_desc[]中找到程序申请的irq号对应的action队列

(2)       如果该队列不为空,说明该irq号被多个设备共享,检查这种共享是否允许(由老的irqaction结构的flags标识),如果合法,则将新的irqaction结构插到对应的action队列的末尾

(3)       如果队列为空,则将irqaction结构插在对应action队列的头部,填写irq_desc[irq]的其他域

 

至此外部设备驱动向系统注册中断完成

 

中断释放:

void free_irq(unsigned int irq, void *dev_id)

完成以下工作:

(1)       检查irq的合法性

(2)       action队列irq_desc[irq].action上,查找action->dev_id == dev_idirqaction结构

(3)       如果找到这样的结构,则将其从队列上摘下,同时释放其原本占用的内存空间

(4)       如果释放后,irq_desc[irq]上已经没有其他的irqaction结构,则释放irq_desc[irq]上的相应域,关掉中断

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有