Linux驱动开发基础__ Linux中断系统中的重要数据结构

news2024/11/19 12:35:33

目录

1 整体概述

2  irq_desc 数组

3  irqaction 结构体

4 irq_data 结构体

5 irq_domain 结构体 

6  irq_chip 结构体


1 整体概述

该文章内容,可以从 request_irq(include/linux/interrupt.h)函数一路分析得到。 能弄清楚下面这个图,对 Linux 中断系统的掌握也基本到位了。

最核心的结构体是 irq_desc,之前为了易于理解,我们说在 Linux 内核中有一个中断数组,对于每一个硬件中断,都有一个数组项,这个数组就是irq_desc 数组。 
注意:如果内核配置了 CONFIG_SPARSE_IRQ,那么它就会用基数树(radix tree)来代替 irq_desc 数组。SPARSE 的意思是“稀疏”,假设大小为 1000 的数组中只用到 2 个数组项,那不是浪费嘛?所以在中断比较“稀疏”的情况下可以用基数树来代替数组。

2  irq_desc 数组

irq_desc 结构体在 include/linux/irqdesc.h 中定义,主要内容如下图: 

 每一个 irq_desc 数组项中都有一个函数:handle_irq,还有一个 action链表。要理解它们,需要先看中断结构图:

 外部设备 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 数组如下:

3  irqaction 结构体

irqaction 结构体在 include/linux/interrupt.h 中定义,主要内容如下图:

 

当调用 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,非共享中断可以不提供。

4 irq_data 结构体

irq_data 结构体在 include/linux/irq.h 中定义,主要内容如下图: 

 它就是个中转站,里面有 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。 

5 irq_domain 结构体 

irq_domain 结构体在 include/linux/irqdomain.h 中定义,主要内容如下图:

 当我们后面从设备树讲起,如何在设备树中指定中断,设备树的中断如何被转换为 irq 时,irq_domain 将会起到极大的作为。 
这里基于入门的解度简单讲讲,在设备树中你会看到这样的属性: 

interrupt-parent = <&gpio1>; 
interrupts = <5 IRQ_TYPE_EDGE_RISING>; 

它表示要使用 gpio1 里的第 5 号中断,hwirq 就是 5。 
但是我们在驱动中会使用 request_irq(irq, handler)这样的函数来注册中断,irq 是什么?它是软件中断号,它应该从“gpio1 的第 5 号中断”转换得来。 
谁把 hwirq 转换为 irq?由 gpio1 的相关数据结构,就是 gpio1 对应的irq_domain 结构体。 
irq_domain 结构体中有一个 irq_domain_ops 结构体,里面有各种操作函数,主要是: 

⚫  xlate :用来解析设备树的中断属性,提取出 hwirq、type 等信息。 
⚫  map :把 hwirq 转换为 irq。

 6  irq_chip 结构体

irq_chip 结构体在 include/linux/irq.h 中定义,主要内容如下图: 

 这个结构体跟“chip”即芯片相关,里面各成员的作用在头文件中也列得很清楚,摘录部分如下: 

* @irq_startup:  start up the interrupt (defaults to ->enable if NULL) 
* @irq_shutdown:  shut down the interrupt (defaults to ->disable if NULL) 
* @irq_enable:   enable the interrupt (defaults to chip->unmask if NULL) 
* @irq_disable:  disable the interrupt 
* @irq_ack:    start of a new interrupt 
* @irq_mask:    mask an interrupt source 
* @irq_mask_ack:  ack and mask an interrupt source 
* @irq_unmask:   unmask an interrupt source 
* @irq_eoi:    end of interrupt 

我们在 request_irq 后,并不需要手工去使能中断,原因就是系统调用对应的 irq_chip 里的函数帮我们使能了中断。 
我们提供的中断处理函数中,也不需要执行主芯片相关的清中断操作,也是系统帮我们调用 irq_chip 中的相关函数。 
但是对于外部设备相关的清中断操作,还是需要我们自己做的。就像上面图里的“外部设备 1“、“外部设备 n”,外设备千变万化,内核里可没有对应的清除中断操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Domino Nomad Web 1.0.6!

