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_desc[A].handle_irq是XXX_gpio_irq_handler(XXX指厂家),这个函数需要读取芯片的GPIO控制器,细分发生的是哪一个GPIO中断(假设是B),再去调用irq_desc[B]. handle_irq。

注意:irq_desc[A].handle_irq细分出中断后B,调用对应的irq_desc[B].handle_irq。

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

② 模块的中断处理函数:

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

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

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

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

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

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

一旦程序确定发生了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_desc[B]这个数组项;GPIO里的第x号中断,这就是hwirq。

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

相关推荐
KoiHeng2 小时前
操作系统简要知识
linux·笔记
小汉堡编程3 小时前
数据结构——vector数组c++(超详细)
数据结构·c++
Johny_Zhao5 小时前
Docker + CentOS 部署 Zookeeper 集群 + Kubernetes Operator 自动化运维方案
linux·网络安全·docker·信息安全·zookeeper·kubernetes·云计算·系统运维
小毛驴8506 小时前
Linux 后台启动java jar 程序 nohup java -jar
java·linux·jar
雾里看山6 小时前
顺序表VS单链表VS带头双向循环链表
数据结构·链表
好好学习啊天天向上7 小时前
世上最全:ubuntu 上及天河超算上源码编译llvm遇到的坑,cmake,ninja完整过程
linux·运维·ubuntu·自动性能优化
tan180°8 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
典学长编程8 小时前
Linux操作系统从入门到精通!第二天(命令行)
linux·运维·chrome
wuk9988 小时前
基于MATLAB编制的锂离子电池伪二维模型
linux·windows·github
好好研究9 小时前
学习栈和队列的插入和删除操作
数据结构·学习