INTx中断机制源码分析

news2025/6/9 4:03:50

INTx中断机制源码分析


文章目录

  • INTx中断机制源码分析
  • 参考资料:
    • 一、 配置空间
    • 二、 扫描设备时分配中断号
    • 三、 使用INTx中断
    • 四、 PCIe中断树
    • 五、 PCIe INTx中断映射过程
      • 5.1 PCIe控制器支持的中断
      • 5.2 PCIe控制器注册中断
      • 5.3 PCIe设备中断号的分配
        • 5.3.1 IRQ domain
        • 5.3.2 得到PCIe设备的中断号
  • 致谢


参考资料:

  • 《PCI_SPEV_V3_0.pdf》6.8节
  • 《devicetree-specification-v0.2.pdf》

开发板资料:

  • 开发板Firefly-rk3399资料

本课程分析的文件:

  • linux-4.4_rk3399\drivers\pci\host\pcie-rockchip.c


一、 配置空间

无论是PCI设备还是PCIe设备,它们都可以在配置空间里声明:通过INTA#、INTB#、INTC#还是INTD#发出中断。

在这里插入图片描述
配置空间有2个寄存器:Interrupt Pin、Interrupt Line,作用如下:

  • Interrupt Pin:用来表示本设备通过哪条引脚发出中断信号,取值如下

    Interrupt Pin取值含义
    0不需要中断引脚
    1通过INTA#发出中断
    2通过INTB#发出中断
    3通过INTC#发出中断
    4通过INTD#发出中断
    5~0xff保留
  • Interrupt Line:给软件使用的,PCI设备本身不使用该寄存器。软件可以写入中断相关的信息,比如在Linux系统中,可以把分配的virq(虚拟中断号)写入此寄存器。软件完全可以自己记录中断信息,没必要依赖这个寄存器。

二、 扫描设备时分配中断号

PCIe设备在硬件信息里表明自己可以发出哪个中断,比如INTA、INTB、INTC或INTD,这个中断要转换为中断号,我们编写的软件才可以为它注册中断处理函数。

怎么得到中断号?下面只列出调用过程,后面再分析:

rockchip_pcie_probe
    bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
		pci_scan_root_bus_msi
            pci_scan_child_bus
            	pci_scan_slot
            		dev = pci_scan_single_device(bus, devfn);
						dev = pci_scan_device(bus, devfn);
							struct pci_dev *dev;
							dev = pci_alloc_dev(bus);
							pci_setup_device
                                pci_read_bases(dev, 6, PCI_ROM_ADDRESS);	
                        pci_device_add(dev, bus);
                        	pcibios_add_device(struct pci_dev *dev)
                        		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);

解析出中断信息后,分配的中断号放在pci_dev的irq里面:

pci_scan_single_device
    pci_device_add
    	pcibios_add_device(struct pci_dev *dev)
    		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);

三、 使用INTx中断

每个PCIe设备,在Linux内核里都对应一个pci_dev结构体:
在这里插入图片描述可以为这个设备注册中断:

request_irq(pci_dev->irq, ....);

四、 PCIe中断树

要分析PCIe设备中断号的分配过程,需要从RK3399的芯片资料开始学习。

层级结构为:PCIe设备 => PCIe控制器 => GIC =>CPU
在这里插入图片描述在设备树中:

       gic: interrupt-controller@fee00000 {
                compatible = "arm,gic-v3";
                #interrupt-cells = <4>;
                #address-cells = <2>;
                #size-cells = <2>;
                ranges;
                interrupt-controller;
                /* 省略 */
		};

       pcie0: pcie@f8000000 {
                compatible = "rockchip,rk3399-pcie";
                #address-cells = <3>;
                #size-cells = <2>;
                aspm-no-l0s;
                clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
                         <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
                clock-names = "aclk", "aclk-perf",
                              "hclk", "pm";
                bus-range = <0x0 0x1f>;
                max-link-speed = <1>;
                linux,pci-domain = <0>;
                msi-map = <0x0 &its 0x0 0x1000>;
                interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
                             <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
                             <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
                interrupt-names = "sys", "legacy", "client";
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 7>;
                interrupt-map = <0 0 0 1 &pcie0_intc 0>,
                                <0 0 0 2 &pcie0_intc 1>,
                                <0 0 0 3 &pcie0_intc 2>,
                                <0 0 0 4 &pcie0_intc 3>;
	};

