1. PCIe基础概念:从总线架构到配置空间

大家好,我是你们的讲师。今天咱们聊聊PCIe的基础概念。说实话,PCIe这玩意儿我接触了十几年,从最早的PCI到PCI-X,再到现在的PCIe 5.0、6.0,一路踩坑过来。嗯,这一章我会把最核心的东西讲清楚,让你对PCIe有个整体的认识。

1.1 PCIe总线架构:点对点的革命

先说说PCIe的总线架构。老一代的PCI总线是共享总线架构,所有设备挂在同一条线上,谁用谁抢。我当年调试一块PCI网卡,经常遇到带宽不够的问题,因为硬盘、显卡全挤在一起。

PCIe不一样,它用的是点对点串行连接。每个设备都有自己的专用通道,不用跟别人抢。说白了,就像以前大家共用一条电话线,现在每人一条专线。

核心特点:

  • 点对点连接:每个设备直连Root Complex或Switch
  • 串行传输:数据按位发送,不是并行
  • 差分信号:一对差分线(TX+、TX-)传输
  • 全双工:可以同时收发数据

我个人习惯把PCIe架构想象成高速公路系统。Root Complex就像城市中心枢纽,Switch就像立交桥,Endpoint就是各个小区。数据包在高速公路上跑,不会堵车。

1.2 拓扑结构:树形还是星形?

PCIe的拓扑结构是树形结构。为什么不是星形?你想想看,星形结构需要中心节点处理所有流量,压力太大。树形结构可以逐级转发,效率更高。

典型的拓扑包含这几部分:

  • Root Complex (RC):根复合体,连接CPU和内存
  • Switch:交换机,扩展端口数量
  • Endpoint (EP):终端设备,比如显卡、SSD
  • Bridge:桥接器,连接老设备

我记得有一次做服务器主板设计,客户要求挂32块NVMe SSD。拓扑怎么设计?用两级Switch级联,第一级接4个Switch,每个Switch再挂8个SSD。嗯,这个方案后来量产了,效果不错。

避坑指南:我曾经遇到过Switch级联深度超过限制导致链路不稳定。PCIe规范建议级联不超过5级,实际项目中我建议控制在3级以内。

1.3 分层协议:三层架构详解

PCIe协议栈分三层:事务层、数据链路层、物理层。为什么要分层?说白了就是为了解耦,每层只管自己的事。

1.3.1 事务层 (Transaction Layer)

事务层是最上层,负责处理事务层包 (TLP)。TLP是啥?就是PCIe通信的基本单位,包含读请求、写请求、完成包等。

事务层主要做这些事:

  • 生成TLP:把CPU的读写请求打包
  • 解析TLP:从收到的包中提取数据
  • 流量控制:管理缓冲区,防止溢出
  • 事务排序:保证数据一致性

我刚开始做驱动时,经常搞混Memory Read和IO Read。其实很简单:Memory Read访问内存空间,IO Read访问IO空间。现在新设备基本都用Memory Mapped IO了,IO空间很少用。

1.3.2 数据链路层 (Data Link Layer)

数据链路层在中间,负责可靠传输。它给TLP加上序列号和CRC校验,形成数据链路层包 (DLLP)。

这层的关键功能:

  • ACK/NAK协议:发送方收到ACK才确认成功
  • 重传机制:NAK或超时后重发
  • 链路管理:初始化、电源管理
  • 错误检测:CRC校验

注意:数据链路层的重传是硬件自动完成的,驱动开发者不需要操心。但如果你发现链路层频繁重传,说明物理层有问题,比如信号质量差。

1.3.3 物理层 (Physical Layer)

物理层在最底层,负责比特传输。它把DLLP编码成串行比特流,通过差分信号发送。

物理层包含:

  • 电气子层:电压、阻抗、信号速率
  • 逻辑子层:8b/10b编码(Gen1/2)或128b/130b编码(Gen3+)
  • 链路训练:协商速率、宽度

我记得调试一块PCIe Gen3的FPGA板卡,死活训练不到8GT/s。后来发现是PCB走线长度不匹配,导致信号歪斜。嗯,物理层的问题往往最难排查。

PCIe版本 单通道速率 编码方式 有效带宽
Gen1 2.5 GT/s 8b/10b 2 Gbps
Gen2 5 GT/s 8b/10b 4 Gbps
Gen3 8 GT/s 128b/130b 7.88 Gbps
Gen4 16 GT/s 128b/130b 15.75 Gbps

1.4 PCIe配置空间:设备的身份证

每个PCIe设备都有配置空间,大小是4KB。前256字节是PCI兼容区,后面是PCIe扩展区。

配置空间里有什么?

  • Vendor ID:厂商编号,比如Intel是0x8086
  • Device ID:设备编号
  • Class Code:设备类型,比如网卡、存储控制器
  • BAR (Base Address Register):基地址寄存器,定义设备的内存/IO空间
  • Capability Pointer:能力指针,指向扩展能力结构

我写驱动时,第一步就是读配置空间。用lspci命令就能看到:

# lspci -vvv -s 01:00.0
01:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller (rev 01)
        Subsystem: Samsung Electronics Co Ltd Device a801
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 47
        Region 0: Memory at f7f00000 (64-bit, non-prefetchable) [size=16K]
        Region 1: Memory at f7e00000 (64-bit, non-prefetchable) [size=1M]
        Capabilities: [40] Power Management version 3
        Capabilities: [50] MSI: Enable+ Count=1/8 Maskable- 64bit+
        Capabilities: [70] MSI-X: Enable+ Count=8 Masked-
        Capabilities: [b0] Express (v2) Endpoint, MSI 00

实用技巧:我习惯用setpci命令直接读写配置空间。比如查看BAR0地址:setpci -s 01:00.0 BASE_ADDRESS_0。调试时特别方便。

1.5 总结与思考

这一章我们讲了PCIe的四个核心概念:

  1. 总线架构:点对点串行,告别共享总线
  2. 拓扑结构:树形结构,RC、Switch、EP各司其职
  3. 分层协议:事务层、数据链路层、物理层各管一摊
  4. 配置空间:设备的身份证,驱动开发的起点

说实话,这些概念刚开始可能觉得抽象。但等你真正动手写驱动、调板子的时候,就会明白它们有多重要。下一章我们讲DMA传输原理,那才是真正开始干活的地方。

嗯,今天就到这里。有问题随时问我。