linux 中断机制浅析
阅读原文时间:2023年07月16日阅读:1

一、中断相关结构体

1.irq_desc中断描述符

2.irq_chip 芯片相关的处理函数集合

3.irqaction中断行动结构体

在整个中断系统中将勾勒出以下的关系框图

二、中断初始化工作

从start_kernel看起,大致按以下的分支顺序初始化

1.在setup_arch中主要是设置全局init_arch_irq函数

1.1.early_trap_init主要挪移了中断向量表到特定位置

2.early_irq_init 初始化全局irq_desc数组
在(kernel/irqs/irqdesc.c)中定义了全局irq_desc数组

获取irq_desc数组项的宏

early_irq_init函数

3.init_IRQ函数调用全局init_arch_irq函数,进入板级初始化

4.板级中断初始化常用到的API

1.set_irq_chip 通过irq中断号获取对应全局irq_desc数组项,并设置其irq_data.chip指向传递进去的irq_chip指针

1.1 irq_chip_set_defaults 根据irq_chip的实际情况初始化默认方法

2.set_irq_handler和set_irq_chained_handler

这两个函数的功能是:根据irq中断号,获取对应全局irq_desc数组项,并将数组项描述符的handle_irq中断处理函数指针指向handle
如果是chain类型则添加数组项的status状态IRQ_NOREQUEST和IRQ_NOPROBE属性

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

2.1 __set_irq_handler函数

3.set_irq_flags 根据irq号获取全局irq_desc数组项,并设置其status标志(中断标志)

4.set_irq_type根据irq号获取全局irq_desc数组项,并设置其status标志(中断触发类型)

4.1 __irq_set_trigger函数

5.set_irq_chip_data 根据irq号获取全局irq_desc数组项,并设置其irq_data的chip_data

6.set_irq_data

三、中断的申请与释放request_irq

1.申请中断(主要是分配设置irqaction结构体)

1.1 request_threaded_irq函数

1.2 __setup_irq函数

代码可以去细究,主要功能是填充irqaction

在设备驱动程序中申请中断可以这么申请

(eg:request_irq(1, &XXX_interrupt,IRQF_TRIGGER_RISING,"nameXXX", (void*)0))

第一个参数是中断号,第二个参数是中断处理函数,第三个参数是中断标志(上升沿),第四个是名字,第五个是设备id(非共享中断设置成(void*)0)即可

共享中断情况下要将第三个参数添加IRQF_SHARED标志,同时要给他制定第五个参数设备id

触发方式宏

然后设计中断函数

static irqreturn_t XXX_interrupt(int irq, void *arg){

……

return IRQ_HANDLED;

}

2.释放中断

2.1 __free_irq

四、中断处理过程

1.当有中断发生时,程序会到__vectors_star去查找向量表(arch/arm/kernel/entry-armv.S)

2.vector_irq的定义声明

3.vector_stub宏的定义

这几段汇编的大致意思是中断发生会跳到vector_irq去执行,vector_irq根据情况会跳到__irq_usr或__irq_svc执行

4.__irq_usr

5.__irq_svc

6.不管是__irq_svc或是__irq_usr都会调用到irqhandler

7.就这样进入了c处理的阶段asm_do_IRQ

8.generic_handle_irq函数

9.generic_handle_irq_desc函数

这里有了分支关键看CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ的设置

如果设置为1,则只调用中断描述符的handle_irq方法

如果设置为0,则如果中断描述符存在handle_irq方法则调用该方法,如果没有则调用__do_IRQ()

中断描述符handle_irq方法,一般是芯片厂商写好的,先看看__do_IRQ()吧

10.__do_IRQ函数

.__do_IRQ函数主要是调用handle_IRQ_event来处理中断

11.handle_IRQ_event函数

这里调用的irqaction的handler方法就是调用了之前设备驱动中用request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)

申请中断时传递进来的第二个参数的函数
其实很多芯片厂商在编写中断描述符handle_irq方法的时候也会调用到handle_IRQ_event函数

整个中断的处理过程就是

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章