当前位置: 首页 > article >正文

PCIe基础分享

简单介绍

之前的专栏主要介绍了DDR - Double Data Rate高速接口,用于处理器和DRAM存储芯片之间的通信。
这里再基于PCIe的SPEC和Mindshare的技术文章,简单介绍下高速并行通信总线规范的PCIe - Peripheral Component Interconnect Express。
PCIe作为用于处理器和各种硬件设备(网卡、显卡等外设)以及硬件设备之间的数据交互和通信的并行信号通信接口,设计阶段肯定需要考虑如下的几个问题:

  • Data Bits Skew
    多个并行Data信号之间存在skew,如果是通过同一个 CLK 采样就会导致错误的采样结果
  • Clock Skew
    一个Host端发出的Clock信号需要传输到多个不同的devices,不同devices之间会存在clock skew
  • Flight Time
    信号从Host端发送到Device端的传递时间,如果Flight Time过大(大于一个采样时钟周期),就会出现数据miss,导致后续signal全部混乱
  • Timing Margin and Clock Rate
    不同信号之间存在skew,采样速率越快,多个信号之间的timing margin越难控制

通信接口设计简单概念

为了解决上述的问题,我们在之前的DDR专栏提到过DDR作为并行通信接口针对此类问题的部分设计(例如通过Training来修正skew)。
而PCIe则是采用了SerDes技术,也就是SERializer(串行器)/De-Serializer(解串器)的简称,将低速的并行信号转化为高速低压差分信号并通过串行里链路发送,再接收串行输入串行信号并还原为低速并行信号。
Wiki-SeDes

所以在PCIe通信接口里,时钟信号和Data数据都会被混合到一起成为串行信号,等发送到对端之后再恢复出时钟信号和Data数据。
而时钟恢复的过程也有专门的硬件设计支持,简单的组成结构如下:
PLL

PCIe的端对端传输中,转化后的串行信号都会通过Tx/Rx通道上的差分信号进行传输,一组Tx/Rx通道就构成了一个lane。
而一组PCIe接口设备之间最多支持32Lane的传输宽度,这么多Lane组成的2个PCIe接口设备之间的信号通路就是一个link。
Lane

不同lane的数量也就定义了PCIe的Link带宽。
带宽

与DDR不同的还包括PCIe PHY的架构支持的信号调制也从NRZ向PAM4过度,一次Clock携带的数据量从0/1(2种情况)变为了00/01/10/11(4种情况)
PAM4

拓扑结构

下图是PCIe 3.0 Spec中部分的拓扑结构图,简单来看,除了具备Function的PCI Express Endpoint (PCIe Device)之外,主要有以下几个组件:

  • Root Complex
    管理所有的PCIe Devices枚举信息和各个Device的Function信息,为后续devices routing 提供信息
  • Switch
    类似于一个Hub,管理部分PCIe Devices枚举信息和Device的Function信息,向Root Complex汇报,具体的消息发送通过一定的routing结构
  • PCI Express to PCI/PCI-X Bridge
    管理PCI/PCI-X等早期的协议和相关设备
  • Bus
    一个switch可以挂载多个Bus,Bus用于挂载Device
    拓扑

并且PCIe枚举时采用的是深度优先,每个PCIe Endpoint枚举成功后才会继续向下枚举next Endpoint。
向下枚举时不同bus下的Device/Function num会重新编号,类似于图中的Bus3和Bus4下面都有Dev0/Function0,但是物理设备和功能上都是不同的Devices和Function。
热插拔场景下,如果像上图中bus3和bus4之间本来还有一个Bus资源,设备需要接入到这个bus下,在基于深度优先的枚举原则下,那么就需要重新枚举(新加入的device占用为Bus4,Bus4及后续Bus都需要Number+1)

因此在真实PCIe枚举过程中,会预留一些空的device number,导致当前相邻的Bus Number数值差异会有点大,便于快速枚举热插拔设备(像上图中的bus3 & bus4可能就变成了bus3 & bus10)
这部分逻辑设计由SW控制,保证如果单个device枚举失败,就会把device视为空,不会影响其他devices。

PCIe设备层级设计

Layers

从上图可以看到,在Pcie Device之间的通信中,Device Core需要通过3个不同的Layer进行数据的封装/解包完成通信。
详细内容如下图所示:
Layers

从上图左侧可以看到,Transfer/Receive的device中不同的Trans/Data/Physical layer对Data进行了不同的封装/解包。
上图右侧是更为详细的封装/解包过程(一个TLP - Transaction Layer Packet payload length为4096 byte),下面基于上图右侧的三个层进行简要介绍:

Trans Layer

传输层主要的操作对象就是TLP - Transaction Layer Packet,TLP Packet中header会包含地址和command类型(R/W)信息,Data Payload包含Data信息,ECRC用于校验。
而TLP本身包括的信息可以分为以下几种类型。

