自学内容网 自学内容网

PCIe的三种路由方式

往期内容

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

  1. 嵌入式系统的内存访问和总线通信机制解析、PCI/PCIe引入
  2. 深入解析非桥PCI设备的访问和配置方法
  3. PCI桥设备的访问方法、软件角度讲解PCIe设备的硬件结构
  4. 深入解析PCIe设备事务层与配置过程

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博客
    – 末篇,有专栏内容观看顺序

img

1.三种路由方式

数据传输时,最先要确定的是:怎么找到对方?

所谓"路由",就是怎么找到对方,PCIe协议中有三种路由方式:

  • 基于ID的路由
  • 基于地址的路由
  • 隐式路由

TLP中怎么表示自己使用哪种路由?TLP头部就表明了:

img

访问PCIe设备时,要先配置,才能读写数据:

  • 配置读、配置写:使用基于ID的路由,就是使用<Bus, Device, Function>来寻找对方。配置成功后,每个PCIe设备都有自己的PCIe地址空间了。

  • 内存读、内存写或者IO读、IO写:

    • 发出报文给对方:使用基于地址的路由
    • 对方返回数据或者返回状态时:使用基于ID的路由
  • 各类消息,比如中断、广播等:使用隐式路由

2.基于ID的路由

TLP中含有<Bus number, Device number, Function number>,这就是ID。

配置成功后,每个PCIe设备,包括虚拟的PCIe桥,都分配到了地址空间:

  • PCIe设备(Endpoint):地址空间是自己的,别的设备访问这个地址范围时,就是想访问它
  • PCIe桥:地址空间是下面的PCIe设备的,别的设备访问这个地址范围时,就是想访问它下面的设备

img

2.1 PCIe设备(Endpoint)的配置空间

Endpoint的配置空间里有"Base Address Regiseters":

  • 一开始:这些寄存器用来声明:需要多大的地址空间、是内存空间还是IO空间
  • 被配置后:系统软件为它分配出地址空间,把首地址写入这些寄存器

下图来自《PCI Express_ Base Specification Revision 4.0 Version 0.3 ( PDFDrive ).pdf》:

img

2.2 PCIe桥的配置空间

PCIe桥的配置空间里有"Primary Bus Number、Secondary Bus Number、Subordinate Bus Number":

  • 配置PCIe桥的时候,系统软件会填充这些信息
  • 对于ID路由,将根据这些信息转发报文

PCIe桥的配置空间里有"Memory Base、Prefetchable Memory Base、I/O Base":

  • 表示该桥下游所有设备使用的三组空间范围

    • 存储器空间
    • 可预取的存储器空间
    • I/O空间
  • 对于地址路由,将根据这些信息转发报文

下图来自《PCI Express_ Base Specification Revision 4.0 Version 0.3 ( PDFDrive ).pdf》:

img

2.3 组合

img

假设2号设备写入到配置空间的地址范围为AB,3号设备写入到配置空间地址范围是CD,那么1号桥设备所记录的地址空间范围就得包含下游设备的地址范围AB和CD。

3.基于地址的路由

PCIe设备(EndPoint)被配置后,它记录有分配给它的基地址。

PCIe桥也记录有下游PCI子树的基地址。

  • PCIe桥监测总线上的信号,根据TLP里的地址决定是否转发到自己下面的总线上
  • PCIe设备监测总线上的信号,根据TLP里的地址决定是否访问自己
  • PCIe设备发出回应的报文时,使用基于ID的路由

3.1 内存读写/IO读写

img

需要注意的是Requester ID,这个是设备回应时所不可缺少的,报文回应的是基于ID的路由

3.2 完成报文

上图里面的Requester ID、TAG,被称为"Transaction ID"。
在这里插入图片描述

主设备要给EndPoint的内存写数据,它发出"内存写报文",不需要对方回应。

主设备要读EndPoint的内存数据,它发出"内存读报文",需要对方回应。

主设备要给EndPoint的IO写数据,它发出"IO写报文",需要对方回应。

主设备要读EndPoint的IO数据,它发出"IO读报文",需要对方回应。

  • PCIe设备要回应时,回应谁?给"Requester ID",使用基于ID的路由
  • 发起PCIe传输的设备(主设备),对每次传输都分配一个独一的Tag,并且在硬件内部保存当前TLP
  • 接收到回应报文后,才会根据Tag清除掉内存中保存数据
  • 如果没接收到回应,或者失败了:会把硬件中保存的TLP重新发送出去

回应的完成报文,可以含有数据,也可以不含数据,格式如下:

img

3.3 示例

img

TLP1:TLP1是要发送给EP1,那么其Requester ID就是RC的信息,RC回应EP21时,靠的就是Requester ID找到EP1,只有接收到回应,EP1中保存的发送的TLP信息才会删除,否则就会进行重发直到收到回应,而这个离不开TLP中的Tag字段(请求标签,用于追踪该请求)

4.隐式路由

隐式路由意味着无需显式指定目标设备(不使用Bus、Device、Function号),而是通过其他信息(如目标地址或ID)确定数据的传输路径。

根据不同的路由方式,PCIe消息可以在不同设备间传递,或直接发送至根复杂设备(Root Complex, RC)。

消息报文的头部格式如下:

img

消息报文中头部的Type字段里低3位表示隐式路由方式:

000:路由到Root Complex (RC)

  • 这种类型的消息直接路由到PCIe总线的根复杂设备(RC),通常用于管理或状态查询的请求,RC负责处理这些消息。
  • 示例:例如,PCIe设备请求RC进行特定的配置或查询操作。

001:使用地址路由

  • 消息根据目标的内存地址I/O地址来进行路由,基于配置阶段中分配的地址范围。地址路由在正常的数据读写操作中比较常见,但消息使用这种方式较为少见。
  • 示例:地址范围确定消息应该送到哪个设备,通过检查内存或I/O地址来定位目标设备。

002:使用ID路由

  • 根据设备的Bus、Device、Function(BDF) ID信息来确定消息的传输路径。此时,系统中的交换机或桥设备会解析消息中的ID信息,将消息转发到对应的目标设备。
  • 示例:典型用于PCIe设备之间的配置操作,如读取某个设备的配置寄存器或发起特定的设备管理请求。

011:来自Root Complex的广播报文

  • 当根复杂设备发出这种类型的广播消息时,所有下游的PCIe桥设备都会转发该消息给其下游设备。
  • 示例:在系统中的所有PCIe设备需要接收某个全局配置或广播命令时,RC会发出这样的广播消息。

100:本地消息

  • 本地消息在到达目的设备后结束,不会被再次转发。这种消息通常用于在设备内部处理一些特定的控制或管理任务,而不是跨越多个设备进行传递。
  • 示例:设备内部的状态或控制消息,如内部的电源管理指令等。

101:路由到Root Complex,仅用于电源管理

  • 这种类型的消息专门用于与Root Complex进行电源管理相关的事务。比如,当某个设备进入低功耗状态时,它可能会向RC发送此类消息以告知其状态。
  • 示例:设备进入睡眠模式时,会向RC报告自身的电源状态。

隐式路由通常由根复杂设备或中间的PCIe桥通过解析TLP(Transaction Layer Packet)中的地址或ID字段来确定路由路径。

Type字段低3位提供了不同类型的路由选择,包括直接路由到RC、使用地址或ID进行路由,以及特殊的广播或本地消息。

img


原文地址:https://blog.csdn.net/caiji0169/article/details/144438956

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!