asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
handle_IRQ(irq, regs);
generic_handle_irq(irq);
//#define irq_to_desc(irq) (&irq_desc[irq])
//根据中断号在数组irq_desc中找到一项
struct irq_desc *desc =
irq_to_desc(irq);
generic_handle_irq_desc(irq,
desc);
desc->handle_irq(irq,
desc)
在系统初始化的时候会调用:
arch_initcall(s3c2440_irq_init);
subsys_interface_register(&s3c2440_irq_interface);
static struct subsys_interface s3c2440_irq_interface =
{
.name =
"s3c2440_irq",
.subsys =
&s3c2440_subsys,
.add_dev =
s3c244x_irq_add,
};
s3c244x_irq_add
irq_set_chip_and_handler(IRQ_NFCON,
&s3c_irq_level_chip,handle_level_irq);
irq_set_chip_and_handler_name(irq, chip,
handle, NULL);
__irq_set_handler(irq, handle, 0,
name);
desc->handle_irq =
handle;
我们看到desc->handle_irq(irq,
desc)实际就是执行handle_level_irq这个函数,我们继续跟踪:
handle_level_irq(irq, desc)
handle_irq_event(desc);
struct irqaction *action =
desc->action;
handle_irq_event_percpu(desc,
action);
res = action->handler(irq,
action->dev_id);
我们看到最终会执行到这个函数,显然action->handler肯定就指向我们注册的中断处理函数!
为了验证一下,我们从注册中断来进行分析:
request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE,
"S2",&pins_desc[0]);
request_threaded_irq(irq, handler, NULL, flags,
name, dev);
struct irqaction *action;
struct irq_desc *desc;
desc = irq_to_desc(irq);// desc指向
irq_desc结构体中下表为irq的项
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
action->handler = handler;//我们的中断处理函数放在了action结构体里面
__setup_irq(irq, desc, action);
old_ptr =
&desc->action;
new->irq = irq;
*old_ptr = new;//* desc->action = new ;
这样我们 desc->action就指向了我们设置的action结构体!
我们来总结一下:
irq_desc[]是一个指向irq_desc_t结构的数组,在注册中断的时候,会根据中断号找到数组中的某一项,并填充它!其中最主要的是action成员,action成员也是一个结构体,我们要将中断号和中断处理函数填充到action结构体里去!
在发生中断的时候,会根据中断号找到对应的irq_desc_t结构体,并执行其中的handle_irq函数,而这个函数在中断初始化的时候就指向了特定的函数handle_level_irq,这个函数最终会调用irq_desc_t结构体的action成员中的中断处理函数!