5.3中断系统中的设备树——中断号的演变与irq_domain

2023-11-03

通过上一节我们知道,在内核中有一个irq_desc数组,数组里面的每一项对应一个中断,数组的下标就是对应中断的虚拟中断号(virq)。

假设只有一个中断控制器,有32个中断,那么中断和irq_desc数组可以一一对应,每一个数组项对应一个中断。

因为第0项一般不用,所以是从第1项开始,一一对应。

此时虚拟中断号和硬件中断号的对应关系为:virq = hwirq + 1。

如果再加一个中断控制器sub_intc,它也会发出中断,并且sub_intc发出的中断会触发上一级的中断控制器的n号中断。

也就是说,sub_intc的0,1,2,3号中断,都会触发上一级中断控制器的n号中断。

根据上一节的说明,sub_intc的0,1,2,3号中断,在irq_desc数组中也会有对应的单独项和它们一一对应。

假设irq_desc数组项中的第36,37,38,39项,分别对应sub_intc的0,1,2,3号中断。

sub_intc的硬件中断号称为hwirq',那么就可以得到hwirq'和virq的转换公式。

virq = hwirq' + 36

也就是说,不论是intc还是sub_intc,都可以根据硬件中断号获得对应的虚拟中断号,并且这些中断号对应的数组项,并不重合

再增加一个外部中断控制器external intc,让系统更复杂一点。

与sub_intc类似,external intc对应intc的m号中断,我们让external intc的0号中断对应数组项的第48项。

那么,也可以得到一个硬件中断号和虚拟中断之间的转换公式:virq = hwirq'' + 48。

以前, 对于每一个硬件中断(hwirq)都预先确定它的中断号(virq),这些中断号一般都写在一个头文件里, 比如:arch\arm\mach-s3c24xx\include\mach\irqs.h。

这里的每一个宏,就是一个虚拟中断号。

使用时:

  1. 执行 request_irq(virq, my_handler) :内核根据virq可以知道对应的硬件中断号,然后去设置、使能中断等;
  2. 发生硬件中断时,内核读取硬件信息,确定hwirq,反算出virq,然后调用 irq_desc[virq].handle_irq,最终会用到 my_handler;

问:前面说了三个中断控制器,intc,sub_intc,external intc,在这三个中断控制器中,不同的硬件中断号对应的虚拟中断号是不同。

但是,intc,sub_intc,external intc都有各自的0号,1号中断等,内核怎么根据这些硬件中断号,推算出对应的虚拟中断号?

答:需要引入了一个新的概念——域(irq_domain),intc,sub_intc,external intc分别有自己的域(irq_domain)。

不同的域(irq_domain)中,相同的硬件中断号(hwirq)对应的虚拟中断号(virq)是不同的

所以,在描述hwirq时,应该注意“是哪个域的hwirq”。

那么,怎么使用域将硬件中断号,转化为虚拟中断号?稍后再说。

之前,virq和硬件的对应关系是固定的,比如virq 38固定对应串口3的接收中断,virq 56固定对应GPIO外部中断等。

但现在的趋势是,virq跟硬件无关,仅仅是一个标号(中断描述数组的标号)而已。

问:为什么会变成这样呢?

答:如果只有几个中断,那么可以事先确定好中断号,并且只要几个宏就可以让中断和数组项一一对应。

但是如果有成百上千个中断,就需要成百上千个宏,并且这些数组项要各自独立互不影响,工作量就变得多得多。(想想要定义上千个宏,很恐怖的。。。)

为了避免这种复杂的情况,就将硬件中断号和虚拟中断号之间固定的关系取消掉它们依旧是一一对应,但是对应关系不再固定了

当需要使用某个硬件中断(hwirq)时,来查找irq_desc数组,在数组中查找到一个空余项,这个空余项的下标就是这个硬件中断号对应的virq

我们在这个空余项中存放对应的处理函数就可以了。

假设,要使用inc的INT2。

那么,先要在 irq_desc 数组中,找到一个空余项。

问:怎么查找空余项呢?

答:最笨的方法,就是从下标0开始依次查找。这当然也是一种方法,但是效率可能不好,这种方法的时间复杂度应该是O(n)。

内核使用的是另一种方法。在内核中定义了一个位图,用来记录哪些空余项被使用了。

这个位图其实就是一个数组——allocated_irqs

allocated_irqs的bit0对应下标0,bitn对应下标n。当某一位等于1时,表示这一项被占用了。

那么,比如硬件ID为2,那么就从bit2开始,bit2,bit3依次查找,直到找到空余项。

