高級FPGA開發(fā)之基礎協(xié)議之PCIe(二)
一、TLP報文類型
在PCIe總線中,存儲器讀寫、I/O讀寫和配置讀寫請求TLP主要由以下幾類報文組成:

1.1 存儲器讀請求TLP和讀完成TLP
當PCIe主設備(RC或者EP)訪問目標設備的存儲器空間時,使用non-posted總線事務向目標設備發(fā)出存儲器讀請求TLP,目標設備收到這個存儲器讀請求tlp后,使用存儲器讀完成tlp,主動向主設備傳遞數據。當主設備收到目標設備的存儲器讀完成tlp后,將完成一次存儲器讀請求。
1.2 存儲器寫請求tlp
在PCIe總線中,存儲器寫使用posted總線事務。PCIe主設備僅使用存儲器寫請求tlp即可完成存儲器寫操作,主設備不需要目標設備的回應報文。
1.3 原子操作請求和完成報文
原子操作由PCIe V2.1總線規(guī)范引入,一個完整的原子操作包括原子操作請求和原子操作完成報文組成。
原子操作的使用方法與其他non-posted總線事務類似。
首先PCIe主設備向目標發(fā)送原子操作請求,之后目標設備向主設備發(fā)送原子操作完成報文,結束一次原子操作。
1.4 IO讀寫請求TLP和讀寫完成TLP
在PCIe總線中,IO讀寫操作使用non-posted,IO讀寫TLP讀需要完成報文作為回應。只是在IO寫請求的完成報文中不需要”帶數據“,而僅含有IO寫請求是否成功的狀態(tài)信息。
1.5 配置讀寫TLP和配置讀寫完成TLP
從總線事務的角度來看,配置讀寫請求的操作工程和IO讀寫操作的過程類似。
配置讀寫請求 TLP 都需要配置讀寫完成作為應答,從而完成一個完成的配置讀寫操作。
1.6 消息報文
和PCI總線相比,PCIe總線增加了消息請求事務。PCIe總線使用基于報文的數據傳送模式,所有總線都是通過報文實現(xiàn)的,PCIe總線取消了一些在PCI總線中存在的邊帶信號。
在PCIe總線中,一些由PCI總線的邊帶信號完成的工作,比如中斷請求和電源管理等,在PCIe總線中由消息請求報文實現(xiàn)。
二、TLP報文詳解
2.1 存儲器讀寫請求TLP
存儲器讀寫請求TLP的格式如下圖:


在PCIe總線上,存儲器寫請求TLP使用posted數據傳送方式。而其他與存儲器和IO相關的報文都使用split方式進行數據傳送,這些請求報文需要完成報文,存儲器讀寫請求TLP使用地址路由方式進行數據傳遞。
length段:
在存儲器讀請求TLP中,length字段表示需要從目標設備數據區(qū)域讀取的數據長度。
在存儲器寫TLP中,length字段表示當前報文的data payload長度。
length字段的最小單位是DW。當字段為n時,表示需要獲取的數據長度或者當前報文的數據長度為n個DW。注意n=0,表示長度為1024的DW。
DW BE字段:
PCIe總線以字節(jié)為基本單位進行數據傳輸的,但是length字段以DW為最小單位。為此,TLP使用last DW BE和First DW BE這兩個字段進行字節(jié)使能,使得在一個TLP中,有效數據以字節(jié)為單位。
這兩個 DW BE 字段各由4位組成,其中 Last DW BE 字段的每一位對應數據 Payload 最后一個雙字的字節(jié)使能位;而 First DW BE 字段的每一位對應數據 Payload 第一個雙字的字節(jié)使能位。其對應關系如下圖所示。