Info TypeComment
Memory面向Memory,往Address指向的空间进行R/W,支持burst
IOInput/Outpt的硬件端口,访问空间有限,不支持burst
Configuration属于Device Function里的Object信息,只供RC - Root Complex处理
Message类似Interrupt这类misc信息

在不同的TLP传输过程中,也需要通过不同的Request请求发起,Request类型包括了Non-Post和Posted两种。
请求类型

Posted代表不需要对端回复信息。
Non-Posted代表需要对端回复,譬如Memory Read,一定需要对端回复一个CplD(Completion with Data),IO Read/Write一定需要回复一个Cpl(Completion without Data) 。
请求flow

而在TLP传输中,传输层也定义了不同TLP的QoS(Quality of Service),包括了:

ComponentComment
Traffic Class(TC)优先级信息,存放在Header中
Virtual Channel(VC)基于TC,对Buffer中的多个Packets根据Prior/Ordering等信息进行发送仲裁
Arbitration Logic基于VC进行仲裁
Ordering排序规则仅适用于 VC

TLP

可以理解为QoS决定了不同的Data传输对象可以根据TC里的Priority决定是否要在一个严格order的VC传输。
譬如设计的时候,如果是IO传输对象,必须严格要求order,但是memory传输对象就不用那么严格要求ordering。

并且传输层还支持了Flow Control。
Flow Control

Flow Control就是保证Ordering前提下,根据带宽管理Virtual Channel做流量限制,并且在Link Packet之外,会单独地让DLLP - Data Link Layer Packet建立一个CRC校验包。
如果VC Buffer快满了,DLLP控制反压流量,告诉发送方当前的流量需要控制在多少。

Data Link Layer

保持了Flow Control的机制,对于Packet增加了CRC校验以及Ack响应机制。DLLP - Data Link Layer Packet也是在这一层实现。
DLLP

在Data Link Layer,发送端根据接收方返回的ACK保证每笔数据准确地发送成功,如果长时间没有收到ACK或者收到了Nak,则会把数据存储到Retry Buffer进入重发队列,如果多次fail,就会上报error。
接收端根据DLLP模块校验CRC确认每笔数据都是准确的,再根据Packet中的Sequence Number进行周期性地ACK/Nak回复。
这里的ACK/Nak + CRC + LCRC + ECRC就简单地保证了一笔传输的正确性。
Ack

这里Switch之间的传输ACK对应关系就是1a/1b, 2a/2b, 3a/3b, 4a/4b这样,不会有requester到Completer的直接ack,都由switch中继。

Physical Layer

物理层的任务就比较繁杂了:

  • Byte striping and de-striping
    Byte分配到不同物理lane的拆包/重组任务
  • Scrambling and de-scrambling
    信息传输的加扰/解扰任务
  • Encode/Decode
    数据的编码/解码
  • Elastic Buffer
    由于串口上的Clock传输存在多拍/少拍/skew等问题,弹性buffer这里用于恢复串口上的Clock信号为SoC片内Clock
  • Link Training
    对Link训练保证delay满足信号传输需求
  • Order Set
    就是信息传输的顺序配置,结构组成就是右下角的图
  • Link Width/Data Rate
    发送方和接收方确定双方都能接受的Link带宽和传输速率
  • Lane Reversal
    Lane上的两端Rx/Tx可以根据具体布线方案任意端接,如果是Rx-Rx/Tx-Tx,就需要配置Lane
  • Reversal Polarity Inversion
    由于都是差分信号传输,同样可以根据具体布线方案任意端接,如果是T-T/C-C,就需要配置这个
  • Bit/Symbol Lock Per Lane
    每个lane上的bit/symbol(就是8b到10b转换后的head/tail部分)信息都是lock不变的,不会出现重排序
  • Lane to Lane skew
    Byte分配到不同物理lane拆包后,需要保证lane之间的skew不影响Byte重组
  • Serialized & De-Serialized
    并串/串并信号转换
    Phy

FSM状态机

