Linux外部中断架构初始化流程-----Tiny6410


arch/arm/plat-s3c64xx/irq-eint.c文件实现了S3C64XX系列的外部中断初始化,这是一个内核模块,入口点是s3c64xx_init_irq_eint,声明如下:

arch_initcall(s3c64xx_init_irq_eint);

参考源码可以确定编译时会将其替换为

<SPAN style="FONT-SIZE: 14px">static initcall_t __initcall_s3c64xx_init_irq_eint3 __used __attribute__((__section__(".initcall3.init"))) = s3c64xx_init_irq_eint;</SPAN>

类似于驱动的module_init,这个宏定义将函数地址保存在变量__initcall_s3c64xx_init_irq_eint3 中,并强制其存放到段initcall3.init处,函数s3c64xx_init_irq_eint完成外部中断的架构初始化,调用流程如下:

(1)s3c64xx_init_irq_eint

(2)set_irq_handler

(3)__set_irq_handler//设置跟架构相关的handle_irq,当中断发生时会调用

(4)handle_level_irq

(5)handle_IRQ_event

(6)set_irq_chained_handler

(7)__set_irq_handler//设置中断处理程序

当发生中断时,首先跳转到异常向量表处,然后调用do_asm_IRQ函数,接着调用generic_handle_irq<=generic_handle_irq_desc(按中断号来查询irq_desc型变量)<=desc->handle_irq(与架构相关)

 

内部异常和中断设置流程如下图:

 

在Linux中使用函数request_irq来申请中断号,并注册用户中断处理函数到系统中,request_irq函数在interrupt.h中定义如下:直接调用函数request_threaded_irq,而该函数定义在文件kernel\irq\Manage.c 中,分析源码可知,它主要做以下事情:

1.动态分配一个irqaction结构体

2.将request_irq函数中传递进来的irq,irq_handler_t,flags等值赋给该结构体的对应字段上

3.调用.__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)将该结构体挂载到对应中断的irq_desc类型的结构体上

相关内容