USB封包格式
1.起始(SOP)封包
根集線器會在每1 ms時,送出SOF封包。這介于2個SOF封包之間的時間,即稱為幀(frame)。SOF封包雖是屬于令牌封包的一種,但卻具有獨自的PID形態(tài)名稱SOF。通常目標設各都利用SOF封包來辨識幀的起點。這個封包常用于等時傳輸。也就是在1 ms的幀(高速是125 μS微幀,將1 ms切成8份)開始時,等時傳輸會利用SOF激活傳輸并達到同步傳輸?shù)淖饔?。而在每一個幀開始時,SOF會傳給所有連接上去的全速設各(包含集線器)。因此,SOF封包并不適用于低速設備。這個封包內包含了一個幀碼,其可不斷地遞增,且在高達最大值時反轉為0,重新再計
數(shù)一次。這個幀碼是用來表示幀的計數(shù)值,因此,8個微幀都使用同一個幀碼值。若必要時,高速設各可計算出SOF的重復使用次數(shù),并計算出微幀的數(shù)量。通過縮短微幀的周期時間,便可減少高速設各對于緩沖存儲器的需求。
如圖1所示,高速的根集線器將會使用額外的SOF來傳輸8個微幀。有些書籍會把這種高速的SOF,另命名為uSOF。這種增加的微幀,同時也替高速的連接帶來了更復雜的控制方式。
圖1 USB幀與微幀示意圖
此外,再利用如圖2所示的簡圖來說明主機所送出的一個SOF封包的格式。其中,SOF的封包標識符,PID數(shù)據(jù)域的值為0xA5。PID[3:o]=0101與PID[3:o]=1010所產生的,只不過它的傳送順序須由LSB→MSB。因此,即可推算出0xA5。以下,所有的PID數(shù)據(jù)域皆可由此推算而得到。
圖2 SOF封包的各種組成字段
圖2顯示了SOF封包的各種字段與相關的定義。
此外,端點可以通過SOF封包來加以同步,或是以幀碼值來作為時間的參考依據(jù)。當整個USB總線上沒有USB傳輸時,SOF封包也可避免讓設備切人低功率的中止(suspend)狀態(tài)。再者,雖然在低速設各上,是看不到SOF封包的,但相反,設各的集線器使用了前面所提及的BOP(End of-Packet)信號,且在每一個幀設置一次。因此,有時后也稱這種信號為設各的低速存活(keep alive)信號。所以說,SOF/uSOF封包是給全速/高速設各來使用的,而低速存活信號卻可避免讓低速設備切入中止狀態(tài)中。
2.令牌封包
由于USB的數(shù)據(jù)交易是由PC主機端所激活的,所以在每一個數(shù)據(jù)交易中,必須以下列的5個數(shù)據(jù)域所組合而成的令牌封包作為起始,并執(zhí)行通信協(xié)議的前導工作。一個令牌封包含蓋了5個數(shù)據(jù)域SYNC、PID、ADDR、ENDP與CRC5。這即是54233的第1個數(shù)字:5。如下所列為其令牌封包的各個組成的數(shù)據(jù)域。
令牌封包的PID數(shù)據(jù)域(PID[1:0]=[0,1])中包含了OUT、IN、SETUP這3種PID類型名稱。也就是包含了OUT令牌封包、IN令牌封包以及SETUP令牌封包。例如,在執(zhí)行控制傳輸主機要通過預設的地址取得設備描述符(Get ̄Descriptor),就必須先執(zhí)行下列的SETUP令牌封包,作為每一次控制傳輸?shù)拈_始,其中,PID欄變成SETUP的PID類型名稱(0xB4)。IN令牌封包,則是主機用來通知設備,將要執(zhí)行數(shù)據(jù)輸入的工作。而OUT令牌封包則剛好相反。
圖3 顯示了PC主機所起始的SETUP令牌封包。
圖3? 令牌封包的各種組成的字段
3.數(shù)據(jù)封包
在USB接口中,主機執(zhí)行了總線的管理、數(shù)據(jù)傳輸以及設各對主機所提出的要求命令作出響應的動作。這些所要傳輸?shù)臄?shù)據(jù)與要求命令是什么呢?因此,必須通過數(shù)據(jù)封包來執(zhí)行這項工作。
而由SETUP、IN與OUT令牌封包所起始的數(shù)據(jù)傳輸,將會以DATAO、DATA1、DATA2與MDATA封包來加以實現(xiàn)。一個數(shù)據(jù)封包含了4個數(shù)據(jù)域:SYNC、PID、DATA與CRC16。各個字段的意義之前已有介紹過。這即是54233的第2個數(shù)字:4。在這里,要稍微注意的是DATA字段內所放置的位值,須根據(jù)USB設各的傳輸設備(低速、高速與全速)以及傳輸類型(中斷傳輸、批量傳輸與等時傳輸)而定,且須以所設置的MaxPackSize字節(jié)為基本單位。也即是,若傳輸?shù)臄?shù)據(jù)不足MaxPackSize字節(jié),或是傳輸?shù)阶詈笏S嗟囊膊蛔鉓axPackSize字節(jié),則仍須傳輸MaxPackSize個字節(jié)的數(shù)據(jù)域。
列出由4個數(shù)據(jù)域所組合而成的數(shù)據(jù)封包。
數(shù)據(jù)封包的PID數(shù)據(jù)域(PID[1:0]=[1:1])包含了4種類型:DATA0、DATA1、DATA2與MDATA。而根據(jù)USB規(guī)范,最初的數(shù)據(jù)封包都以DATA0作為開始,其后才是DATA1,然后依此方式交替切換。這個動作稱之為數(shù)據(jù)緊密連接(data toggle)。這個動作有點類似將數(shù)據(jù)緊密連接。如此就可確保整個傳輸過程中,主機能與設各維持同步,且作為幀錯之用。例如,如果兩個連續(xù)的DATA0被接收到的話,意味著DATA1封包被遺漏掉,并產生了錯誤的狀況。而DATA2與MDATA,則僅適用于高速的等時傳輸。
若主機要針對特別尋址的設各端點,送出取得設各描述符的命令,就可如圖4所示,將含有命令的數(shù)據(jù)封包傳出。其中,須特別注意的是,由于是控制傳輸,所以數(shù)據(jù)域中僅有8字節(jié)。至于“8006 0001 000040”的設備要求的意義。
圖4 數(shù)據(jù)封包的各種組成字段
4.握手封包
握手封包是最簡單的封包類型。在這個握手封包中,僅包含一個PID數(shù)據(jù)域。它的格式如下所列,僅包含SYNC與PID兩個數(shù)據(jù)域,這即是54233的第3個數(shù)字:2。
握手封包的PID數(shù)據(jù)域(PID[1:0]=[1:0])中包含了ACK、NAK、STALL與NYET這4種PID類型名稱。也就是含有ACK、NAK、STALL與NYET握手封包。
延伸上一個圖例,如果設備已收到主機要執(zhí)行取得設備描述符的命令,設備就以握手封包來加以響應。因此須注意的是,如果設備已準備接收的話就以ACK握手封包響應;如果尚未就緒就使用NAK握手封包響應;如果發(fā)生錯誤而停滯,就使用STALL握手封包響應。圖5顯示一個握手封包的格式,其中ACK的PID數(shù)據(jù)域值為Ox4B,剛好與SETUP的PID數(shù)據(jù)域值相反。
圖5 握手封包的各種組成字段
通過上述的3個封包,即可組成一個數(shù)據(jù)交易。當然,這即是54233的第4個數(shù)字:3。
對于高速設備,為了改善NAK的機制,特別支持了NYET握手封包。這是由于當數(shù)據(jù)已經傳輸至總線時,通過NAK這個OUT數(shù)據(jù)交易的動作是不夠的。況且若是在總線上存在著高頻率的NAK傳輸過程,將會使得整個總線逐漸地被拖累,帶寬被分享掉。此時,高速設各就可以使用特殊的PING封包(稍后會提及)來詢問,是否接收器還有緩沖區(qū)空間來接收OUT數(shù)據(jù)交易。如果設各以ACK來響應,那么傳送器就會安排
OUT傳輸。反之,如果響應的是NYET,那么傳送器就會以PING封包來查詢。如此,總線上就會有最佳的使用率。
5.特殊封包
總共包含了4個特殊封包(PRE、ERR、SPLIT與PING)。其中,一個僅使用在低速設備,一個僅使用在高速設各,其余兩個則是針對當?shù)退倩蚴侨僭O備連接上USB 2.0集線器后,再以高速的方式與主機通信時,才會用到。
(1)PRE封包
這個特殊前置(Special Preamble,PRE)封包擁有獨自的PID類型名稱PRE,其僅適用于主機想要從高速傳輸變成低速傳輸時所送出來的情形。也就是主機對于下端端口送出低速封包與低速設備通信之前,所必須先送出的PRE封包。在該PRE封包中,包含了前置碼以告訴集線器,下一個封包是低速。如此,集線器將會以即將接上的低速設備開始執(zhí)行通信的工作。此時,PRE封包會放在導引至低速設各的所有令牌、數(shù)據(jù)以及握手封包之前。而高速設各是將PRE以SPLIT封包來加以編碼,因此不會重復地送出。對于原本已是低速的設備來說,不需要PRE封包。這種格式如下所列,僅包含兩個8位的數(shù)據(jù)域:SYNC與PRE。
?。?)PING封包
僅存于高速設備所使用的特殊封包是PING封包。主機會送出PING封包來找出是否高速設各端點在以批量或是包含以多個數(shù)據(jù)封包的控制傳輸來送出下一個數(shù)據(jù)封包之前,是否為忙碌的狀態(tài)。這是由于傳統(tǒng)的USB數(shù)據(jù)交易時,若常以NAK來響應批量或控制的OUT傳輸,通常都會導致浪費太多的帶寬。因此,為了減少高速或控制的OUT端點的損失,USB 2.0新增了PING封包。一旦批量或控制傳輸?shù)腛UT數(shù)據(jù)交易被NAK響應后,主機控制器將會使用PING封包來查詢高速非周期性的端點是否有足夠的內存來接收wMaxPacketSize大小容量的數(shù)據(jù)。如果此端點具有足夠的緩沖區(qū)來使用,就以ACK來響應之;反之,繼續(xù)以NAK響應為止。
此外,高速非周期性的OUT端點也可以使用NYET來加以響應,以通知主機所要加載的數(shù)據(jù)是可以接收的,但是端點沒有足夠的內存。此時,主機會使用PING令牌,直到端點表示了針對下一個OUT數(shù)據(jù)交易,已有足夠的緩沖區(qū)內存。
?。?)SPLIT封包
SPILIT封包定義了令牌封包為分割數(shù)據(jù)交易(split transactION)的一部分。為了最佳地使用總線時間,USB 2.0主機與集線器會以高速來送出低速與全速的通信數(shù)據(jù)。至于為什么需要分割數(shù)據(jù)交易呢?這是由于當主機開始傳輸一個針對低速或是全速的設各所預定的數(shù)據(jù)交易時,那么最接近設備的2.0集線器就有責任去實現(xiàn)與此設各的數(shù)據(jù)交易。此外,也負責存儲任何回傳的數(shù)據(jù)或是狀態(tài)信息,以及以一個或是兩個稍后的數(shù)據(jù)交易來加以回報回去。如此,整個總線就無須去針對實現(xiàn)一個低速的交易來持續(xù)地等待。而這個介于集線器與主機之間的特殊數(shù)據(jù)交易,就稱之為分割數(shù)據(jù)交易。
?。?)ERROR甚寸包
這個封包僅使用在分割數(shù)據(jù)交易時。2.0集線器會使用該封包并以低速或全速的數(shù)據(jù)交易來回報一個錯誤給主機。在此,讀者是否發(fā)現(xiàn)該PID碼值與PRE PID碼值是一樣的。但是其中,最大的差異是前者是應用在設各與集線器上,另一個則是應用在主機上。也即是集線器不會送出PRE封包給主機或是ERR封包給設各。
以下,將這些封包格式與字段等加以匯整,如表所列,并列出各個字段與其目的。
表 封包與字段之間的關系
續(xù)表