int sah_Intr_Init(wait_queue_head_t * wait_queue) //硬中断申请
{
...........
中断回调
result = request_irq(SAHARA_IRQ, sah_Intr_Top_Half,
0, SAHARA_NAME, NULL);
...........
}
// 硬中断函数
static irqreturn_t sah_Intr_Top_Half(int irq, void *dev_id)
{
#if defined(DIAG_DRV_INTERRUPT) && defined(DIAG_DURING_INTERRUPT)
LOG_KDIAG("Top half of Sahara's interrupt handler called.");
#endif
interrupt_count++;
reset_flag = sah_Handle_Interrupt(sah_HW_Read_Status());
/* Schedule the Bottom Half of the Interrupt. */
tasklet_schedule(&BH_task);// 对应的中断函数在适当时候将被执行
/* To get rid of the unused parameter warnings. */
irq = 0;
dev_id = NULL;
return IRQ_RETVAL(1);
}
2.
工作队列(参考:drivers\usb\musb\Musb_core.c)
note:执行于内核线程上下文
在linux2.6.36后出现cmwq自动维护工作队列的线程池
以提高并发性。之前是在work内核线程中执行。
//定义工作队列和关联函数
struct work_struct xxx_wq
void xxx_do_work(struct work_struct *work);
//中断处理底半部
void xxx_do_work(struct work_struct *work)
{
............
}
// 中断处理顶半部
irqreturn_t xxx_interrupt(int irq, void *dev_id)
{
.....
schedule_work(&xxx_wq);
.....
return IRQ_HANDLED;
}
// 设备驱动模块加载
int xxx_int(void)
{
// 申请中断
reuqest_irq(xxx_irq, xxx_interrupt, 0, "xxx", NULL);
// 初始化队列
INIT_WORK(&xxx_wq, xxx_do_work);
.................
}
// 设备模块卸载
void xxx_exit(void)
{
........
//释放中断
free_irq(xxx_irq, xxx_interrupt);
.........
}
3.
软中断(softirq)(一般不用。。。。)
note:执行与原子上下文,不能休眠
禁止和使能: loal_bh_disable() local_bh_enable()
注册:open_softirq()
触发:raise_softirq()
4.
threaded_irq(参考:driver\rtc\Rtc-ab8500.c
& driver\hwmon\Lis3lv02d.c)
request_threaded_irq(unsigned
int irq, irq_handler_t handler,
irq_handler_t thread_fn,
unsigned long irqflags,
const char *devname, void *dev_id)
devm_request_threaded_irq()
handler 对应的中断函数执行完后,如果返回值是IRQ_WAKE_THREAD则内核会分配新的线程处理这个 thread_fn函数
中断共享
申请中断时添加标志:IRQF_SHARED
类似于共用一条中断线,当中断到来时需要在中断处理函数中做判断处理
------------------------------------------------------------------------------------
参考:linux设备驱动详解 &互联网