大家好&#xff0c;才是真的好。 虽然Domino Notes 9.0.x版本早前宣布从本月开始停止市场商业推广&#xff0c;并逐步停止技术支持服。但没让人意外的是&#xff0c;12月5号&#xff0c;HCL更新了一版Domino Notes 9.0.1版本的补丁程序FP10IF10&#xff1a; 没有任何额外的说…

车规级CAN FD收发器SIT1044Q,能替代TJA1044吗?

国际知名品牌NXP推出的TJA1042Q、TJA1043Q、TJA1044Q、TJA1051Q等CAN FD收发器芯片&#xff0c;相信很多电子工程师并不陌生。这类芯片应用中&#xff0c;非常成熟稳定&#xff0c;深受汽车电子工程师的认可、支持和青睐。然而&#xff0c;在实际应用中&#xff0c;很多客户由于…

新建文本文档

Spring Boot 加载外部配置文件 Spring Boot 允许你从外部加载配置&#xff0c;这样的话&#xff0c;就可以在不同的环境中使用相同的代码。支持的外部配置源包括&#xff1a;Java属性文件、YAML文件、环境变量、命令行参数。 用Value注解可以将属性值直接注入到beans中。命令行…

【win11环境编译安装deformable Detr的MultiScaleDeformableAttention模块】

Microsoft Visual C 14.0 is required.1.Compiling CUDA operators2.安装Build Tools for Visual Studio3.安装合适的cuda4.编译1.Compiling CUDA operators cd ./models/ops sh ./make.sh # unit test (should see all checking is True) python test.pyNote: win11 or win10…

经认定的闵行区企业技术中心给予10万元资助

闵行区企业技术中心一、主管部门闵行区经济委员会二、政策依据《闵行区关于推进先进制造业高质量发展的若干产业政策意见》&#xff08;闵府规发〔2020〕5号&#xff09;《闵行区企业技术中心认定管理办法》&#xff08;闵经委规发〔2021〕2号&#xff09;《关于申报认定2022年…

搭建Go环境 03

1、windows下搭建go环境 1、介绍SDK 1、SDK&#xff08;软件开发工具包&#xff09; 2、SDK是给开发人员使用的&#xff0c;其中包含了对应开发语言的工具包 2、下载SDK Go官方镜像站(国内用户推荐): https://golang.google.cn/dl/ 官网下载 https://golang.org/dl/ # 安装事项…

【参考答案】java基础练习:变量、数据类型、输入、输出、运算符

练习1&#xff1a;判断输入的值是否是偶数&#xff0c;另外&#xff0c;要处理输入错误 (目的&#xff1a;熟悉输入、输出&#xff0c;特别是Scanner对象的方法) package com.qzcsbj;import java.util.Scanner;public class Test {public static void main(String[] args) {Sca…

Hudi集成Spark(一)Spark Shell方式

文章目录环境准备安装 Spark启动 Hadoop&#xff08;略&#xff09;spark-shell 方式启动 spark-shell插入数据查询数据查询数据更新数据增量查询指定时间点查询删除数据覆盖数据环境准备 安装 Spark 1&#xff09;Hudi 支持的 Spark 版本 HudiSupported Spark 3 version0.1…

131页8万字数字化矿山整体解决方案

【版权声明】本资料来源网络&#xff0c;知识分享&#xff0c;仅供个人学习&#xff0c;请勿商用。 【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间删除&#xff01; 完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 目 录 1、煤矿综合自动化系统…

两台 mac 通过 scp 命令快速传输数据

这两天由于电脑进水了&#xff0c;所以申请换了一台 mac 电脑&#xff0c;所以想把老电脑的数据拷贝到新电脑&#xff0c;折腾了半天&#xff0c;最后还是发现 scp 命令最好用。 使用 「scp 命令方式」之前尝试的其他方法 1、隔空投送 刚开始使用那个隔空投送功能&#xff0c;但…

数据结构与算法(一)——时间复杂度和空间复杂度