这样做的效率应该是比从左到右一个一个找要快。

假设,要设置2号中断,并且allocated_irqs的bit2为0,那么它的virq就等于2。

问:以后处理2号中断时,我们可以从中断控制器里面获得hwirq为2,但是怎么知道对应的virq呢?

答:这就需要在设置中断时,将中断的virq保存下来了。

事实上,这个virq保存在对应的irq_domain里面。

@linear_revmap: Linear table of hwirq->virq reverse mappings
struct irq_domain {
	......

	unsigned int linear_revmap[];
};

irq_domain里面有一个数组linear_revmap,叫做反向映射数组

为什么叫反向映射数组呢?

以前,我们使用中断时,是在驱动程序里面执行 request_irq,通过virq找到对应的hwirq。

现在呢,反过来,使用hwirq找到virq。

把hwirq对应的virq,保存在对应的irq_domainlinear_revmap数组中,也就是 linear_revmap[hwirq] = virq

对于本例,hwirq=2,virq=2,所以就是linear_revmap[2] = 2。

这样,后续发生2号中断时:

  1. 首先根据中断向量进入到指定地址执行中断处理流程,将会调用到C语言的中断处理函数
  2. 然后,在中断处理函数中读取中断控制器,得到硬件中断号
  3. 之后,再根据这个中断控制器,得到对应的irq_domain
  4. 通过irq_domain的linear_revmap数组以及硬件中断号,就可以得到一个virq
  5. 最后,在irq_desc数组中,根据virq,找到对应的那一项,把其中的handle_irq拿出来执行。

假设要使用子中断控制器(subintc)的n号中断, 它发生时会导致父中断控制器(intc)的m号中断:

  1. 设备树表明要使用<subintc n>,subintc表示要使用<intc m>
  2. 解析设备树时,会为<subintc n>找到空闲项 irq_desc[virq'],
    sub irq_domain.linear_revmap[n] = virq';
    会为<intc m>   找到空闲项 irq_desc[virq],
    irq_domain.linear_revmap[m] = virq;
    并且设置它的handle_irq为某个分析函数demux_func
  3. 设置驱动程序 request_irq(virq', my_handler);
  4. 发生硬件中断时,内核读取intc硬件信息, 确定hwirq = m, 确定 virq =  irq_domain.linear_revmap[m];
    然后调用 irq_desc[m].handle_irq, 即demux_func
  5. demux_func:读取sub intc硬件信息, 确定hwirq = n, 确定 virq' =  sub irq_domain.linear_revmap[n];
  6. 然后调用 irq_desc[n].handle_irq, 即my_handler。

在旧的中断配置方法中,irq_domain也有linear_revmap成员,只是它的linear_revmap数组都预先设置好了,只有新的中断配置方法中,linear_revmap才是设置了才不为空(0)。

也就是说,新旧配置方法是兼容的,只是配置方法略有不同

旧的配置方法是通过固定配置,可以直接通过 request_irq 函数配置中断(因为virq是已知的,固定的),而新的配置方法在一开始并不知道virq,需要先在设备树表明要使用哪个中断(hwirq),然后程序会将这个hwirq和某个virq绑定,确定virq后,才可以调用request_irq函数设置中断。

那么,要怎么在设备树中表明要使用哪个中断?这个下节再说明。

在设备树中表明要使用的中断信息后,会通过xlate函数对设备树进行解析,获得对应的hwirqirq_type中断触发方法)。

然后,再把hwirq映射得到virq,之后驱动程序才能来设置和使用中断。

还有一个map函数,用来建立hwirq和virq之间的映射关系的,比如,若配置的是子中断,那么map函数还要去设置父中断。

xlatemap都是irq_domain.ops的成员,他们都是函数指针。

struct irq_domain {
    ......
	const struct irq_domain_ops *ops;
    ......
};

struct irq_domain_ops {
	int (*match)(struct irq_domain *d, struct device_node *node,
		     enum irq_domain_bus_token bus_token);
	int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec,
		      enum irq_domain_bus_token bus_token);
	int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
	void (*unmap)(struct irq_domain *d, unsigned int virq);
	int (*xlate)(struct irq_domain *d, struct device_node *node,
		     const u32 *intspec, unsigned int intsize,
		     unsigned long *out_hwirq, unsigned int *out_type);
#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
	/* extended V2 interfaces to support hierarchy irq_domains */
	int (*alloc)(struct irq_domain *d, unsigned int virq,
		     unsigned int nr_irqs, void *arg);
	void (*free)(struct irq_domain *d, unsigned int virq,
		     unsigned int nr_irqs);
	int (*activate)(struct irq_domain *d, struct irq_data *irqd, bool reserve);
	void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
	int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
			 unsigned long *out_hwirq, unsigned int *out_type);
