PCIe 数据链路层的主要功能时保证两台设备之间传送TLP的完整性。还负责链路的初始化和电源管理,包括跟踪链路状态以及上面的处理层和下面的物理层之间传递的消息和状况。
在管理链路时,由3组重要的DLLP:TLP确认Ack/Nak DLLP;电源管理DLLP;流控制数据包DLLP。
DLLP与TLP不同,没有携带目标信息,因为它们只用于相邻最近组件之间的通信。
当DLLP从发送器发送至接收器时,立即被处理,不能对DLLP进行流量控制。与TLP不同,DLLP没有确认协议,PCIe规范定义了超时机制,能够用来从丢失或者丢弃DLLP的状态中恢复出来。
固定大小的DLLP数据包:8个字节。所有的数据链路层数据包由如下几部分组成:①由一个字节的类型字段和3个附加属性字节组成的1DW核心,其中属性随DLLP类型的变化而变化;②一个根据DW核心内容计算的16比特CRC,附加在核心之后;③然后,把这6个字节传送至物理层,物理层给数据包添加一个DLLP开始控制字符和一个数据包结束控制字符。
DLLP中不会有数据有效载荷,所有有用信息都在类型字段和属性字段中。
1.5.1 DLLP数据包的类型
规范定义了3组DLLP,每组都有许多变体。
DLLP类型 | 类型字段编码 | 用途 |
ACK | 0000 0000b | TLP传送的完整性 |
Nak | 0001 0000b | TLP传送的完整性 |
PM_Enter_L1 | 0010 0000b | 电源管理 |
PM_Enter_L23 | 0010 0001b | 电源管理 |
PM_Active_State_Request_L1 | 0010 0011b | 电源管理 |
PM_Request_Ack | 0010 0100b | 电源管理 |
厂商专用 | 0011 0000b | 厂商 |
INitFC1-P(xxx-VC#) | 0100 0xxxb | TLP流控制 |
INitFC1-NP(xxx-VC#) | 0101 0xxxb | TLP流控制 |
INitFC1-Cpl(xxx-VC#) | 0110 0xxxb | TLP流控制 |
INitFC2-P(xxx-VC#) | 1100 0xxxb | TLP流控制 |
INitFC2-NP(xxx-VC#) | 1101 0xxxb | TLP流控制 |
INitFC2-Cpl(xxx-VC#) | 1110 0xxxb | TLP流控制 |
UpdateFC-P(xxx-VC#) | 1000 0xxxb | TLP流控制 |
UpdateFC-NP(xxx-VC#) | 1001 0xxxb | TLP流控制 |
UpdateFC- Cpl (xxx-VC#) | 1010 0xxxb | TLP流控制 |
保留 | 其他 | 保留 |
1.5.2 Ack或Nak DLLP数据包的格式
下图是接收器用来确认或否认一个TLP传送的DLLP数据包的格式。
各字段定义如下表:
字段名 | 头字节/比特 | DLLP功能 |
AckNak_Seq_Num[11:0] | 字节3的比特7:0 字节2的比特3:0 | ACK DLLP:对于接收的序列号等于EXT_RCV_SE count的正确TLP数据包,使用NEXT_RCV_SEQ count-1;对于接收的序列号小于EXT_RCV_SE count的正确TLP数据包,使用NEXT_RCV_SEQ count-1; NAK DLLP:与CRC校验失败的TLP有关,使用NEXT_RCV_SEQ count-1;对接收的序列号早于NEXT_RCV_SEQ count的TLP,使用NEXT_RCV_SEQ count-1;发送器一旦接收到NAK DLLP,它就会清除序列号等于或早于该序列号的TLP,重发剩余的TLP |
类型[7:0] | 字节0的比特7:0 | 表示DLLP的类型 0000 0000b = ACK DLLP 0001 0000b = NAK DLLP |
16比特的CRC | 字节5的比特7:0 字节4的比特7:0 | 16比特的CRC用来保护此DLLP的内用,根据ACK/NAK的字节0~3计算的 |
1.5.3 电源管理DLLP数据包的格式
PCIe电源管理DLLP和TLP数据包可代替大部分与电源管理状态变化有关的信号。用于电源管理的DLLP的格式如下图。
字段名 | 头字节/比特 | DLLP功能 |
类型[7:0] | 字节0的比特7:0 | 0010 0000b = PM_Enter_L1 0010 0001b = PM_Enter_L2 0010 0011b = PM_Active_State_Request 0010 0100b = PM_Request_Ack |
链路CRC | 字节5的比特7:0 字节4的比特7:0 | 16比特的CRC用来保护此DLLP的内用,根据ACK/NAK的字节0~3计算的 |
1.5.4 流控制数据包的格式
PCIe通过使用基于信用的流控制方案消除了早期总线协议中许多效率低下的方面。初始化信用和当接收器缓冲区空间可用时更新信用要使用3个略有不同的DLLP。两个流控制初始化数据包分别称为InitFC1和InitFC2。更新DLLP称为UpdateFC。
字段名 | 头字节/比特 | DLLP功能 |
DataFC 11:0 | 字节3的比特7:0 | 此字段含有与数据存储相关的信用。数据信用的单位时每信用16个字节,能够应用于对V[2:0]表示的虚拟信道和字节0中比特7:4代码表示的流量类别的流控制计数 |
HdrFC 11:0 | 字节2的比特7:6 字节1的比特5:0 | 此字段含有与头存储相关的信用。数据信用的单位时每信用一个头,能够应用于对V[2:0]表示的虚拟信道和字节0中比特7:4代码表示的流量类别的流控制计数 |
VC[2:0] | 字节0的比特2:0 | 此字段表示接收信用的虚拟信道(VC0~7) |
类型[3:0] | 字节0的比特7:4 | 0100b = INitFC1-P 0101b = INitFC1-NP 0110b = INitFC1-Cpl 0101b = INitFC2-P 1101b = INitFC2-NP 1110b = INitFC2-Cpl 1000b = UpdateFC-P 1001b = UpdateFC-NP 1010b = UpdateFC- Cpl |
链路CRC | 字节5的比特7:0 字节4的比特7:0 | 16比特的CRC用来保护此DLLP的内用,根据ACK/NAK的字节0~3计算的 |
1.5.5 厂商专用DLLP
字段名 | 头字节/比特 | DLLP功能 |
类型[3:0] | 字节0的比特7:4 | 厂商专用 |
链路CRC | 字节5的比特7:0 字节4的比特7:0 | 16比特的CRC用来保护此DLLP的内用,根据ACK/NAK的字节0~3计算的 |