张 健,刘威鹏,李跃鹏,杨亚璞,朱彦磊
(许继电气股份有限公司,河南 许昌 461000)
为了满足工业控制装备对高速数据交换的需求以及PCIe 总线技术的成熟应用,PCIe 总线已被引入到工业控制装置的设计中。PCIe 总线作为一种超高速通信总线,可以通过交换机扩展的PCIe 链路作为背板总线使用,支持多种不同类型设备的连接,例如IO 模块、传感器和执行器等。这些设备可以通过PCIe 链路与主控制器进行数据交换,实现工业控制装备的各种功能。此外,PCIe 链路还可以用于连接工业网络和传感器网络等外部设备,使得工业控制装备可以与外部系统进行数据交换,实现更加灵活的控制和管理功能[1-3]。
PCIe 总线与传统工业控制装备的设备互联方式不同。PCIe 总线采用的是点对点连接方式,可以保证设备间的数据传输不被其他设备干扰[4-8]。但是,PCIe 总线设备地址的分配方式与传统工业控制装备不同。在传统工业控制装备中,设备地址通常由生产厂商设定并固定。而在PCIe 总线架构中,设备地址是由装置上电初始化时动态分配的[9]。此外,工业控制装备通常支持可插拔的PCIe 外设,以增强系统的灵活性。可插拔的PCIe外设也是由系统动态地分配地址。然而,在高度自动化的工业控制装备中,设备的外设地址通常是固定的。如果设备的外设地址不是固定的,主控处理器访问外设时需要遍历整个外设地址表获取相应的外设地址,这会增加系统开销并可能导致设备之间数据传输故障,影响设备的正常运行。
在工业控制装备中,设备之间的数据交换是至关重要的。这些装置的运行直接关系到人们的生命和财产安全。因此,为了确保设备之间数据传输的高可靠、高实时性,保证工业控制装备的高效运行,需要在系统设计阶段充分考虑设备的特性和要求,设计一种适用于工业控制装备的PCIe 外设地址分配方案,避免地址变化和地址冲突带来的问题。
本文从工业控制装备的应用特性及设计、调试和查找问题的便利性角度出发,提出了一种基于虚拟端点的PCIe 交换机地址分配方案,该方案在支持热插拔的装置中,能够将PCIe 设备分配的地址空间固定下来,即设备所分配的地址与装置中插入的设备数量、类型无关,仅与设备插入的位置有关。该方案旨在使PCIe 总线更加便捷地应用于工业控制领域。
PCIe 交换机是一种用于扩展PCIe 总线的硬件设备,并提供多个PCIe 设备之间的数据转发,以充分利用PCIe 总线的带宽[10]。通常,PCIe 交换机系统由3 个主要部分组成[11],包括根复合体(Root-complex)、PCIe 交换机(Switch)和端点设备(End-point)。
图1 为基于PCIe 交换机的系统拓扑结构。在该系统中,交换机可看作是虚拟PCI 桥和虚拟总线的集合体。它由一个上游端口和多个下游端口组成[12]。CPU处理器通过根复合体完成存储器域到PCIe 总线域的地址转换,扩展出虚拟PCIe 桥,将其连接到Switch 的上游端口,以扩展PCIe 链路。Switch 内部由多个虚拟PCI 桥组成,其中上游端口和各下游端口均分别对应一个虚拟PCI 桥。上游端口对应的虚拟PCI 桥0 用于连接各虚拟PCI 桥,而每个下游端口(例如4 个)均对应一个虚拟PCI桥,分别为虚拟PCI 桥1、虚拟PCI 桥2、虚拟PCI 桥3 和虚拟PCI 桥4。此外,端点A、C 和D 是挂载在各下游端口下的有效端点。
图1 基于PCIe 交换机的系统拓扑结构图
根据遍历路径的不同,图的遍历算法可分为两种:广度优先搜索和深度优先搜索[13]。其中,广度优先搜索法是在完成当前层的节点遍历后再进行下一层的遍历,而深度优先搜索法则是优先遍历深度最大的未遍历节点[14]。
PCIe 设备采用深度优先搜索算法。该算法的基本思想是从图中某个顶点v 开始遍历,访问该顶点后依次遍历v 的未被访问的邻接点,直至所有与v 相连的顶点都被访问过。如果此时还有未被访问的顶点,则选取一个未访问的顶点作为新的源节点,重新进行深度优先遍历,直到图中所有顶点都被访问过为止[15-18]。
PCIe 设备的枚举过程是计算机启动过程中的一个重要步骤,它负责识别系统中的PCIe 设备并将其配置到正确的地址空间。一般情况下,PCIe 设备的枚举过程是由BIOS 或者操作系统自动完成的,用户无需手动干预。
在计算机启动过程中,BIOS 或者操作系统会执行PCIe 设备的枚举,以识别和配置这些设备。枚举流程遵循以下步骤:
(1) 动态探测PCIe 总线:通过深度优先搜索算法,动态探测所有PCIe 总线。设备枚举从根节点开始,探测总线0 上的所有设备。当探测到第一个桥设备时,会为其分配Primary bus 号和Secondary bus 号,其中Secondary bus 号为1,Subordinate bus 号暂时和Secondary bus 号相同。然后以该桥为根节点,继续探测其下游总线,发现新总线后会自动调整Subordinate bus 号。如此反复直到所有子树都探测完毕。
(2) 确定PCIe 总线上的有效设备:从PCIe 总线上的根端口开始(通常是Device0),依次访问每个设备并读取读取其厂商识别码(Vendor ID),该识别码是由设备制造商唯一分配的,可用于确定设备的身份。如果没有找到有效设备,则可以继续尝试访问Device1~Device31的设备。
(3) 建立设备信息链表:将所有探测到的PCIe 设备的ID 信息Bus+Device+Function(BDF)放入设备信息链表中。在PCIe 系统中,通过BDF 可以唯一确定一个PCIe 设备。
(4) 检查需要自动配置的设备:利用设备信息链表,检查这些设备是否需要自动配置。对于需要自动配置的设备,向设备的Base Address Register (BAR)空间写0xFFFFFFFF,并读取BAR 值确定BAR 地址空间大小。然后进行地址空间分配,最终完成各个PCIe 设备的自动配置。
在枚举完成后,操作系统为每个PCIe 设备注册驱动程序,驱动程序使用分配给PCIe 设备的地址和资源信息来初始化和配置设备,此过程需要遵循PCIe 规范,并考虑设备的电气特性和性能要求,可以确保PCIe 设备与系统的稳定性和兼容性。
在明确了PCIe 交换机架构、枚举方式、资源分配后,即可设计相应的PCIe 交换机地址分配方案。
本方案在PCIe 交换机系统遍历过程中,在未发现连接任何端点设备的下游虚拟PCI 桥下设置虚拟端点,并将虚拟端点添加到该下游虚拟PCI 桥的链路下,形成包括有虚拟端点的系统拓扑结构,并为系统扩展链路下所有虚拟PCI 桥设置固定间隔的下辖外设地址空间,以实现无论系统中支持热插拔的外设板卡在装置运行过程中数目、类型和位置如何改变,各下游虚拟PCI 桥下接入的有效端点分配的地址空间固定。
系统拓扑结构是PCIe 交换机资源分配的基础。为了优化系统资源分配,需要改进系统拓扑结构。以交换机有4 个下游端口为例,图2 为获取含有虚拟端点的拓扑结构流程:
图2 含有虚拟端点的拓扑结构获取流程图
(1)从连接根复合体与上游端口的总线BUS1 开始,遍历PCIe 交换机系统,当扫描到位于BUS2 上的下游虚拟PCI 桥及下游总线BUS3~BUS6 时,将处于Switch 扩展链路下的下游虚拟PCI 桥加入设备ID 表中。
(2)如果该设备是有效端点,则将其添加到设备信息链表中,并设置其属性。有效端点指的是系统中扫描到的实际物理设备。
(3)如果某下游虚拟PCI 桥下未扫描有效端点,则在拓扑结构中为该下游虚拟PCI 桥链路添加一个虚拟端点,并将该虚拟端点添加到设备ID 表中并设置其属性。虚拟端点可以被视为一种特殊的PCIe 设备,它并不对应于任何实际的物理设备,但它同样具有设备ID 和特殊识别码等标识信息,可以被PCIe 交换机识别并分配资源。
(4)设置下游虚拟PCI 桥下接入设备(有效端点或者虚拟端点)的属性,并加入设备ID 表中;这个过程涉及设备属性信息的更新和设备ID 表的修改,确保设备ID 的唯一性和设备属性的准确性。
(5)继续扫描下一个下游虚拟PCI 桥,当BUS2 上所有下游虚拟PCI 桥扫描完毕后,得到含有虚拟端点的系统拓扑结构。
在得到含有虚拟端点的拓扑结构之后,需要对每个下游虚拟PCI 桥的下辖设备(有效端点或者虚拟端点)分配地址空间,并为每个虚拟PCI 桥(虚拟PCI 桥1、虚拟PCI 桥2、虚拟PCI 桥3 和虚拟PCI 桥4)设置下辖外设地址空间。
如图3 所示,系统外设地址空间固定分配的具体步骤如下:
图3 系统外设地址分配流程图
(1)获取驱动程序中预先配置的下游虚拟PCI 桥的固定下辖空间以及PCIe 空间起始地址(Pcie_Mem_Adrs),并将其作为PCI0 和PCI1 下辖空间首地址进行PCIe 端点地址分配。
(2)对于虚拟端点,为其分配固定间隔为Fixed_Space 的下辖外设地址空间,以使得虚拟端点所属的桥下辖空间为Fixed_Space,由于虚拟PCI 桥不含BAR 空间,不占用PCIe 空间,因此,虚拟端点所属的下游虚拟PCI 桥下辖空间为虚拟端点分配的地址空间。
(3)对于有效端点,通过读取BAR 寄存器中可读不可写的位数,获取所需申请的BAR 空间长度(Required_Space),然后,为有效端点分配BAR 地址空间。接着,将Required_Space 和预设的固定间隔Fixed_Space进行比较,如果固定间隔的长度大于或等于BAR 空间长度,则设置该有效端点所属的下游虚拟PCI 桥下辖空间长度为Fixed_Space;如果固定间隔长度小于BAR 空间长度,则将固定间隔Fixed_Space 重新设置为Required_Space,并返回执行步骤(2),实现自动调整固定间隔Fixed_Space 的功能。
(4)根据已经分配的外设地址总长度,更新剩余外设空间地址首地址(Pcie_Mem),作为下一个下游虚拟PCI 桥的下辖空间首地址,然后,返回步骤(2)配置下一个下游虚拟PCI 桥。
(5)当所有下游虚拟PCI 桥全部配置完毕,将虚拟PCI 桥0 的下辖地址空间的结束地址设置为Pcie_Mem。
外设地址空间的固定分配如图4 所示,其中Pcie_Mem_Adrs 由驱动程序配置,Fixed_Space 表示固定间隔,Required_Space 表示有效端点的BAR 空间长度,Pcie_Mem 表示剩余外设地址空间的首地址,Pcie_Mem_Pre 表示下游虚拟PCI 桥的下辖外设地址空间的起始地址,Mem_Limit 表示下游虚拟PCI 桥接入端点的BAR 空间边界,Pcie_Mem_Post 表示下游虚拟PCI 桥下辖的结束地址。图中端点A、C、D 为不同类型的有效端点,B为添加的虚拟端点。由图可知,当前下游虚拟PCI 桥的Pcie_Mem_Post 为下一个下游虚拟PCI 桥的Pcie_Mem_Pre。虽然各端点A、B、C 分配的地址空间空间大小不同,但是各端点所属的下游虚拟PCI 桥下辖的外设地址空间的长度相等。
图4 外设地址空间的固定分配示意图
图5 为含有虚拟端点的系统拓扑结构与地址分配图,图中端点B 即为添加的虚拟端点,图中所有端点(虚拟端点和有效端点)均分配固定的地址空间。
图5 含有虚拟端点的系统拓扑结构与地址分配图
由图4 和图5 可以得出,各下游端口对应的虚拟PCI桥的下辖外设起始地址计算公式为:
式中,PMP(Num)为所求各下游端口对应的虚拟PCI 桥配置固定间隔的下辖外设地址空间的起始地址;PMA 为驱动中配置的系统PCIe 空间起始地址;Num 为下游端口对应的虚拟PCI 桥的编号,Num=0,1,2,...,n;FS 为固定间隔。
式(1)中的Num 与外设所处的物理槽位号存在一一映射关系。因此,可以通过以下公式来计算外设的物理槽位号:
式中,HWA(Num)为所求外设物理槽位号;α为固定值,表示Num 与物理槽位号间的差值。
当发生外设交互故障时,处理器通过记录故障时刻外设交互的地址来确定PMP(Num),并通过式(2)来确定故障外设的物理槽位位置。这个过程是非常重要的,因为快速准确地确定故障外设的位置是进一步分析故障原因的基础。一旦确定了故障外设的物理槽位位置,处理器生成故障日志文件,其中包含故障发生的时间、故障时刻设备的运行状态、使用设备的应用程序、故障外设的BDF、厂商识别码等重要信息。这些信息可以帮助进一步分析和定位故障原因。
本方案设计的是一个通用PCIe 交换机系统,为验证该方案的可行性和正确性,在风河公司开发的实时操作系统VxWorks 上开发了PCIe 驱动,并构建了如图6 所示的测试平台,测试平台包括嵌入式CPU 板卡、PCIe 机箱、信号发生器、ADC 外设板卡和串口连接线。其中,CPU 板卡位于机箱第一个槽位,其余10 个槽位用于插入ADC 外设板卡,支持热插拔。
图6 测试平台示意图
在该测试平台中,信号发生器与ADC 板卡相连接,产生的数据源通过机箱PCIe 背板以DMA 的方式传递给CPU 板卡。为了实现地址空间的分配和管理,设计了驱动函数sysPciAutoConfig。图7 为该函数通过串口打印输出的地址分配结果,其中PCIe 空间起始地址为0x90000000,各下游虚拟桥的下辖外设地址空间大小均为0x1000000 Byte(16 MB),各端点的预取BAR 空间均位于其接入的下游虚拟PCI 桥的下辖空间内。通过这种地址分配方式,无论系统中支持热插拔的外设板卡在装置运行过程中数目、类型和位置如何改变,系统为装置的各个槽位下的外设板卡所分配的地址空间不变。
图7 PCIe 总线扫描与资源分配函数实现
对比测试表明,采用地址固定分配的方式和地址动态分配的方式都能够正确地完成DMA 传输。然而,固定地址方式的传输速率要比动态分配的方式快0.5 μs。这是因为采用固定地址方式可以省去遍历查询外设地址的环节,从而提高了数据传输的效率。当数据量较小(例如只有16 B)时,这种提升可以达到大约10%的执行效率提升,如表1 所示。
表1 地址分配速率对比
本文提出了的一种基于虚拟端点的PCIe 交换机地址分配方案,该方案通过固定PCIe 外设地址,实现了系统中支持热插拔的外设板卡在装置运行过程中数目、类型和位置改变时,系统为装置的各个槽位下的外设板卡所分配的地址空间不变,外设地址与物理槽位相对应,可以快速地确定设备物理槽位。这种方案的优点在于能够简化系统设计和调试,提高系统的实时性和灵活性,有助于推动PCIe 总线技术在工业控制领域的应用,促进工业自动化水平的提高。