“Zero-Length”讀請求的引入是為了實現(xiàn)“讀刷新”操作,該操作的主要目的是為了確保之前使用 Posted 方式所傳送的數據,到達最終的目的地,與“Zero-Length”讀對應的讀完成報文中不含有負載,從而提高了 PCIe 鏈路的利用率。
requester ID:
requester ID字段包含生成這個TLP報文的PCIe設備的總線號(bus number)、設備號(device number)、功能號(function number)。
對于non-posted數據請求,目標設備需要使用完成報文作為回應。在這個完成報文中,需要使用源設備的requester ID字段。
因此在non-posted數據請求TLP中,如存儲器讀請求、IO和配置讀寫請求、必須使用requester ID字段。
IO讀寫請求TLP規(guī)則:
I/O 讀寫請求 TLP 只能使用32位地址模式和基于地址的路由方式且只能使用 Non-Posted 方式進行傳遞。
2.2 完成報文TLP
PCIe 總線支持 Split 傳送方式,目標設備使用完成報文向源設備主動發(fā)送數據。
完成報文使用 ID 路由方式,由 TLP Predix、報文頭和 Data Payload 組成,但是在某些完成報文可以不含有 Data Payload,如 I/O 或者配置寫完成和 Zero-Length 讀完成報文。
所有的數據讀請求,包括存儲器、I/O 讀請求、配置讀請求和原子操作請求。當一個PCIe設備發(fā)出這些數據請求報文后,必須收到目標設備的完成報文后,才能結束一次數據傳送。這一類完成報文必須包含 Data Payload。完成報文格式如下圖:

requester ID和tag字段:
完成報文使用ID路由方式。完成報文頭的長度為3DW,完成報文頭中包含了transaction ID,由requester ID和tag字段組成,這個ID必須和源設備發(fā)送的數據請求報文的tansaction ID對應,完成報文使用transaction ID進行ID路由,并將數據發(fā)送給源設備。
當PCIe設備收到存儲器讀、IO讀寫或者配置讀寫請求TLP時,需要首先保證保存這些報文的transaction ID,之后當該設備準備好完成報文后,將完成報文requester ID和tag ID字段賦值為之前保存的transaction ID字段。
completer ID字段:
completer ID字段的含義與requester ID字段較為相似,只是該字段存放發(fā)送完成報文的PCIe設備的ID號。
PCIe設備進行數據請求時需要在TLP字段中包含requester ID字段,而完成報文結束數據請求時,需要提供completer ID字段。
status字段:
status字段保存當前完成報文的完成狀態(tài),表示當前TLP是正確地將數據傳遞給數據請求端,還是在數據傳輸過程中出現(xiàn)錯誤,或者要求數據請求方式進行重試。

BCM 位與 Byte Count 字段:
bcm(byte count modified)字段由pci-x設備設置的。
pci-x設備也支持split transaction傳送方式。當pci-x設備進行存儲讀請求時,且目標設備不一定一次將所有數據傳遞給源設備。此時目標設備在進行第一次數據傳送時,需要設置byte count字段和bcm位。
bcm位表示byte count字段是否被更改,該位僅對pci-x設備有效,而PCIe設備不能操作BCN位。
byte count字段記錄源設備還需要從目標設備中,獲取多少字節(jié)的數據就能完成全部數據傳遞,當前的TLP中的有效負載也被byte count字段統(tǒng)計在內。該字段由12位組成。
該字段為0b0000-0000-0001表示還剩一個字節(jié),為0b1111-1111-1111表示還剩4095個字節(jié),而為0b0000-0000-0000表示還剩4096個字節(jié)。
除了存儲器讀請求的完成報文外,大多數完成報文的 Byte Count 字段為4。
lower address字段:
如果當前完成報文為存儲器讀完成TLP,該字段存放在存儲器讀完成TLP中第一個數據所對應地址的最低位。
值得注意的是,在讀完成報文中,并不存在first DW BE和last DW BE字段。
因此接收端必須使用存儲器讀完成 TLP 的 Low Address 字段,識別一個 TLP 中包含數據的起始地址。
配置讀寫請求 TLP:
配置讀寫請求 TLP 由 RC 發(fā)起,用來訪問 PCIe 設備的配置空間。配置請求報文使用基于ID 的路由方式。PCIe 總線也支持兩種配置請求報文,分別為 Type 00h 和 Type 01h 配置請求。配置請求 TLP 的格式如下圖。

