中断注册函数分析总结

来源:互联网 发布:雅克比矩阵 机器人 编辑:程序博客网 时间:2024/05/16 23:48
#include <linux/interrupt.h> 。函数原型如下:
  • 2.4 内核
int request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long frags, const char *device, void *dev_id);
  • 2.6 内核

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);

参数说明:

irq----是要申请的硬件中断号。
handler---是向系统注册的中断处理函数的函数指针,我们需要自己定义这个函数并把函数指针做为参数传到这里,中断发生时,系统会调用这个函数,dev_id参数将被传递给它。
irqflags---是中断处理的属性,若设置了IRQF_DISABLED,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了 IRQF_SHARED,则表示多个设备共享中断(多个中断服务程序将注册到这个中断号上),若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。这几个flag是可以通过或的方式同时使用的。
dev_id---在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL这个参数一般设为设备结构体,这样方便我们把设备有关信息传给该设备的中断处理程序,在使用到共享中断时,该参数必须设置,因为free_irq(unsigned int irq, void *dev_id) 这个函数中,需要根据这个参数来判断要释放共享上的哪个中断。在共享中断里,每个中断服务程序需要读取中断寄存器来判断是否是自己的中断,是的则执行相应代码,不是的则马上返回。

其中irqreturn_t为一个类型定义,

typedef irqreturn_t (*irq_handler_t)(int, void *);

在linux-2.6.32.2/include/linux/interrupt.h中定义的request_irq()函数如下:

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)

{

    return request_threaded_irq(irq, handler, NULL, flags, name, dev);

}

  1. int request_threaded_irq(unsigned int irq,   
  2.   
  3. irq_handler_t handler,  
  4.   
  5. irq_handler_t thread_fn,   
  6.   
  7. unsigned long irqflags,  
  8.   
  9. const char *devname,   
  10.   
  11. void *dev_id )  
  12.   
  13. {  
  14.      。。。  
  15.   
  16.     /*获得一个irq_desc对象*/  
  17.   
  18.     desc = irq_to_desc(irq);  
  19.   
  20.      。。。。  
  21.   
  22.     /*向内核申请一个中断反应对象并根据传进来的参数初始化*/  
  23.   
  24.     action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);  
  25.   
  26.     if (!action)  
  27.   
  28.     return -ENOMEM;  
  29.   
  30.     action->handler = handler;  
  31.   
  32.     action->thread_fn = thread_fn;  
  33.   
  34.     action->flags = irqflags;  
  35.   
  36.     action->name = devname;  
  37.   
  38.     action->dev_id = dev_id;  
  39.   
  40.     /*处理这个中断服务,如将这个中断添加到中断服务链表中等 
  41.  
  42.      后面我们将仔细分析__setup_irq这个函数 
  43.     */  
  44.   
  45.     chip_bus_lock(irq, desc);  
  46.   
  47.     retval = __setup_irq(irq, desc, action);  
  48.   
  49.     chip_bus_sync_unlock(irq, desc);  
  50.   
  51.      。。。  
  52.   

__setup_irq来完成注册函数处理,将action注册到desc[irq]中。

  1. static int setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  
  2.   
  3. {   
  4.    。。。。  
  5.   /* add new interrupt at end of irq queue */  
  6.   
  7. old_ptr = &desc->action;
    old = *old_ptr;
  8. if (old) {
  9.               do {  
  10.   
  11.                      old_ptr = &old->next;  
  12.   
  13.                      old = *old_ptr;  
  14.   
  15.                     } while (old);  
  16.   
  17.       shared = 1;  
  18.      }
  19.    。。。
  20.     new->irq = irq;
        *old_ptr = new;
  21. 。。。
  22. }  

      while(old)循环使得old_ptr存放desc->action最后一个action的地址(即最后一个action存放nex的地址),且最后一个action->next的指针指向为空。最后,将要插入的新的action放到连尾。




0 0
原创粉丝点击