Saturday, July 19, 2014

USB 簡介[3]

前面提到USB支援四種Endpoint傳輸:

  1. Control
  2. Bulk
  3. Interrupt
  4. Isochronous

這邊簡單說明,太詳細實在沒意思。

Control傳輸:一定是透過Endpoint 0,而且一個裝置只能有一個,而且一定要支援。它一次最大能傳的資料大小為64 bytes,並且是雙向傳輸。基本上一個USB裝置一插上電腦,電腦就會透過Endpoint 0來問一些資料。根據USB2.0規格,Host必須保留10%的頻寬給Control傳輸。

Bulk傳輸:它一次最大能傳的資料大小為512 bytes(HS)。它並沒有保證頻寬這件事情,通常都是HOST覺得BUS有頻寬了才會選擇傳輸Bulk資料。相對的,如果頻寬很空閒,每秒可傳輸的資料量就很大。

Interrupt傳輸:它一次最大能傳的資料大小為1024 bytes(HS),而且是定期傳輸,裝置端需要聲明這個期間是多久,以HS而言,是以micro-second為單位。它需要HOST保證頻寬,如果HOST無法滿足這個裝置的頻寬需求,HOST可以拒絕啟動這個裝置。

Isochronous傳輸:跟Interrupt傳輸非常類似,但是它沒有錯誤重傳的機制。以上三種都有錯誤重傳的機制,而這個機制建立在每次傳輸都會有ACK封包的前提下。Isochronous傳輸並不需要ACK封包,所以自然無法偵測錯誤。

Interrupt跟Isochronous傳輸還支援一種叫做"High Bandwidth"的傳輸,也就是在HS模式下,資料量最大可以三倍。作法很簡單,HOST每次要開始Interrupt或Isochronous傳輸時,直接發三次傳輸要求即可。不過我很少會看到有這樣子做的裝置,也有可能是我孤陋寡聞。

Isochronous傳輸可以用在即時的影音資料傳輸,因為這些影音資料錯了就錯了,沒關係。但是,凡是都有個但是,如果你的影音資料是一些有編碼過的,這個前提就有問題了。據我實驗的結果,如果你拿Isochronous傳輸MJPEG資料,並透過Windows內建的MJPEG decoder來解MJPEG,如果很不幸的資料掉了,那微軟的MJPEG decoder就有可能直接當掉,不解了。如果使用FFDSHOW反而沒這個問題。如果你今天是作產品的,敢賭這個嗎?

從上面的四種傳輸特性,你會發現沒有一種可以用來傳輸非常即時的大量重要資料?Interrupt傳輸可以保證頻寬,但是很抱歉,頻寬已經固定了,這次傳不完,等下次吧。Bulk傳輸沒有頻寬保證,所以根本不知道什麼時候可以傳完。Control傳輸資料量太小,而且也無法保證傳輸時間。Isochronous傳輸看似可以,但是資料不保證完整。

為什麼會有這種限制?主要是因為USB所有的傳輸都必須由HOST發起,而USB也沒有類似Interrupt這個腳位來讓HOST知道Device有急事要處理,所以一切都得等HOST的反應,而HOST也只能按照規範來作,所以結果就是這樣了。

在USB2.0規格裡,第五章裡面有計算每種傳輸的最大實際頻寬,有興趣可以自己算一下,其實USB的overhead還算蠻大的,尤其是每次的傳輸資料量小的時候,主要是檔頭跟CRC佔了一部分。這個沒辦法,每種傳輸介面一定都會有overhead,所以USB2.0號稱480Mbps,可是實際上可以達到240Mbps實際資料傳輸就很了不起了。這是因為不會每次都是大量的資料傳輸,一定會穿插一些小資料的傳輸。

這邊又有另外一個觀念,前面所提的USB傳輸是指Transaction,也就是不能傳超過該傳輸種類的資料大小。如果要傳超過最大資料量呢?那就是叫做Transfer。其實說穿了transfer就是數個transaction集合起來的。舉個例子,如果一個裝置支援一個最大資料量512 bytes的bulk-in endpoint,那的確在BUS上,你只能每次傳512 bytes。如果你要傳2048 bytes,你得分4次512 bytes,而這整個2048 bytes傳輸,就叫做transfer。這個觀念很重要,因為這牽涉到你的傳輸速度。如果你的裝置支援USB transfer的API呼叫,那就表示它可以用硬體幫你切成transaction傳輸,這樣會快很多。如果你用軟體做的話,速度會差很多。

有一些工程師不知道Transaction跟Transfer的差別,明明可以用transfer方式傳,結果還傻傻的用transaction,那結果就是效能低落,然後還怪別人或自己的硬體效能差。




3 comments:

大頭鰱 said...

你好
請問你有寫過linux usb gadget 嗎?
可以跟你討教嗎?

OD said...

你好,我沒寫過...你要寫自己定義的protocol嗎?還是只是要用?

Unknown said...

有一些工程師不知道Transaction跟Transaction的差別
應該是Transfer
受益良多 謝謝文章!!!!!

codeblock