#endif
#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
	void (*debug_show)(struct seq_file *m, struct irq_domain *d,
			   struct irq_data *irqd, int ind);
#endif
};

关于 xlate map 的更详细的说明,会在后面的文章中说明。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

5.3中断系统中的设备树——中断号的演变与irq_domain 的相关文章

  • linux用户态使用gpio中断方法

    一 用户空间gpio的调用文件 用户空间访问gpio 即通过sysfs接口访问gpio 下面是 sys class gpio目录下的三种文件 export unexport文件 gpioN指代具体的gpio引脚 gpio chipN指代gp
  • 单片机:按键(使用中断)控制数码管的数字加减(c语言实现)

    本实验的目的 使用中断实现通过编号为8和C的按键控制数码管数字的加减 加至15之后再循环到0 减到0之后保持0不变 include
  • linux内核中断(一)

    一 中断简介 中断是指 CPU 在执行程序的过程中 出现了某些突发事件急待处理 CPU 必须暂停当前程序的执行 转去处理突发事件 处理完毕后又返回原程序被中断的位置继续执行 由于中断的存在极大的提高了 CPU 的运行效率 但是设备的中断会打
  • linux中断实验

    文章目录 一 linux中断简介 1 linux中断API函数 1 中断号 2 request irq函数 3 free irq 4 中断处理函数 5 中断使能与禁止函数 2 上半部与下半部 1 软中断 2 tasklet 3 工作队列 3
  • 全志A64触摸屏驱动调试

    一 前言 linux的触摸屏驱动一般要经历一下几个步骤 以4412为例 1 移植驱动到linux源码 driver input touchscreen 目录下 在Kconfig里面增加这款触摸屏驱动的菜单 add by long 20170
  • FreeRTOS入门(05):事件组

    文章目录 目的 基础说明 相关函数 使用演示 总结 目的 事件组是RTOS中相对常用的用于任务间交互的功能 这篇文章将对相关内容做个介绍 本文代码测试环境见前面的文章 FreeRTOS入门 01 基础说明与使用演示 基础说明 事件组 Eve
  • 2.2设备树的规范(dts和dtb)——DTB格式

    本节讲述设备树的dtb格式 上节讲述了dts格式 回顾上节 在dts文件和dtsi文件中 可以使用C语言的define和include 使用方法和作用也同C语言相同 编写dts文件后 需要使用dtc工具将dts文件编译成dtb文件 dtc工
  • Linux中断原理、上半部和下半部、硬中断和软中断

    目录 1 中断简介 1 1 作用 1 2 物理实现 1 3 中断请求线IRQ 1 4 异常 2 中断处理程序 2 1 作用 2 2 上半部和下半部 2 3 中断上下文 3 中断系统 3 1 中断机制的实现 3 2 中断控制 4 下半部和软中
  • 15、STM32 中断应用概览

    15 STM32 中断应用概览 文章目录 15 STM32 中断应用概览 1 异常类型 2 NVIC 简介 2 1 NVIC寄存器简介 2 2 NVIC 中断配置固件库 3 优先级的定义 3 1 优先级定义 3 2 优先级分组 4 中断编程
  • 新唐NUC980使用记录(5.10.y内核):在用户应用中使用GPIO

    文章目录 目的 使用参考与演示 使用参考 存在的问题 问题定位 修改设备树 使用测试 总结 设备树文件内容 目的 GPIO是最基础的外设 使用频率也非常高 这篇文章将简单体验在NUC980 Liunx用户应用中使用GPIO功能 这篇文章中内
  • STM32通用定时器(原理、结构体、库函数、定时器中断每秒闪烁一次灯) —— 时钟源、分频值、重装载值

    参考 stm32定时器与定时器中断 作者 打酱油的 发布时间 2021 04 11 01 04 09 网址 https blog csdn net weixin 46098612 article details 115493737 参考 s
  • 5.3中断系统中的设备树——中断号的演变与irq_domain

    通过上一节我们知道 在内核中有一个irq desc数组 数组里面的每一项对应一个中断 数组的下标就是对应中断的虚拟中断号 virq 假设只有一个中断控制器 有32个中断 那么中断和irq desc数组可以一一对应 每一个数组项对应一个中断
  • 51单片机中断系统的原理和运用

    QX MCS51开发板上使用的是DIP封装 双列直插式 有40只引脚 40只引脚按其功能来分 有三类 一 电源和时钟引脚 Vcc Vss XTAL1 XTAL2 电源引脚接入单片机工作电源 Vcc 40脚 接 5V电源 Vss 20脚 接地
  • 快速查找Unity死循环

    我们先建立一个新工程 新建C 文件 然后在Start函数中加入以下代码 void Start while true int i 1 把这个C 文件挂到场景摄像机或其它GameObject上 打开这个工程对应的VS工程 如何用VS编辑unit
  • 【学习记录】STM32利用定时器中断实现定时闪烁指示灯

    任务 定时闪烁指示灯 任务目标 掌握 CubeMX 软件配置定时器实现定时功能的方法 任务内容 控制开发板上的指示灯LED每隔1s闪烁 任务实现 使用的STM32芯片是STM32F407ZET6 第一步 设置高速时钟 设置LED 第二步 配
  • 嵌入式中锁机制杂谈

    在之前的文章中有提到操作系统中锁机制一般依赖于硬件CPU提供的原子数据操作指令 如SWP TEST AND SET等原子原语实现 基于此 才能真正保证锁机制的有效实现 通过上面原子操作 我们比较容易实现所谓的自旋操作 原子性的原地循环判断条
  • Linux内核中断之获取中断号

    目录 一 调用流程 二 应用举例 1 查找中断号 2 dts配置 3 驱动函数 Linux内核中可使用platform get irq 函数获取dts文件中设置的中断号 函数原型 int platform get irq struct pl
  • 8259初始化命令字(ICW1-ICW4)

    8259A的中断操作功能很强 包括中断的请求 屏蔽 排队 结束 级联以及提供中断类型号和查询等操作 并且其操作的方式又有不同 它既能实现向量中断 又能进行中断查询 它可以用于16位机 也可用于8位机 因此 使用起来感到复杂且不好掌握 为此
  • spi总线挂载多个设备的设备树描述

    内核版本 linux4 6 Vivado版本 201602 工程中用到很多spi控制的从设备 首先对FPGA工程的正确性验证一下 验证的设备树描述如下 spi e0006000 compatible xlnx zynq spi r1p6 r
  • STM32中断标志:先清理后清理的区别

    先上总结 再闲聊爬坑过程 进入中断函数后 先清理中断标志 再执行其它动作 爬坑过程 各种教程中 都只解释中断的机制 使用 但对于中断标志的清理顺序 没多少官方准确的资料 今天在F429的代码里 又遇到问题 进中断后卡死跳不出来 各种排查没发