发出中断的过程:

  • 任何一个PCIe设备向PCIe控制器发出"Assert INTx"(x=A/B/C/D)这类TLP包
  • PCIe控制器就会向GIC发出第50号SPI中断
  • GIC再给CPU发出中断。

中断的处理过程是反过来的:

  • CPU接收到中断,跳转到异常向量表处理代码,会调用GIC驱动
  • GIC:读取寄存器,得知发生的是SPI 50号中断,这个中断函数由PCIe控制器驱动提供
  • PCIe控制器:读取PCIe控制器的寄存器,分辨是INTA还是INTB、INTC、INTD,调用对应函数,这个函数由PCIe设备驱动程序提供
  • PCI设备:提供设备相关的驱动程序

五、 PCIe INTx中断映射过程

文件:drivers\pci\host\pcie-rockchip.c

5.1 PCIe控制器支持的中断

对于RK3399,PCIe控制器可以向GIC发出3个中断:sys、legacy、client:

  • sys:下图中Event ID为81,就是SPI 49号中断(81=32+49),用来处理一些系统性的中断,比如电源状态、热拔插
  • legacy:用来处理PCIe设备发来的INTA/INTB/INTC/INTD中断
  • client:跟外接的PCIe设备通信时,可能会发送传输错误,用这个中断来处理

在这里插入图片描述在设备树中,这3类中断如下定义:

       pcie0: pcie@f8000000 {
       			/* 省略 */
                interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
                             <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
                             <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
                interrupt-names = "sys", "legacy", "client";

5.2 PCIe控制器注册中断

在这里插入图片描述为什么legacy中断的函数,不是使用devm_request_irq而是使用irq_set_chained_handler_and_data?

因为发生legacy中断时,rockchip_pcie_legacy_int_handler函数要进一步分辨发生的是INTA还是INTB、INTC、INTD中断,然后处理。

5.3 PCIe设备中断号的分配

5.3.1 IRQ domain

在设备树里,PCIe控制器的节点里有一个更下一级的中断控制器,这是一个虚拟的中断控制器:

          pcie0: pcie@f8000000 {
          		#address-cells = <3>;
          		#interrupt-cells = <1>;
          		
               	interrupt-map-mask = <0 0 0 7>;
                interrupt-map = <0 0 0 1 &pcie0_intc 0>,
                                <0 0 0 2 &pcie0_intc 1>,
                                <0 0 0 3 &pcie0_intc 2>,
                                <0 0 0 4 &pcie0_intc 3>;
          
                pcie0_intc: interrupt-controller {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <1>;
                };                    
          };

在代码里,对于pcie0_intc会创建出一个IRQ domain:
在这里插入图片描述在设备树的interrupt-map里面就用到了这个子节点,也就是用到了对应的IRQ domain:

               	interrupt-map-mask = <0 0 0 7>;
                interrupt-map = <0 0 0 1 &pcie0_intc 0>,
                                <0 0 0 2 &pcie0_intc 1>,
                                <0 0 0 3 &pcie0_intc 2>,
                                <0 0 0 4 &pcie0_intc 3>;

5.3.2 得到PCIe设备的中断号

从PCIe设备得到的硬件中断信息,将会映射得到pcie0_intc,从它里面得到中断号。

这会涉及interrupt-map-maskinterrupt-map,比较复杂,在视频里讲解。

pci_scan_single_device
    pci_device_add
    	pcibios_add_device(struct pci_dev *dev)
    		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);

of_irq_parse_and_map_pci
	ret = of_irq_parse_pci(dev, &oirq);
				rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);

                out_irq->np = ppnode;
                out_irq->args_count = 1;
                out_irq->args[0] = pin;
                laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
                laddr[1] = laddr[2] = cpu_to_be32(0);
                rc = of_irq_parse_raw(laddr, out_irq);				
	
	return irq_create_of_mapping(&oirq);


致谢

以上笔记源自韦东山老师的视频课程,感谢韦老师,韦老师是嵌入式培训界一股清流,为嵌入式linux开发点起的星星之火,也愿韦老师桃李满园。聚是一团火,散是满天星!

在这样一个速食的时代,坚持做自己,慢下来,潜心琢磨,心怀敬畏,领悟知识,才能向下扎到根,向上捅破天,背着世界往前行!
仅此向嵌入行业里的每一个认真做技术的从业者致敬



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

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

相关文章

Java源码程序设计-房屋出租管理系统设计与实现

摘 要系统设计系统实现开发环境摘 要 随着我国市场经济的快速发展和人们生活水平的不断提高&#xff0c;简单的房屋出租服务已经不能满足人们的需求。如何利用先进的管理手段&#xff0c;提高房屋出租的管理水平&#xff0c;是当今社会所面临的一个重要课题。 本文采用结构化…

Win10系统电脑开机后总是蓝屏无法使用怎么办?

Win10系统电脑开机后总是蓝屏无法使用怎么办&#xff1f;电脑开机的时候出现了蓝屏问题&#xff0c;这个情况是我们的电脑系统不兼容导致的。遇到这个问题一般是需要去进行系统的重装来解决&#xff0c;安装一个更兼容的系统就可以解决问题了。一起来看看详细的解决方法分享吧。…

前端学习第八站——CSS定位和装饰

目录 一、定位 1.1 网页常见布局方式 1.2 定位的常见应用场景 2.1 定位初体验 2.2 使用定位 3.1 静态定位 4.1 相对定位 5.1 绝对定位 6.1 子绝父相 7. 固定定位 8.1 定位的层级关系 8.2 更改定位元素的层级 9.总结 二、装饰 1.1 了解基线 1.2 文字对齐问…

安卓小游戏:小板弹球

安卓小游戏&#xff1a;小板弹球 前言 这个是通过自定义View实现小游戏的第三篇&#xff0c;是小时候玩的那种五块钱的游戏机上的&#xff0c;和俄罗斯方块很像&#xff0c;小时候觉得很有意思&#xff0c;就模仿了一下。 需求 这里的逻辑就是板能把球弹起来&#xff0c;球…

股票交易开放接口是什么意思?

在股票量化市场上&#xff0c;大家可能对股票交易开放接口的意思不太理解&#xff0c;其实换个角度来看&#xff0c;就是关于由开发团队进行开发的股票交易开放接口&#xff0c;那么对于接口的开发原理跟代码是怎么样的呢&#xff1f;一、股票交易开放接口函数的调用&#xff1…

面试的同学看这里!这套Java面试八股文,已经帮助200+人进入大厂

在看这篇文章之前&#xff0c;我想我们需要先搞明白八股文是什么&#xff1f;&#xff1f;&#xff1f; 明清科举考试的一种文体&#xff0c;也称制义、制艺、时文、八比文。八股文章就四书五经取题&#xff0c;内容必须用古人的语气&#xff0c;绝对不允许自由发挥&#xff0c…

Git 常用命令

一、基本的git命令 1、查看现在在哪个分支 git branch 2、切换到某分支 git checkout 某分支 3、添加修改后的代码到缓存区 git add . 4、添加提交代码的备注 git commit -m "注释" 5、提交代码到指定的分支 git push origin 某分支 6、从远程仓库克隆git仓库…

四 、QML常用控件的使用详解

在Qt Quick的世界里&#xff0c;window对象用于创建一个与操作系统相关的顶层窗口&#xff0c;而其他的元素&#xff0c;如Text Rectangle,Image等&#xff0c;都睡Windows提功能场景里面的显示对象&#xff0c;Window还有一个派生类&#xff0c;即是大名鼎鼎的Application Win…

基于DSP+FPGA高速运动控制器设计

基于“PC运动控制器”结构的开放式机器人运动控制系统能够充分利用PC开放程 度高、通用性好、处理能力强等特点以及运动控制器运算速度快、实时性能好、控制能 力强等特点&#xff0c;因此得到较快发展&#xff0c;成为目前的研究热点。但目前采用此种结构的开放式 机器人运动控…

3D模型深度生成网络【ShapeAssembly】

推荐&#xff1a;使用 NSDT场景设计器 快速搭建 3D场景。 我们提出了一个深度生成模型&#xff0c;该模型学习在ShapeAssembly中编写新颖的程序&#xff0c;ShapeAssembly是一种用于建模3D形状结构的特定领域语言。 执行 ShapeAssembly 程序会生成一个由部件代理长方体的分层连…