消息請求報文:
在 PCIe 總線中,多數消息報文使用隱式路由方式,其格式如下圖:

)
PCIe 總線規(guī)定了以下幾類消息報文:
INTx 中斷消息報文(INTx Interrupt Signaling);
電源管理消息報文(Power Management);
錯誤消息報文(Error Signaling);
鎖定事務消息報文(Locked Transaction Support);
插槽電源限制消息報文(Slot Power Limit Support);
Vendor-Defined Messages;
三、TLP中與數據負載相關的參數
在 PCIe 總線中,有些 TLP 含有 Data Payload,如存儲器寫請求、存儲器讀完成 TLP 等。
在 PCIe 總線中,TLP 含有的 Data Payload 大小與 Max_Payload_Size、Max_Read_Request_Size和 RCB 參數相關。
Max_Payload_Size 參數:
PCIe 總線規(guī)定在 TLP 報文中,數據有效負載的最大值為4KB,但是 PCIe 設備并不一定能夠發(fā)送這么大的數據報文。PCIe 設備含有“Max_Payload_Size”和“Max_Payload_SizeSupported”參數,這兩個參數分別在Device Capability 寄存器和Device Control寄存器中定義。
PCIe設備發(fā)送數據報文時,使用Max_Payload_Size 參數決定 TLP 的最大有效負載。當PCIe 設備的所傳送的數據大小超過 Max_Payload_Size 參數時,這段數據將被分割為多個 TLP進行發(fā)送。
Max_Payload_Size參數的大小與 PCIe 鏈路的傳送效率成正比,該參數越大,PCIe鏈路帶寬的利用率越高,該參數越小,PCIe 鏈路帶寬的利用率越低。
Max_Read_Request_Size 參數:
Max_Read_Request_Size 參數由 PCIe 設備決定,該參數規(guī)定了 PCIe 設備一次能從目標設備讀取多少數據。
PCIe 總線規(guī)定存儲器讀請求,其讀取的數據長度不能超過 Max_Read_Request_Size 參數,即存儲器讀 TLP 中的 Length 字段不能大于這個參數。如果一次存儲器讀操作需要讀取的數據范圍大于 Max_Read_Request_Size 參數時,該 PCIe 設備需要向目標設備發(fā)送多個存儲器讀請求 TLP。
RCB 參數:
RCB 位在 Link Control 寄存器中定義。RCB 位決定了 RCB 參數的值,在 PCIe 總線中,RCB 參數的大小為64B 或者128B,如果一個 PCIe 設備沒有設置 RCB 的大小,則 RC 的 RCB參數缺省值為64B,而其他 PCIe 設備的 RCB 參數的缺省值為128B。PCIe 總線規(guī)定 RC 的 RCB參數的值為64B 或者128B,其他 PCIe 設備的 RCB 參數為128B。
Read Completion Boundary (RCB),讀完成邊界,是 Completer 響應讀請求的一種地址邊界對齊策略,應用于 CplD。

第一筆completion必須開始于request的起始地址,當request的length不大于RCB時不進行切分,當request的length大于RCB時在RCB處結束。
最后一筆completion返回的地址必須滿足所有completion payload長度滿足request的length。
所有中間的completions payload大小必須滿足RCB。
1. Read request length 不大于RCB
例如RCB為128 Byte,read request length 小于128 Byte。這時不會返回multi-completions,所以不會對返回包進行切分,從request的起始地址讀夠length長度的數據返回。
Read request length 大于RCB,這種情況會返回multi-completions,且與起始地址有關系
例如:
1. 例如RCB為128 Byte,read request length 為200 Bytes,起始地址為0X60。這時會有三筆completion返回,
第一筆從0X60開始讀取32 Bytes數據,第二筆數據從0X80開始讀取128 Bytes數據,第三筆從0X100地址開始讀取40 Bytes數據。
2. 例如RCB為128 Byte,read request length 為200 Bytes,起始地址為0X10。這時會有兩筆completion返回,
第一筆從0X10開始讀取112 Bytes數據,第二筆數據從0X80開始讀取88 Bytes數據。
四、未完待續(xù)
下章將繼續(xù)介紹核心的基本概念:內核態(tài)的線程/進程技術。
歡迎關注知乎:北京不北,+vbeijing_bubei
歡迎關注douyin:near.X (北京不北)
歡迎+V:beijing_bubei
獲得免費答疑,長期技術交流。