linux-3.14版本;
1. request_irq
原型: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
作用:向内核注册一个中断处理函数;
参数1:IRQ号,用于决定构造的struct irqaction结构体对象被插入到哪个链表;
参数2:typedef irqreturn_t (*irq_handler_t)(int, void *); 指向中断处理函数的函数指针;
参数3:IRQF_开头的中断相关标志; 常见的几种;如下:
- #define IRQF_TRIGGER_NONE 0x00000000
- #define IRQF_TRIGGER_RISING 0x00000001 //上升沿触发
- #define IRQF_TRIGGER_FALLING 0x00000002 //下降沿触发
- #define IRQF_TRIGGER_HIGH 0x00000004 //高电平触发
- #define IRQF_TRIGGER_LOW 0x00000008 //低电平触发
-
- #define IRQF_SHARED 0x00000080 //共享中断必须设置的标志
- #define __IRQF_TIMER 0x00000200 //定时器专用中断标志
参数4:该中断在/proc中的名字;
参数5:区别共享中断中不同设备所对应的struct irqaction结构体对象;共享中断必须传一个非NULL实参,非共享中断可以为NULL;
返回值:成功返回0; 失败返回负数;
2. free_irq
void free_irq(unsigned int irq, void *dev_id)
作用: 注销一个中断处理函数;
参数1:IRQ号;
参数2:共享中断必须传一个有requist_irq参数5相同的非NULL实参;
3. 内核源码阅读笔记
request_irq调用request_threaded_irq,然后又调用__setup_irq函数;
- //以下代码块必须以原子方式执行
- raw_spin_lock_irqsave(&desc->lock, flags);
-
- //遍历irq所在irqaction链表,遍历到末尾结束;
- old_ptr = &desc->action;
- old = *old_ptr;
- if (old) {
-
- /* add new interrupt at end of irq queue */
- do {
- /*
- * Or all existing action->thread_mask bits,
- * so we can find the next zero bit for this
- * new action.
- */
- thread_mask |= old->thread_mask;
- old_ptr = &old->next;
- old = *old_ptr;
- } while (old);
- shared = 1;
- }
-
- ...
-
- //将新的通过irq构造的struct irqaction对象加入链表尾
- new->irq = irq;
- *old_ptr = new;//加入链表尾部
-
- if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
- desc->istate &= ~IRQS_SPURIOUS_DISABLED;
- __enable_irq(desc, irq, false);//使能中断
- }
-
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
- //在proc下生成信息
- register_irq_proc(irq, desc);
- new->dir = NULL;
- register_handler_proc(irq, new);
- free_cpumask_var(mask);
-
- return 0;//成功返回0
free_irq函数调用kfree(__free_irq(irq, dev_id)); 其中__free_irq函数返回找到的struct irqaction;
- static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
- {
- raw_spin_lock_irqsave(&desc->lock, flags);
-
- action_ptr = &desc->action;
- //遍历irq所在的action链表,通过dev_id找到对应的struct irqaction对象
- for (;;) {
- action = *action_ptr;
-
- if (!action) {
- WARN(1, "Trying to free already-free IRQ %d\n", irq);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
- return NULL;
- }
-
- if (action->dev_id == dev_id)
- break;
- action_ptr = &action->next;
- }
-
- ...
- raw_spin_unlock_irqrestore(&desc->lock, flags);
- unregister_handler_proc(irq, action); //注销/proc下相关信息
- ...
-
- return action; //找到返回该对象,然后kfree掉;
- }