linux怎么注册中断函数,linux中断(3):中断注册之request_irq

注册中断的函数是request_irq,实际上这个函数会调用request_threaded_irq,但由于

调用request_threaded_irq(irq, handler, NULL, flags, name, dev);时,参数3,也就是thread_fn为NULL,

调用request_irq注册的isr不会被线程化。

request_threaded_irq(unsigned int irq, irq_handler_t handler,

irq_handler_t thread_fn,

unsigned long flags, const char *name, void *dev);

static inline int __must_check

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);

}

-----------------------------------------------------------------------------

下面介绍下request_threaded_irq

线程化的中断服务程序,包括两部分

handler, 在中断环境下执行的程序

thread_fn 在线程环境下执行的程序, 如果为NULL,就不会为当前注册的中断产生一个专门的内核线程

/**

* request_threaded_irq - allocate an interrupt line

* @irq: Interrupt line to allocate

* @handler: Function to be called when the IRQ occurs.

*    Primary handler for threaded interrupts

*    If NULL and thread_fn != NULL the default

*    primary handler is installed

* @thread_fn: Function called from the irq handler thread

*      If NULL, no irq thread is created

* @irqflags: Interrupt type flags

* @devname: An ascii name for the claiming device

* @dev_id: A cookie passed back to the handler function

*

* This call allocates interrupt resources and enables the

* interrupt line and IRQ handling. From the point this

* call is made your handler function may be invoked. Since

* your handler function must clear any interrupt the board

* raises, you must take care both to initialise your hardware

* and to set up the interrupt handler in the right order.

*

* If you want to set up a threaded irq handler for your device

* then you need to supply @handler and @thread_fn. @handler is

* still called in hard interrupt context and has to check

* whether the interrupt originates from the device. If yes it

* needs to disable the interrupt on the device and return

* IRQ_WAKE_THREAD which will wake up the handler thread and run

* @thread_fn. This split handler design is necessary to support

* shared interrupts.

*

* Dev_id must be globally unique. Normally the address of the

* device data structure is used as the cookie. Since the handler

* receives this value it makes sense to use it.

*

* If your interrupt is shared you must pass a non NULL dev_id

* as this is required when freeing the interrupt.

*

* Flags:

*

* IRQF_SHARED  Interrupt is shared

* IRQF_TRIGGER_*  Specify active edge(s) or level

*

*/

/*

关于IRQF_ONESHOT, 直到线程函数执行完毕才会开启该中断

IRQF_ONESHOT:Interrupt is not reenabled after the hardirq handler finished.

Used by threaded interrupts which need to keep the irq line disabled until

the threaded handler has been run. */

int request_threaded_irq(unsigned int irq, irq_handler_t handler,

irq_handler_t thread_fn, unsigned long irqflags,

const char *devname, void *dev_id)

{

struct irqaction *action;

struct irq_desc *desc;

int retval;

/*

* Sanity-check: shared interrupts must pass in a real dev-ID,

* otherwise we'll have trouble later trying to figure out

* which interrupt is which (messes up the interrupt freeing

* logic etc).

*/

/* 如果是共享中断,dev_id不能为NULL,否则在free_irq时,没有devid作为参照,无法释放 */

if ((irqflags & IRQF_SHARED) && !dev_id)

return -EINVAL;

desc = irq_to_desc(irq);

if (!desc)

return -EINVAL;

if (!irq_settings_can_request(desc) ||

WARN_ON(irq_settings_is_per_cpu_devid(desc)))

return -EINVAL;

if (!handler) {

if (!thread_fn)

return -EINVAL;

handler = irq_default_primary_handler;

}

/* 分配一个action, handler,thread_fn赋给action

action->handler,

action->thread_fn  */

action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);

if (!action)

return -ENOMEM;

action->handler = handler;

action->thread_fn = thread_fn;

action->flags = irqflags;

action->name = devname;

action->dev_id = dev_id;

chip_bus_lock(desc);

retval = __setup_irq(irq, desc, action); /* 安装这个action */

chip_bus_sync_unlock(desc);

if (retval)

kfree(action);

#ifdef CONFIG_DEBUG_SHIRQ_FIXME

if (!retval && (irqflags & IRQF_SHARED)) {

/*

* It's a shared IRQ -- the driver ought to be prepared for it

* to happen immediately, so let's make sure....

* We disable the irq to make sure that a 'real' IRQ doesn't

* run in parallel with our fake.

*/

unsigned long flags;

disable_irq(irq);

local_irq_save(flags);

handler(irq, dev_id);

local_irq_restore(flags);

enable_irq(irq);

}

#endif

return retval;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值