這一篇文章來簡單地分析幾個(gè)Ack/Nak機(jī)制的例子。
Example 1. Example of Ack

Step1 設(shè)備A準(zhǔn)備依次向設(shè)備B發(fā)送5個(gè)TLP,其對(duì)應(yīng)的序列號(hào)分別為3,4,5,6,7;
Step2 設(shè)備B成功的接收到了TLP3,并將NEXT_RCV_SEQ從3加到4,但是設(shè)備B沒有立即向設(shè)備A返回Ack(此時(shí)AckNak_LATENCY_TIMER尚未溢出);
Step3 設(shè)備B又成功地接收到了TLP4和TLP5;
Step4 假設(shè)此時(shí)AckNak_LATENCY_TIMER溢出了,則設(shè)備B會(huì)向設(shè)備A返回一個(gè)帶有序列號(hào)為5的Ack DLLP。同時(shí),設(shè)備B將AckNak_LATENCY_TIMER復(fù)位,但是并未重新啟動(dòng),直到設(shè)備B成功地接收到了TLP6。
Step5 設(shè)備A接收到了Ack5,將REPLAY_TIMER和REPLAY_NUM復(fù)位,然后將Buffer中的序列號(hào)5(和5之前)的TLP備份移除;
Step6 一旦設(shè)備B接收到TLP6,AckNak_LATENCY_TIMER又會(huì)被重新啟動(dòng)。
Example 2. Ack with Sequence Number Rollover

Step1 設(shè)備A準(zhǔn)備依次向設(shè)備B發(fā)送序列號(hào)為4094,4095,0,1,2的TLP,注意第一個(gè)發(fā)送的是TLP4094,最后一個(gè)發(fā)送的是TLP2。也就是說序列號(hào)Rollover了;
Step2 設(shè)備B成功接收到TLP4094~TLP1后,假設(shè)此時(shí)AckNak_LATENCY_TIMER溢出了,則設(shè)備B向設(shè)備A返回Ack1 DLLP;
Step3 設(shè)備A接收到Ack1,并將Buffer中的序列號(hào)為1(和之前的,包括TLP4094~TLP1)的TLP備份移除。同時(shí)將REPLAY_TIMER和REPLAY_NUM復(fù)位。
Example 3. Example of Nak

Step1 假設(shè)設(shè)備A準(zhǔn)備依次向設(shè)備B發(fā)送序列號(hào)為4094,4095,0,1,2的TLP;
Step2 設(shè)備B成功地接受了TLP4094,并將NEXT_RCV_SEQ加1,變?yōu)?095;
Step3 設(shè)備B接收到了TLP4095,但是該TLP并未通過CRC校檢(即存在錯(cuò)誤)。此時(shí)無論AckNak_LATENCY_TIMER處于何種狀態(tài),設(shè)備B都會(huì)立即向設(shè)備A返回Ack4094(注意返回的Ack DLLP中的序列號(hào)為上一次成功接收的TLP的序列號(hào))。同時(shí)設(shè)備B將AckNak_LATENCY_TIMER停止并復(fù)位;
Step4 設(shè)備B會(huì)一直等待設(shè)備A向其發(fā)送TLP4095,但是設(shè)備A卻并不知發(fā)生了什么,在接收到設(shè)備B向其返回的Ack/Nak之前,會(huì)繼續(xù)發(fā)送TLP0~TLP2,只是設(shè)備B會(huì)直接忽略這些TLP。
Step5 當(dāng)設(shè)備A接收到來自設(shè)備B的Nak4094 DLLP時(shí),會(huì)將Buffer中的TLP4094(和之前的TLP)移除,并從TLP4095從新開始發(fā)送。同時(shí),將REPLAY_TIMER復(fù)位。
注:Mindshare書中,此處說還會(huì)復(fù)位REPLAY_NUM,這是不正確的。
Step6 由于設(shè)備A接收到的是Nak,而不是Ack,因此設(shè)備A會(huì)重新啟動(dòng)REPLAY_TIMER并將REPLAY_NUM加一;
Step7 一旦設(shè)備B成功地接收到TLP4095,設(shè)備B便會(huì)清除NAK_SCHEDULED標(biāo)志位,并將NEXT_RCV_SEQ計(jì)數(shù)器加一,同時(shí)重啟AckNak_LATENCY_TIMER。
Example 4. Example of Lost TLPs

