第2章:PCIe体系结构简介
聊LTSSM之前,我建议大家先把PCIe的整体架构摸清楚。你想想看,链路训练说白了就是让两边的设备能对上话,但你连对话的双方是谁、中间有什么角色、消息怎么传递都不清楚,那学状态机就只能死记硬背了。
记得我最早接触PCIe时,上来就啃LTSSM的12个状态,结果越看越晕。后来一位老前辈跟我说:“你先别管状态机,先把PCIe这棵树长什么样画出来。”从那以后,我才算真正入了门。
2.1 从并行到串行:PCIe的诞生
早期的PCI总线是并行架构,32位或64位数据线一起走。听起来很美好对吧?但实际上,并行信号有个大麻烦——信号偏移(Skew)。
每条线的传播延迟稍微不一样,频率一高,数据就乱了。PCI/PCI-X最高跑到533 MHz,再往上就上不去了。我在一个老项目中修过PCI-X的时序问题,那叫一个痛苦——换了几版PCB都没搞定,最后只能降频。
PCIe换了个思路:串行差分信号。一对差分线(TxP/TxN或RxP/RxN)就是一个Lane,数据一位一位传。频率可以拉得非常高,而且没有Skew问题。PCIe 1.0单Lane就到了2.5 GT/s,比PCI-X快多了。
2.2 PCIe系统拓扑结构
一个典型的PCIe系统长什么样?我用一张图给你讲清楚。
你看这张图,从上到下分成了几个层次:
- Root Complex (RC):CPU和内存的接口,是整个PCIe层次结构的根。我习惯把它想象成“交通指挥中心”。
- 交换器 (Switch):负责把RC的一个端口扩展成多个端口。它由多个虚拟PCI-PCI桥组成,数据包在这里做转发。
- 端点 (Endpoint, EP):实际的功能设备,比如网卡、GPU、NVMe SSD。EP只消费或产生事务,不转发。
- 桥 (Bridge):用来连接PCIe和传统PCI总线,做协议转换。
要点提醒:LTSSM只存在于物理层(PHY),但它管理的是整个链路的建立和维护。你看到上图每两个设备之间的那条线,就是LTSSM要管的事。
2.3 层次化架构:三层分工
PCIe使用层次化架构,从顶到底分为三层。每层只跟相邻层打交道,职责非常清晰。
| 层级 | 核心职责 | 关键数据单元 |
|---|---|---|
| 事务层 (Transaction Layer) | 生成和接收事务层包(TLP),管理事务排序、流量控制、虚拟通道 | TLP(Transaction Layer Packet) |
| 数据链路层 (Data Link Layer) | 提供可靠传输,包括CRC校验、ACK/NAK重传、链路管理 | DLLP(Data Link Layer Packet) |
| 物理层 (Physical Layer) | 串并转换、比特传输、链路初始化与训练(LTSSM就在这里!) | PLP(Physical Layer Packet)、有序集合(Ordered Sets) |
三层各有各的包格式,但它们之间不是孤立的。物理层发的有序集合(比如TS1/TS2),直接驱动LTSSM的状态跳转。
2.4 深入各层:看看它们干了什么
2.4.1 事务层——PCIe通信的“内容”
事务层负责跟软件打交道。你的驱动程序要读取设备寄存器,或者把内存中的数据发到网卡,这些请求都由事务层打包成TLP。
TLP有四种主要类型:Memory、IO、Configuration、Message。我建议你重点记住Memory读写,因为日常开发中90%的事务都是它。
避坑提示:我曾经遇到一个GPU驱动挂死的问题。调了一周,最后发现是TLP中的Length字段填错了——驱动代码里把字节数写成了DWord数。事务层要的数据跟物理层实际传输的数据不匹配,链路直接挂起。
2.4.2 数据链路层——可靠的“搬运工”
数据链路层在TLP外面套了一个帧头,加上一个32位的CRC(LCRC),然后发给物理层。它还会等接收端回复ACK或NAK。
- 收到ACK:TLP发送成功,从重发缓冲区里清除。
- 收到NAK:TLP发送失败,必须重新发送。
- 超时没收到回复:也重新发送。
这个机制叫ACK/NAK重传协议。说白了,就是物理层只管发,数据链路层要确认对方真的收到了。我手头有个项目,刚开始测试时偶尔出现丢包,追到最后发现是接收端LCRC校验逻辑里的一个时序问题。
2.4.3 物理层——LTSSM的大本营
物理层分为两个子层:逻辑子层和电气子层。
- 逻辑子层:包含LTSSM、加扰/解扰、8b/10b编码(PCIe 1.0/2.0)或128b/130b编码(PCIe 3.0+)、弹性缓冲区。
- 电气子层:包含SerDes(串化器/解串器)、差分驱动器和接收器、PLL时钟恢复电路。
LTSSM是逻辑子层的核心,它管理着链路从复位到正常工作的每一个步骤。
一个小技巧:当你用协议分析仪抓取PCIe流量时,物理层的有序集合(如TS1/TS2、SKP、FTS)会在逻辑子层被剥离,所以你看到的抓包数据直接就是TLP。但如果链路训练失败了,你只能看到反复出现的TS1/TS2,不会有任何TLP。——记住这个现象,实际抓debug时很有用。
2.5 一个重点概念:Lane与链路宽度
PCIe的Lane是一对差分发送和一对差分接收构成的双向通道。每个Lane是独立的,但多个Lane可以绑在一起,形成一个链路(Link)。
| 链路宽度 | x1 | x2 | x4 | x8 | x16 |
|---|---|---|---|---|---|
| Lane数 | 1 | 2 | 4 | 8 | 16 |
| 常见用途 | 网卡、Wi-Fi模块 | SSD(少数) | NVMe SSD、RAID卡 | 显卡(中端) | 显卡(旗舰) |
LTSSM在训练时,会做一件关键的事——宽度协商。两端设备先各自声明“我能支持x16”,然后通过交换训练序列确定最终的宽度。如果一个x16的显卡插到x8的插槽上,LTSSM最终就会协商成x8。
经验之谈:我调试过一块主板,x16插槽只能跑x1。用示波器量着量着发现,有一对差分线的过孔处阻抗不连续。LTSSM在宽度协商时会检测到某些Lane的电气质量不达标,自动降级。硬件工程师看到这种问题,千万不要直接怀疑LTSSM的软件实现——先查信号完整性。
哦对了,还有一点要注意:LTSSM对每个Lane是独立训练的,但链路作为一个整体进入某状态。举个例子,在Polling状态,每个Lane各自检测接收器是否工作,但所有Lane都完成后,整个链路才一起进入Configuration。
好了,PCIe体系结构的骨架已经有了。下一层要往里边填充的,就是LTSSM这个真正驱动链路“跑起来”的状态机。别着急,咱们一章一章来拆。