时间复杂度 1、概念引入 先说结论&#xff1a;时间复杂度是用来估计算法运行时间的一个式子&#xff08;单位&#xff09;。 例如&#xff1a;这四组代码&#xff0c;哪组运行时间最短&#xff1f; q&#xff1a;我们该用什么方式来体现算法运行的快慢&#xff1f; a&#…

安卓apk包破解

安卓apk包破解前言一、前置工作二、正式开始前言 拿到安卓的apk包如何&#xff0c;如何破解呢。流程如下 一、前置工作 拿到一个apk文件&#xff0c;修改其后缀为zip 例如&#xff1a; test.apk > test.zip 使用解压工具进行解压。解压后如图 获取到原始文件目录&…

Django项目——通过APIView实现API访问,增删改查数据库

前提 该文章在已有项目的基础上进行修改 https://blog.csdn.net/qq_38122800/article/details/128583379?spm1001.2014.3001.5502 1、配置序列化器 序列化器包含序列化和反序列化两个过程,简单点理解就是 序列化 : 将从数据库中查的数据变为前端页面可以接受的json数据 反…

机器学习的逻辑回归(Logistic)的实例————预测学生是否被录取

目录要求代码1. 导入模块2. 导入数据3. 求解theat的最优值,画出样本的位置和决策边界。4. 画出迭代函数随迭代次数变化的曲线,代价函数最终的收敛值5.比较三种学习率的代价函数随迭代次数变化的曲线5.1 学习率为0.00035.2 学习率为0.00055.3 学习率为0.00001要求 代码 1. 导入…

PySpark和RDD对象详解

目录 一.了解Spark、PySpark Spark是什么 Python on Spark Pyspark 小结 二.构建PySpark执行环境入口对象 PySpark的编程模型 小结 三.RDD对象 python数据容器转RDD对象 注意 演示 读取文件转RDD对象 演示 一.了解Spark、PySpark Spark是什么 定义:Apache Spark是用…

计算机组成原理【2】

文章目录一 计算机系统的层次结构1.1 思维导图1.2 计算机机器的五个层次1.3 三种级别的语言1.4 区分计算机组成原理和计算机体系二 计算机性能指标2.1 思维导图2.2 主存储器性能指标2.3 CPU性能指标2.4 系统整体的性能指标2.5 系统整体性能指标【动态测试】三 进位计数制3.1 思…

springboot整合opencv进行灰度图像与RGB图像互转

问题&#xff1a; 在开发过程中遇到一个问题&#xff0c;需要在图片上加上数据&#xff08;原卷留痕&#xff09;&#xff0c;由于图片是灰度的&#xff0c;无法进行彩色编辑&#xff0c;需要将灰度图片转成RGB图片&#xff0c;才能进行彩色编辑&#xff0c;于是想到用opencv进…

Grafana 告警模块介绍

Grafana 系列文章&#xff0c;版本&#xff1a;OOS v9.3.1 Grafana 的介绍和安装Grafana监控大屏配置参数介绍&#xff08;一&#xff09;Grafana监控大屏配置参数介绍&#xff08;二&#xff09;Grafana监控大屏可视化图表Grafana 查询数据和转换数据Grafana 告警模块介绍 Gra…

Java对接JeePay支付、转账实现以及回调函数

最近公司对接了第三方支付平台JeePay&#xff0c;看到网上文章比较少&#xff0c;给大家发一篇对接微信支付的吧&#xff0c;支付宝也一样&#xff0c;更换里面的参数即可&#xff0c;官方文档地址&#xff1a;系统介绍 - 计全文档&#xff0c;具体的服务需要大家去搭建&#x…

为ABP新增手机验证模块

当前手机验证基本是标配&#xff0c;但Abp自身并没有实现这个功能&#xff0c;于是有了通过自定义模块实现的想法。 经过研究&#xff0c;发现要实现这个&#xff0c;只要重写和替换包含ReplaceEmailToUsernameOfInputIfNeeds方法的类就可以了。但要实现这个&#xff0c;首先要…