Step1 假設(shè)設(shè)備A準(zhǔn)備依次向設(shè)備B發(fā)送TLP 4094,4095,0,1,2;
Step2 設(shè)備B成功地接收了TLP4094~TLP0,并向設(shè)備A返回Ack0,此時(shí)設(shè)備B的NEXT_RCV_SEQ為1;
Step3 設(shè)備A接收到設(shè)備B返回的Ack0,從Buffer中移除相應(yīng)的TLP備份;
Step4 設(shè)備B接收到了TLP2(而不是TLP1),也就是說TLP1在傳輸過程中丟失了。此時(shí),設(shè)備B會(huì)直接將TLP2丟棄,并將NAK_SCHEDULED標(biāo)志位置位,同時(shí)向設(shè)備A返回Nak0 DLLP;
Step5 設(shè)備A接收到Nak0 DLLP后,會(huì)將Buffer中的TLP0(以及之前的,如果有的話)移除。同時(shí),從TLP1開始,重新向設(shè)備B發(fā)送。
Example 5. Example of Bad Nak

Step1 設(shè)備A準(zhǔn)備依次向設(shè)備B發(fā)送TLP 4094,4095,0,1,2;
Step2 設(shè)備B成功的接收了TLP4094~TLP0,但是由于AckNak_LATENCY_TIMER尚未溢出,所以設(shè)備B沒有立即向設(shè)備A返回Ack DLLP;
Step3 設(shè)備B發(fā)現(xiàn)TLP1中存在錯(cuò)誤,于是向設(shè)備A返回Nak0 DLLP,并將NAK_SCHEDULED標(biāo)志位置位;
Step4 設(shè)備A發(fā)現(xiàn)其接收到的Nak0 DLLP中也存在錯(cuò)誤(CRC校檢不通過),于是直接丟棄了Nak0;
Step5 然而設(shè)備B卻一直在等待設(shè)備A向其發(fā)送TLP1,在其成功接收TLP1之前,設(shè)備B不會(huì)返回任何Ack或者Nak,不管設(shè)備A向其發(fā)送什么(除TLP1之外的)。設(shè)備B的NAK_SCHEDULED標(biāo)志位也一直保持置位;
Step6 尷尬的是,設(shè)備A并不知道設(shè)備B想要其重發(fā)TLP1(由于沒有成功接收到Nak0)。因此,設(shè)備A會(huì)繼續(xù)向設(shè)備B發(fā)送之后的TLP,但是由于一直沒有接收到設(shè)備B的Ack/Nak DLLP,設(shè)備A的REPLAY_TIMER會(huì)在一段時(shí)間后溢出;
Step7 當(dāng)設(shè)備A的REPLAY_TIMER溢出后,設(shè)備A會(huì)向Buffer中的所有TLP都重新發(fā)送一遍,并重啟REPLAY_TIMER,同時(shí)將REPLAY_NUM計(jì)數(shù)器加一;
Step8 設(shè)備B會(huì)再次接收到TLP4094~TLP0,但是這在之前就已經(jīng)成功接受到過了。因此設(shè)備B會(huì)直接將其丟棄,且不會(huì)像設(shè)備A返回任何的Ack或者Nak
Step9 此時(shí),設(shè)備B再次接收到了TLP1,并未發(fā)現(xiàn)錯(cuò)誤(成功接收)。于是,設(shè)備B將NAK_SCHEDULED標(biāo)志位清零,并重啟AckNak_LATENCY_TIMER,將NEXT_RCV_SEQ加一。
-
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2316瀏覽量
98207 -
TLP
+關(guān)注
關(guān)注
0文章
37瀏覽量
16495
原文標(biāo)題:【博文連載】PCIe掃盲——Ack/Nak 機(jī)制詳解(二)
文章出處:【微信號(hào):ChinaAET,微信公眾號(hào):電子技術(shù)應(yīng)用ChinaAET】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
CY7C65215A作為從站,在主站寫入時(shí)響應(yīng)NAK是怎么回事?
什么是ACK (ACKnowledge Character)
24C02中IIC總線的應(yīng)答信號(hào)(ACK)時(shí)序圖分析
CAN總線波形中為什么ACK電平偏高?
PCIe總線的通信機(jī)制
Ack/Nak機(jī)制詳細(xì)介紹
PCIe鏈路層里的ACK/NAK介紹
python最簡單for循環(huán)例子
CAN總線波形中為什么ACK電平偏高?
簡單地分析幾個(gè)Ack/Nak機(jī)制的例子
評(píng)論