linux的中断2: 线程模式

1、注册中断
1)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);
}


handler - 中断处理函数
flags - 中断属性
name - 用于线程名
dev - 设备结构体,传回给isr,用于区分不同设备


flags几个常见取值:
#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
 * IRQF_DISABLED - keep irqs disabled when calling the action handler.
 *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
 * IRQF_SHARED - allow sharing the irq among several devices
 * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
 * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
 * IRQF_PERCPU - Interrupt is per cpu
 * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
 * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
 *                registered first in an shared interrupt is considered for
 *                performance reasons)
 * 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.
 * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
 * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
 * IRQF_NO_THREAD - Interrupt cannot be threaded
 * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
 *                resume time.


2)thread_fn为空,缺省不使用线程模式。
if (irq_settings_can_thread(desc))
  irq_setup_forced_threading(new);
但不设置IRQF_NO_THREAD,又被设置为线程。
kthread_create(irq_thread, new, "irq/%d-%s", irq, new->name);
如果是第一次注册,创建了一个线程来处理当前irq,FIFO模式。
如果是线程模式,handle函数被置空,并返回IRQ_WAKE_THREAD
new->handler = irq_default_primary_handler;


3)不管哪种模式,通过下面代码保存action到irq_desc中。
desc = irq_to_desc(irq);
old_ptr = &desc->action;
new->irq = irq;
*old_ptr = new; //即新的action,保存有handler,name和dev


4)share模式要保证部分flags和以前设置的兼容,如触发方式等。


2、ISR的调用
1)IDT(Interrupt Descriptor Table)中断描述表
2)do_IRQ函数
3)handle_irq:指向了handle_level_irq,或者是handle_edge_irq
4)handle_level_irq:调用handle_irq_event
if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
if (!irq_check_poll(desc))
goto out_unlock;


5)handle_irq_event:遍历所有action,调用action->handler(irq, action->dev_id);
6)如果返回IRQ_WAKE_THREAD,说明是线程模式
irq_wake_thread(desc, action);
test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags)
wake_up_process(action->thread);

通知线程开始处理



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值