interrupt子系统中的数据结构

我们接着上一篇,开始真正的interrupt子系统:

现在有一个共享的中断,网卡跟开关共享同一个gpio中断,然后当触发中断的时候,GIC会发信号给CPU,告诉他已经发生了中断了,然后CPU会去读取GIC里面的寄存器,查看是发生了什么中断,然后发现是GPIO中断后,就会去查看GPIO各个引脚的寄存器,查看是哪个引脚发生了中断,发现是B号中断来着,接着会去调取产生这个引脚中断的各种外设的中断判断函数,看看是哪一个发生了中断,然后去执行他的处理函数

外部设备1、外部设备n共享一个GPIO中断B,多个GPIO中断汇聚到GIC(通用中断控制器)的A号中断,GIC再去中断CPU。那么软件处理时就是反过来,先读取GIC获得中断号A,再细分出GPIO中断B,最后判断是哪一个外部芯片发生了中断。

所以,中断的处理函数来源有三:

① GIC的处理函数:

假设irq_descA.handle_irq是XXX_gpio_irq_handler(XXX指厂家),这个函数需要读取芯片的GPIO控制器,细分发生的是哪一个GPIO中断(假设是B),再去调用irq_descB. handle_irq。

注意:irq_descA.handle_irq细分出中断后B,调用对应的irq_descB.handle_irq。

显然中断A是CPU感受到的顶层的中断,GIC中断CPU时,CPU读取GIC状态得到中断A。

② 模块的中断处理函数:

比如对于GPIO模块向GIC发出的中断B,它的处理函数是irq_descB.handle_irq。

BSP开发人员会设置对应的处理函数,一般是handle_level_irq或handle_edge_irq,从名字上看是用来处理电平触发的中断、边沿触发的中断。

注意:导致GPIO中断B发生的原因很多,可能是外部设备1,可能是外部设备n,可能只是某一个设备,也可能是多个设备。所以irq_descB.handle_irq会调用某个链表里的函数,这些函数由外部设备提供。这些函数自行判断该中断是否自己产生,若是则处理。

③ 外部设备提供的处理函数:

这里说的"外部设备"可能是芯片,也可能总是简单的按键。它们的处理函数由自己驱动程序提供,这是最熟悉这个设备的"人":它知道如何判断设备是否发生了中断,如何处理中断。

对于共享中断,比如GPIO中断B,它的中断来源可能有多个,每个中断源对应一个中断处理函数。所以irq_descB中应该有一个链表,存放着多个中断源的处理函数。

一旦程序确定发生了GPIO中断B,那么就会从链表里把那些函数取出来,一一执行。

这个链表就是action链表。

对于我们举的这个例子来说,irq_desc数组如下:

irqaction 结构体

当调用request_irq、request_threaded_irq注册中断处理函数时,内核就会构造一个irqaction结构体。在里面保存name、dev_id等,最重要的是handler、thread_fn、thread。

handler是中断处理的上半部函数,用来处理紧急的事情。

thread_fn对应一个内核线程thread,当handler执行完毕,Linux内核会唤醒对应的内核线程。在内核线程里,会调用thread_fn函数。

可以提供handler而不提供thread_fn,就退化为一般的request_irq函数。

可以不提供handler只提供thread_fn,完全由内核线程来处理中断。

也可以既提供handler也提供thread_fn,这就是中断上半部、下半部。

里面还有一个名为sedondary的irqaction结构体,它的作用以后再分析。

在reqeust_irq时可以传入dev_id,为何需要dev_id?作用有2:

① 中断处理函数执行时,可以使用dev_id

② 卸载中断时要传入dev_id,这样才能在action链表中根据dev_id找到对应项

所以在共享中断中必须提供dev_id,非共享中断可以不提供。

下面来看看设备树跟这些数据结构的关系:

它就是个中转站,里面有irq_chip指针 irq_domain指针,都是指向别的结构体。

比较有意思的是irq、hwirq,irq是软件中断号,hwirq是硬件中断号。比如上面我们举的例子,在GPIO中断B是软件中断号,可以找到irq_descB这个数组项;GPIO里的第x号中断,这就是hwirq。

谁来建立irq、hwirq之间的联系呢?由irq_domain来建立。irq_domain会把本地的hwirq映射为全局的irq,什么意思?比如GPIO控制器里有第1号中断,UART模块里也有第1号中断,这两个"第1号中断"是不一样的,它们属于不同的"域"──irq_domain。

相关推荐
摇滚侠3 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 小时前
Linux 11 动态监控指令top
linux
小小工匠4 小时前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾4 小时前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
不会C语言的男孩5 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈5 小时前
Unix 与 Linux 异同小叙
linux·服务器·unix
Qres8216 小时前
算法复键——树状数组
数据结构·算法
凡人叶枫6 小时前
Effective C++ 条款42:了解 typename 的双重意义
java·linux·服务器·c++
2601_961875246 小时前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant