PCI/PCIe设备INTx中断机制和MSI中断机制

往期内容

本文章相关专栏往期内容,PCI/PCIe子系统专栏:

  1. 嵌入式系统的内存访问和总线通信机制解析、PCI/PCIe引入
  2. 深入解析非桥PCI设备的访问和配置方法
  3. PCI桥设备的访问方法、软件角度讲解PCIe设备的硬件结构
  4. 深入解析PCIe设备事务层与配置过程
  5. PCIe的三种路由方式
  6. PCI驱动与AXI总线框架解析(RK3399)
  7. 深入解析PCIe地址空间与寄存器机制:从地址映射到TLP生成的完整流程
  8. PCIe_Host驱动分析_地址映射
  9. PCIe_Host驱动分析_设备枚举

Uart子系统专栏:

  1. 专栏地址:Uart子系统
  2. Linux内核早期打印机制与RS485通信技术
    -- 末片,有专栏内容观看顺序

interrupt子系统专栏:

  1. 专栏地址:interrupt子系统
  2. Linux 链式与层级中断控制器讲解:原理与驱动开发
    -- 末片,有专栏内容观看顺序

pinctrl和gpio子系统专栏:

  1. 专栏地址:pinctrl和gpio子系统

  2. 编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

    -- 末片,有专栏内容观看顺序

input子系统专栏:

  1. 专栏地址:input子系统
  2. input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
    -- 末片,有专栏内容观看顺序

I2C子系统专栏:

  1. 专栏地址:IIC子系统
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
    -- 末篇,有专栏内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树
  2. 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
    -- 末篇,有专栏内容观看顺序

目录

资料

参考资料:

开发板资料:

分析的文件:

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

1.PCI设备的INTx中断机制

PCI设备是可以通过INTA#引脚喝PCIe设备进行连接的,有PCIe硬件来向控制器传递中断,这种和GPIO引脚的中断传递方式差不多。PCI总线上有INTA#~INTD#这些真实存在的引脚。

在PCI设备的配置空间,它声明:通过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(虚拟中断号)写入此寄存器。软件完全可以自己记录中断信息,没必要依赖这个寄存器。

INTx中断是电平触发,处理过程如下:

  • PCI设备发出中断:让INTx引脚变低
  • 软件处理中断,清除中断:写PCI设备的某个寄存器,导致PCI设备取消中断
  • PCI设备取消中断:让INTx引脚变高

2.PCIe设备的INTx中断机制

看接口图可以看出,PCIe设备是没有像PCI设备那样用INTx# 引脚(PCIE总线上并没有这些引脚)来和PCIe控制器进行连接从而达到传递中断的目的,但是一般情况下PCIe设备的驱动程序一般都是兼容PCI设备的,那么是怎么兼容的? --- 发出特殊的TPL

PCIe 是完全向后兼容 PCI 的,因此即使没有物理的 INTx# 引脚 ,PCIe 仍然可以通过软件和消息的方式模拟这些传统中断,以支持那些依赖于 INTx# 中断的 PCI 驱动程序。具体来说,PCIe 使用的是消息传递而非物理中断引脚。

TLP头部中,Message Code被用来区分发出的是哪类TLP包,为例"INTx模拟",有两类TLP包:

  • Assert_INTx -- 发出
  • Deassert_INTx -- 取消

跟传统PCI设备类似,这个"INTx模拟"的处理过程也是一样的:

  • PCIe设备发出中断:发出Assert_INTx的TLP包
  • 软件处理中断,清除中断:写PCIe设备的某个寄存器,导致PCIe设备取消中断
  • PCIe设备取消中断:发出Deassert_INTx的TLP包

硬件框图如下:

对于软件开发人员来说,他感觉不到变化:

  • PCI设备通过真实的引脚传输中断
  • PCIe设备通过TLP实现虚拟的引脚传输中断

3.MSI中断机制

从上图可以看出,传统的INTx#中断,比如PCI系统,由于是并行连接,因此如果有多个PCI设备的话,他们就得共享这四条INTA#~INTD#这四条真实的中断引脚才能连接同一个PCI控制器,中断效率很低;同样对于PCIe系统,PCIe设备只能发出 INTA#~INTD# 四种TPL包。为此引入了新的中断机制:MSI,Message Signaled Interrupts。

在初始PCI设备时,可以告诉它一个地址(主控芯片的地址)、一个数据:

  • PCI设备想发出中断时,往这个地址写入这个数据就可以触发中断
  • 软件读到这个数据,就知道是哪个设备发出中断了

流程及硬件框图如下:

设备发出 MSI/MSI-X 中断时,会通过**向一个特定的地址(pci_addr > cpu_addr)写入数据(value)**来触发中断。

  • cpu_addr 是内存中的某个地址,通常是一个分配给中断控制器(例如 GIC,Generic Interrupt Controller)的地址,或是 PCI/PCIe 控制器的某个特定寄存器地址,当然,分配给它们肯定是需要映射为pci_addr

  • 当设备触发中断时,会将 value 数据写入 pci_addr ,pci_addr又是cpu_addr的映射,会写入到cpu_addr,这使得 CPU 中的中断控制器(如 GIC)检测到这个写操作,并生成中断。

    • cpu_addr:可以是PCI/PCIe控制器也可以是GIC的地址。往前者写入value,其会进一步上报给GIC;后者则可以直接往GIC写入value,触发中断
  • pci_addrvalue的地址范围 在初始化设备时就写入了设备配置空间中Capabilities Pointer 相应的Capability 结构(比如 MSI Capability

3.1 Capabilities Pointer

capability的意思是"能力",PCI/PCIe设备可以提供各种能力,所以在配置空间里有寄存器来描述这些capability:

  • 配置空间里有第1个capability的位置:Capabilities Pointer
  • 它指向第1个capability的多个寄存器,这些寄存器也是在配置空间里
  • 第1个capability的寄存器里,也会指示第2个capability在哪里

Capability示例图如下:

  • 配置空间0x34位置,存放的是第1个capability的位置:假设是 A4H

  • 在配置空间0xA4位置,找到第1个capability,capability的寄存器有如下约定

    • 第1个字节表示ID,每类capability都有自己的ID
    • 第2个字节表示下一个capability的位置,如果等于0表示这是最后一个capability
    • 其他寄存器由capability决定,所占据的寄存器数量由capability决定
  • 第1个capability里面,它表示下一个capability在5CH

  • 在配置空间0x5C位置,找到第2个capability

    • 第1个字节表示ID,第2个字节表示下一个capability的位置(图里是E0H)
    • 其他字节由capability本身决定
  • 在配置空间0xE0位置,找到第3个capability

    • 第1个字节表示ID
    • 第2个字节表示下一个capability的位置,这里是00H表示没有更多的capability了
    • 其他字节由capability本身决定

假设Capability X就是MSI Capability类型的结构,那么pci_addr和value就存在这里面,同时也代表了这个设备支持MSI

  • Message Address:设备触发 MSI 中断时要写入的地址。
  • Message Data:设备触发中断时写入的数据。

\1. MSI Capability (Message Signaled Interrupts)

  • ID: 0x05
  • 用于支持 Message Signaled Interrupts (MSI),它允许设备通过写内存的方式来触发中断,而不是传统的 INTx 引脚。

\2. MSI-X Capability

  • ID: 0x11
  • 是 MSI 的扩展版本,支持多个中断向量,可以为不同的事件触发不同的中断向量,从而提高系统中断处理的并行性和性能。

\3. PCI Power Management Capability

  • ID: 0x01
  • 提供设备的电源管理功能,支持各种电源状态(如 D0、D1、D2、D3),允许操作系统和驱动程序控制设备的功耗,进入低功耗模式或唤醒。

\4. AGP Capability (Accelerated Graphics Port)

  • ID: 0x02
  • 用于 AGP 设备,主要出现在老式图形处理器中,定义了设备如何通过 AGP 接口进行内存访问和加速图形处理。

\5. PCI Express Capability

  • ID: 0x10
  • 用于 PCI Express 设备,描述了设备的 PCIe 相关特性和能力。它是 PCIe 设备的一个重要 Capability,包含有关链路状态、链路速度、设备功能等信息。

\6. Vital Product Data (VPD) Capability

  • ID: 0x03
  • 允许存储设备的产品相关数据,如序列号、制造商信息等。这些信息通常是不可变的,用于识别设备。

\7. Hot-Plug Capability

  • ID: 0x0F
  • 用于支持热插拔功能的 PCIe 设备,允许在不关闭系统的情况下动态地插入和移除设备。这个 Capability 通常会出现在支持热插拔功能的 PCIe 插槽或设备中。

\8. Vendor-Specific Capability

  • ID: 0x09
  • 一些厂商定义的特定功能。每个厂商可以根据需求定制自己的 Capability,用于实现特定的硬件功能或扩展特性。

\9. SATA Capability

  • ID: 0x12
  • 出现在支持 SATA 接口的设备中,提供了有关 SATA 控制器的扩展特性,包含 SATA 端口的信息。

\10. Advanced Error Reporting (AER) Capability

  • ID: 0x13
  • 用于 PCI Express 设备,提供高级错误报告功能,允许设备报告和记录错误事件,支持更强的错误检测和错误处理机制。

\11. Slot Identification Capability

  • ID: 0x04
  • 用于表示设备所在的物理插槽,尤其是在多插槽的系统中有用,可以帮助操作系统识别设备所在的具体位置。

\12. HyperTransport Capability

  • ID: 0x08
  • 用于支持 HyperTransport 总线的设备,HyperTransport 是一种高速、低延迟的点对点链路技术,主要用于 CPU 和其他高速外设之间的通信。

\13. PCI-X Capability

  • ID: 0x07
  • 出现在支持 PCI-X 标准的设备中,描述了设备的 PCI-X 特性,主要用于服务器和工作站等需要更高带宽的场景。

\14. Latency Tolerance Reporting (LTR) Capability

  • ID: 0x18
  • 用于报告设备的延迟容忍度信息,帮助系统优化功耗和性能之间的平衡,尤其在低功耗系统中比较常见。

\15. Resizable BAR Capability

  • ID: 0x15
  • 允许设备调整其基址寄存器(BAR)的大小,支持更大内存映射区域,这在高性能 GPU 或需要大量内存映射的设备中很有用。

\16. Access Control Services (ACS) Capability

  • ID: 0x0D
  • 提供设备对 I/O 请求路径的控制,主要用于 PCIe 设备隔离和安全性,确保 I/O 传输不会受到未授权的访问影响。

\17. Alternative Routing-ID Interpretation (ARI) Capability

  • ID: 0x0E
  • 用于支持 PCIe ARI 扩展,允许一个 PCIe 设备具有多个功能域(Function),从而增加设备的功能数量(例如多功能网卡等)。

3.2 MSI Capability

  • pci_addr是32位、还是64位?
  • 能触发几个中断?通过地址来分辨,还是通过数据来分辨?
  • 这些中断能否屏蔽?
  • 能否读出中断状态?
  • 这些问题,都由capability里面的"Message Control"决定。

MSI Capability格式的含义如下:

  • Capability ID:对于MSI capability,它的ID为05H
  • Next Pointer:下一个capability的位置,00H表示这是最后一个capability
  • Message Control
描述
8 Per-vector masking capable 是否支持屏蔽单个中断(vector): 1: 支持 0: 不支持 这是只读位。
7 64 bit address capable 是否支持64位地址: 1: 支持 0: 不支持 这是只读位。
6:4 Multiple Message Enable 系统软件可以支持多少个MSI中断? PCI设备可以表明自己想发出多少个中断, 但是到底能发出几个中断? 由系统软件决定,它会写这些位,表示能支持多少个中断: 000: 系统分配了1个中断 001: 系统分配了2个中断 010: 系统分配了4个中断 011: 系统分配了8个中断 100: 系统分配了16个中断 101: 系统分配了32个中断 110: 保留值 111: 保留值 这些位是可读可写的。
3:1 Multiple Message Capable PCI设备可以表明自己想发出多少个中断: 000: 设备申请1个中断 001: 设备申请2个中断 010: 设备申请4个中断 011: 设备申请8个中断 100: 设备申请16个中断 101: 设备申请32个中断 110: 保留值 111: 保留值 这些位是只读的。
0 MSI Enable 使能MSI: 1: 使能 0: 禁止
  • Message Address/Message Uper Address:地址

    • 32位地址保存在Message Address中
    • 64位地址:低32位地址保存在Message Address中,高32位地址保存在Message Uper Address中
    • 这些地址是系统软件初始化PCI设备时分配的,系统软件把分配的地址写入这些寄存器
    • 这些地址属于PCI地址空间
  • Message Data:数据

    • 这个寄存器只有15位,PCI设备发出中断时数据是32位的,其中高16位数据为0

    • 这个寄存器的数值是系统软件初始化设备时写入的

    • 当PCI设备想发出中断是会发起一次写传输:

      • 往Message Address寄存器表示的地址,写入Message Data寄存器的数据
      • 如果可以发出多个中断的话,发出的数据中低位可以改变
      • 比如"Multiple Message Enable"被设置为"010"表示可以发出4个中断
      • 那么PCI设备发出的数据中bit1,0可以修改
  • Mask Bits/Pending Bits: 屏蔽位/挂起位,这是可选的功能,PCI设备不一定实现它

    • Mask Bits:每一位用来屏蔽一个中断,被系统软件设置为1表示禁止对应的中断
    • Pending Bits:每一位用来表示一个中断的状态,这是软件只读位,它的值为1表示对应中断发生了,待处理
相关推荐
7yewh4 小时前
Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02
linux·arm开发·驱动开发·嵌入式硬件·嵌入式
上海易硅智能科技局有限公司4 小时前
AG32 MCU 的电机控制方案
单片机·嵌入式硬件
程序员JerrySUN5 小时前
Yocto 项目 - 共享状态缓存 (Shared State Cache) 机制
linux·嵌入式硬件·物联网·缓存·系统架构
嵌入式小强工作室7 小时前
stm32能跑人工智能么
人工智能·stm32·嵌入式硬件
MikelSun7 小时前
电压控制环与电流控制环
单片机·嵌入式硬件·物联网
陌夏微秋7 小时前
STM32单片机芯片与内部45 UART 不定长度接收 标志位结束 定时器超时 串口空闲中断
stm32·单片机·嵌入式硬件·信息与通信·智能硬件
挥剑决浮云 -8 小时前
STM32学习之 按键/光敏电阻 控制 LED/蜂鸣器
c语言·经验分享·stm32·单片机·嵌入式硬件·学习
Whappy0019 小时前
第13部分 1.STM32之PWR电源控制-----4个实验
stm32·单片机·嵌入式硬件
冲,干,闯10 小时前
单片机里不想阻塞系统的延时
单片机·嵌入式硬件
小菜鸟学代码··11 小时前
STM32中断详解
stm32·单片机·嵌入式硬件