随机推荐

  • 【Android】BottomNavigationView+ViewPager实现底部导航栏(步骤+源码)

    吐糟大会 时隔好久再一次在博客上与大家见面 上一年九月份怀疑自己不适合这行毅然辞职 我没结婚没车贷没房贷本以为能很潇洒 但现实给我开了个玩笑 我发现除了这一行其他什么都不会 也许是我很懒吧 为了能吃饱饭我再次踏入这一行 回归初衷为了让更多刚
  • RDF与可视化

    Rudolf RDFViz Exploring tools for RDF Graph Visualisation http www ilrt bris ac uk discovery rdf dev rudolf rdfviz To vi
  • Win10系统无法打开chm文档提示无法显示该页面怎么办?

    网上下载了一个chm文档 但打开后发现无法显示该页 提示 确保 Web 地址 ieframe dll dnserrordiagoff htm 正确 通过查找相关资料 迅速了解决该问题 特此分享 一 CHM文档定义 CHM Compiled
  • 查看电脑CPU是否支持虚拟化

    有两次方法 使用securable 可以在一下地址下载https www grc com files securable exe 安装双击就会出现如图 32 64 就是表示电脑的位数 D E P 表示的是硬件 Virtualization表
  • VSCode 下python输出中文乱码问题

    在处理这个问题之前 你首先得知道为什么会出现这个这个问题 你在使用VScode编辑代码时 代码页面中文正常 而终端输出那里中文却为乱码 出现这个现象的原因是因为编码方式的不同 VScode的默认编码方式为UTF 8 中国地区下cmd的编码方
  • github下载的项目如何build--如何利用configure.ac和Makefile.am,生成Makefile。

    环境是Ubuntu18 04 1 aclocal命令根据configure ac文件的内容 自动生成aclocal m4文件 2 autoconf命令会根据configure ac和aclocal m4文件 生成configure文件 3
  • 基于 Flutter+Dart 聊天实例

    1 项目介绍 Flutter是目前比较流行的跨平台开发技术 凭借其出色的性能获得很多前端技术爱好者的关注 比如阿里闲鱼 美团 腾讯等大公司都有投入相关案例生产使用 flutter chatroom项目是基于Flutter Dart chew
  • TortoiseGit 入门指南11:还原与重置

    Git 就像个时光机器 能让我们还原到任何提交 还原未提交的更改 假如我们在查看一个干净的代码仓库 干净意味着工作区中的文件保持着最后一次提交的状态 没有修改 在查看的过程中 我们有意或无意的修改了工作区中的文件 之后我们想把这些文件恢复成
  • STLINK-V3 STDC14座转2.54mm排针转接板Kicad工程

    简介 这是一个 STLINK V3 STDC14座转2 54mm排针转接板Kicad工程 STDC14座实际工作中不太方便 所以搞了这个转接板 另外转接版上提供了可选的电源输出功能 An adapter board for STLINK V
  • EMC测试仪器_EMC测试整改流程及常见问题

    EMC主要是通过测试产品在电磁方面的干扰大小和抗干扰能力的综合评定 是产品在质量安全认证重要的指标之一 很多产品在做产品安全认证时都会遇到产品测试不合格的情况 尤其是在电磁兼容测试 即EMC测试 出错频率更是普遍 当产品一旦测试不合格 那么
  • J-002 Jetson电路设计之电源设计--NANO && XAVIER NX

    Jetson电源设计 1 电源说明 1 1 电源和系统引脚描述 1 2 电源控制框图详情 2 上电的时许 2 1 框图分析 2 2 上电时序 3 GND引脚 1 电源说明 Jetson NANO和XAVIER NX核心板的电源为DC 5V
  • 白盒测试之静态检查

    态检查一般是检查编码标准规范 错误列表 编码规范往往团队 会根据自己的经验和风格进行设置一些规范 现在很多IDE工具都会 在编辑代码的时候实时的提醒是否符合代码风格 错误列表 一般 是代码潜在的bug 由于某种代码写法虽然没有语法错误 但是
  • 现在有多个异步操作ajax请求,我们需要当所有异步请求都成功的时候,执行后续操作

    1 场景 现在有多个异步操作ajax请求 我们需要当所有异步请求都成功的时候 执行后续操作 2 方法 方法一 通常的讲 我们可以设置一个flag变量 然后在各自的ajax的成功回调内去维护这个变量数量 当满足条件时 我们来触发后续函数 方法
  • stat函数(stat、fstat、lstat)

    include
  • 基于STM32的录音与播音

    基于STM32的录音与播音 设计方案 本设计通过STM32的内置ADC加一个麦克风和放大电路 可以在网上买模块 实现音频的采集 然后存放在SD卡中 这里可以参考我之前的博客FATFS文件系统 然后再读取SD卡里存放的数据通过单片机的内置DA
  • [WPF]WPF Data Virtualization和UI Virtualization

    这篇博客将介绍WPF中的虚拟化技术 1 Data Virtualization 通常情况下我们说数据虚拟化是指数据源没有完全加载 仅加载当前需要显示的数据呈现给用户 这种场景会让我们想到数据分页显示 当需要特定页面的数据时 根据页数请求相应
  • noip2013提高组初赛(答案+选择题题目+个人分析)

    一 单项选择题 共 15 题 每题 1 5 分 共计 22 5 分 每题有且仅有一个正确 选项 1 一个 32 位整型变量占用 个字节 A 4 B 8 C 32 D 128 A 1字节 8位 1byte 8bit 2 二进制数 11 01
  • Linux 搜索文件和文件夹的 4 种简单方法

    英文 Prakash Subramanian 翻译 Linux中国 geekpi linux cn article 10362 1 html Linux 管理员一天都不能离开搜索文件 因为这是他们的日常活动 了解一些搜索的东西是不错的 因为
  • jquery的ajax数据显示不出来,jQuery的Ajax请求确实在HTML元素不显示数据

    当我运行在循环Ajax请求 成功AJAX不显示返回的数据 这里是代码 jQuery的Ajax请求确实在HTML元素不显示数据 url siteAdmin statistics queriesAjax php siteAdmin statis
  • 5.3中断系统中的设备树——中断号的演变与irq_domain

    通过上一节我们知道 在内核中有一个irq desc数组 数组里面的每一项对应一个中断 数组的下标就是对应中断的虚拟中断号 virq 假设只有一个中断控制器 有32个中断 那么中断和irq desc数组可以一一对应 每一个数组项对应一个中断