linux驱动注册注销中断处理函数

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掉;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天未及海宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值