下图是PCIe的状态机信息,以这个图为基础介绍下不同的状态代表的含义
FSM

  • Detect
    通过电容充放电的速度判断是否端接了Rx
  • Polling
    包括 Bit Lock + Symbol/Block Lock + Lane Polarity + Lane Data Rate 的配置和检查。
    Lock可以理解为两个PCIe设备之间相互发送特殊码进行协商,确定通信配置是否一致。
  • Configuration
    根据刚才Lock的商量结果,配置Link Width + Lane Number + Lane Reversal + De-Skew
  • Recovery
    主要用于重新建立链接或者重新配置Link/Lane的场景,常见的场景有:
    设备挂了,Lock掉了,L0直接进Recovery
    设备Rate变了,重新分配Deskew Lane2Lane,L0直接进Recovery
    L2/L1SS等 Power State变化,低功耗场景下,设备主要的Clock变化,需要重新进Detect/Recovery
    L0s这类浅度睡眠场景,短时间不会进Recovery,但是长时间还是会切state
    PS. Low-Power场景下最耗费时间的通常是上下电,而不是Clock切换或者FSM切换。
  • L0
    非低功耗模式,最基础的State,发Traffic信息流都在这个阶段。
  • L0s
    没有Traffic阶段的低功耗模式。
    由SW手动控制或者由ASPM (Active State Power Management State) 控制PCIe是否在没有Traffic阶段自动进入低功耗模式.
    或者在有Traffic阶段自动退出低功耗模式。
  • L1
    低功耗State,仅支持两种方式PCI-PM和ASPM控制Power。
    这个模式下,如果两端设备都没有拉低CLKREQ(默认为弱上拉),那就会直接进入L1SS State。
  • L2
    低功耗State,几乎所有Logic Off,只保留部分Vaux供电最低Logic。
    如果外部Device送进来Wake模拟信号(Beacon),以及Controller过来的片内Wake信号(SideBand)可以被唤醒。

PCIe枚举

首先来看枚举相关的寄存器配置,如下图所示:
枚举

在每个Function中会有256字节的寄存器配置空间,寄存器里存储的前64字节是Header信息,主要有用于Endpoint的Type0和用于Switch/bridge的Type1两种类型。
Enum Types

除了最基础的地址信息,设备ID,Status,指令等信息之外,两个Header之间的区别主要如下:
Type0类型Header不需要关注Routing相关信息(Bus Number/Latency Timer/Base/Limit)。
Type1类型Header不需要关注subsystem ID信息。

在枚举过程中,BAR - Base Address Register通过地址路由则是负责路由的基准之一,另外一种是BDF(Bus Device Func)通过ID路由。
Routing

BDF枚举后,RC(Root Complex)就可以访问任意device,RC就需要初始化每一个Device里的BAR。
一个BAR是32bits长度。
BAR初始化过程如下:

  1. 往BAR里写0xFFFFFFFF
  2. 读回来发现一部分写不了
  3. 推算出BAR大小,SW根据读到的信息(IO/MEM, 32/64 bits decode, prefetch/non-prefetch)开始写Base Address
  4. 对应设备的BAR信息固定
  5. 后续Endpoint接收data就会根据BAR信息匹配到对应的address,写入data

BAR初始化之后,地址路由主要通过RC配置的header实现地址路由。
Switch的Type1 Header里的IO/(P/NP Memory) Base/Limit信息决定可寻址的区间。
Type0 header里的BAR决定Endpoint的寻址空间(譬如BAR: 0xF9000, range就是0xF9000~0xF9FFF)
这种路由方式决定了BAR不能重复。

在BAR枚举之后,一个TLP - Transaction Layer Packet 数据包经过Switch或者 PCIe 桥片时采用哪条路径,最终到达EP或RC,也需要通过路由的方式确定。
而不同的TLP则是有不同的路由适用场景:
TLP Types


http://www.kler.cn/a/523529.html

相关文章:

  • LNMP架构
  • 【已解决】黑马点评项目Redis版本替换过程的数据迁移
  • 高级同步工具解析
  • 护眼好帮手:Windows显示器调节工具
  • SpringBoot统一数据返回格式 统一异常处理
  • Hive:日志,hql运行方式,Array,行列转换
  • TensorFlow实现逻辑回归模型
  • 本地部署 DeepSeek-R1 大模型指南:基于 Ollama 的完整流程
  • Cyber Security 101-Build Your Cyber Security Career-Security Principles(安全原则)
  • 软件工程-软件开发模型
  • RoboMaster- RDK X5能量机关实现案例(一)识别
  • .~C#循环结构
  • Vue学习四—— Home主体页面
  • 数据结构与算法分析:专题内容——人工智能中的寻路4之A*搜索(代码详解)
  • 智慧园区系统分类及其在提升企业管理效率中的创新应用探讨
  • 软件工程概论试题一
  • 服务器上安装Nginx详细步骤
  • Linux:一切皆文件
  • 差分约束系统 + spfa求最短路
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.19 排序革命:argsort的十大高阶用法
  • React中的JavaScript语法
  • MATLAB中fetchOutputs函数用法
  • 2007-2020年各省国内专利申请授权量数据
  • 【MySQL — 数据库增删改查操作】深入解析MySQL的 Update 和 Delete 操作
  • 【C++动态规划】2547. 拆分数组的最小代价|2019
  • 【论文投稿-第八届智能制造与自动化学术会议(IMA 2025)】HTML, CSS, JavaScript:三者的联系与区别