HashMap put() 方法源码分析

文章目录一、前置知识红黑树定义二、构造方法HashMap()HashMap(int initialCapacity, float loadFactor)tableSizeFor(int cap)&#xff1a;计算hashmap初始容量三、put 方法源码1. put()hash(Object key)&#xff1a;计算key的hash值2. putVal()通过 hash 计算数组下标3. resi…

jdk版本切换工具jenv使用指南

1.下载jenv包 下载链接&#xff1a;GitHub - FelixSelter/JEnv-for-Windows: Change your current Java version with one line 下载包的文件&#xff1a;JEnv.zip 然后解压缩&#xff0c;放到一个目录下&#xff0c;我这里放到了目录&#xff1a;D:\tools\JEnv 2.将JENV添…

chatGPT学习

最近看到一个火爆的AI智能聊天工具&#xff1a;ChatGPT。它的功能&#xff1a;文能写文章&#xff0c;武能改BUG&#xff0c;马斯克对它的评价是“Scary Good!”。我非常感兴趣&#xff0c;就试用了一下&#xff0c;感觉还不错&#xff0c;希望大家能喜欢。 ChatGPT&#xff0…

炼石完成近亿元A+轮融资,冲刺1500亿数据安全赛道

近日&#xff0c;炼石宣布完成近亿元A轮融资&#xff0c;本轮融资由重庆科技成果转化基金独家投资&#xff0c;由清科资本担任独家财务顾问&#xff0c;这是继安天科技、安云资本、国科嘉和、腾讯等多轮之后的新一轮投资。随着本轮资金的引入&#xff0c;炼石将更深入研发迭代以…

MASA Stack 1.0 发布会讲稿 —— 产品篇

架构 基于MASA的云原生技术架构 我们基于MASA去做了一个云原生技术架构&#xff0c;左下角的MASA Blazor主要是为我们去集成一个多端的UI能力&#xff0c;具体的使用场景将在实践篇为大家介绍——MASA Blazor如何去做多端的 接着就是集成非业务能力的MASA Framework&#xff…

1.Docker 简介

Docker 简介 什么是 Docker&#xff1f; Docker的英文翻译是“搬运工”的意思&#xff0c;他搬运的东西就是我们常说的集装箱Container&#xff0c;Container 里面装的是任意类型的 App&#xff0c;我们的开发人员可以通过 Docker 将App 变成一种标准化的、可移植的、自管理的…

C语言位运算

所谓位运算&#xff0c;就是对一个比特&#xff08;Bit&#xff09;位进行操作。比特&#xff08;Bit&#xff09;是一个电子元器件&#xff0c;8个比特构成一个字节&#xff08;Byte&#xff09;&#xff0c;它已经是粒度最小的可操作单元了。C语言提供了六种位运算符&#xf…

linux系统下centos7 或 openwrt安装 使用 SpeedTest 测速

博主博客 https://blog.uso6.com https://blog.csdn.net/dxk539687357 一、测试本地是否安装 python(已安装可以跳过) 1.在命令行中输入rpm -qa | grep python36 判断是否已经安装 python3。 2.如果没有安装输入 yum install python36 进行安装。 二、测试 CentOS 到 Speed Te…

响应式布局以及提交网站

1.慕客协作平台1. /摹客官网地址&#xff1a; https://www.mockplus.cn/ 注册一个账号2. 下载moke ps插件 3. PS 安装/摹客/蓝湖插件3. 打开PS/摹客/蓝湖插件4. 上传&#xff08;需要切图&#xff0c;需要先标注切图&#xff09;5. 查看项目6. 邀请成员进入&#xff08;分享按钮…

【Java 面试合集】简述下自定义异常的应用场景

简述下自定义异常的应用场景 1. 概述 如上图所示&#xff0c;我们想回答这个问题就要了解异常的基本结构。哪些是我们可以控制的&#xff0c;哪些是我们不能控制的。 也许有人会问了&#xff0c;其实在逻辑中可以多加判断&#xff0c;为什么要需要自定义呢。 其实判断的内容无…