第1章 PCIe总线概述:从并行到串行的蜕变
做嵌入式或FPGA开发的朋友,对PCIe应该不陌生。但要说清楚它到底怎么来的、跟老一代PCI有什么区别,很多人可能就含糊了。这一章,我们先把这个基础框架搭好。
1.1 PCIe发展历程:踩过的坑和爬过的坡
PCIe的历史不长,但迭代很快。2003年PCI-SIG发布1.0a规范,单通道2.5GT/s。那时候大家觉得挺快,其实现在看就是小水管。后来2.0翻倍到5GT/s,3.0把编码从8b/10b改成了128b/130b,效率大涨。4.0到16GT/s,5.0到32GT/s,6.0更是跳到了64GT/s,还用了PAM4。
我个人习惯把这几代分成两个阶段:编码时代(1.0/2.0)和效率时代(3.0及以后)。
| 版本 | 发布年份 | 单通道速率 | 编码方式 | 有效带宽 |
|---|---|---|---|---|
| PCIe 1.x | 2003 | 2.5 GT/s | 8b/10b | 2.0 Gb/s |
| PCIe 2.x | 2007 | 5.0 GT/s | 8b/10b | 4.0 Gb/s |
| PCIe 3.x | 2010 | 8.0 GT/s | 128b/130b | 7.88 Gb/s |
| PCIe 4.x | 2017 | 16.0 GT/s | 128b/130b | 15.76 Gb/s |
| PCIe 5.x | 2019 | 32.0 GT/s | 128b/130b | 31.52 Gb/s |
1.2 PCIe架构层次:三层结构别搞混
PCIe的协议栈分为三层:事务层、数据链路层、物理层。你想想看,跟网络OSI模型有点像,但更精简。
- 事务层(Transaction Layer):负责生成和解析TLP(事务层包)。比如你要读一个设备的配置空间,事务层就组装一个Memory Read Request TLP往下送。
- 数据链路层(Data Link Layer):在TLP外面加序列号、CRC校验,还有ACK/NAK重传机制。说白了,保证数据不丢、不错。
- 物理层(Physical Layer):最底层,含电气子层和逻辑子层。并串转换、时钟恢复、差分信号的发送接收都在这里。
很多工程师只关心事务层,因为驱动开发主要跟TLP打交道。但调试高速信号时,数据链路层的错误计数、物理层的眼睛图,才是关键。我记得有一次查链路不稳定,查了半天TLP重传,最后发现是物理层的高频去耦电容没焊好。
1.3 与PCI/PCI-X的差异:从并行到点对点
PCI和PCI-X是老前辈了。PCI是33/66MHz的并行共享总线,所有设备挂在同一组信号线上。你想想看,一个设备占用总线,其他都得等着。PCI-X提高了频率到133/266MHz,但本质还是并行,skew和负载效应是硬伤。
PCIe完全不同:点对点串行差分链路,每个设备有自己的独立通道(Lane),全双工同时收发。而且支持多通道绑定(x1, x4, x8, x16),带宽线性叠加。
| 特性 | PCI / PCI-X | PCIe |
|---|---|---|
| 总线拓扑 | 共享并行总线 | 点对点交换架构 |
| 信号方式 | 单端,多地线 | 差分对(Tx+, Tx- / Rx+, Rx-) |
| 时钟 | 同步公共时钟 | 内嵌时钟(CDR恢复) |
| 带宽扩展 | 提高频率很难 | 增加通道数或提高速率 |
| 热插拔 | 软件支持差 | 原生硬件支持 |
| 配置空间 | 256字节 | 4096字节(增强型) |
嗯,这里要注意:PCIe的配置空间扩展到了4KB,支持更多的Capability结构,比如电源管理、MSI中断等。你在写驱动时要遍历这些Capabilities,不能用PCI的老方法。
inl() outl()的地方,一定要改成ioread32() iowrite32()。
1.4 小结:从架构角度看PCIe调试
搞懂这三层架构,对后面的解码和触发配置特别重要。你想想看,触发条件是在事务层拦截TLP包,还是数据链路层看CRC错误?解码的时候,你要解析的是TLP头还是物理层的Ordered Set?没有这个框架,配置逻辑根本写不出来。
我个人习惯在调链路时,先看物理层的链路训练状态机(LTSSM),确定是否进入了L0。然后再看数据链路层的DL_Up状态。最后才在事务层抓包。这个顺序,一步错,调试效率至少降一半。