Tuesday, July 22, 2014

USB 簡介[6]

終於到了最後也是最重要的一章,鼎鼎有名的Chapter 9,USB Device Framework。

為什麼這一章這麼有名?因為前面的鋪陳完全就是在這一章爆發啊。重點是,USB標準測試程式,USBCV(USB Command Verifier),跟微軟的WHCK(Windows Hardware Certification Kit),就是一直在找Chapter 9的碴啊。

第一點,USB裝置可分為好幾種狀態,而每個狀態可以吃的電流是有關連的,基本上只有Configured狀態才可以吃超過100mA的電流。而比較值得注意的是,任何狀態都可以進Suspend狀態,這是因為Suspend狀態是透過Suspend訊號來偵測,很簡單。但是哪個狀態進Suspend,出Suspend之後還得是那個狀態,這個就不簡單了。在Suspend狀態中,裝置最多只能吃500uA的電,要怎麼吃那少的電,還要能夠回到上個狀態,這個就不簡單了。

第二點,當有USB裝置插上去的時候,HOST怎麼知道這個裝置到底是什麼東西?那就是透過USB Device Descriptor啦。HOST只要發個"Get Descriptor"這個標準要求給這個裝置,裝置必須回正確的Device Descriptor,這個Device Descriptor內容很簡單,就是描述這個裝置支援的USB版本、實作的Class、Control Endpoint的最大資料量、Vendor ID跟Product ID等等。

先說明『標準要求』,USB有規範一些『標準要求』(Standard Request),目的是讓每個裝置能夠回覆足夠多的資訊給HOST,這樣HOST才能繼續下個動作。有幾個一定要知道:

  • Set Address:HOST透過它來設定USB裝置的位址。每個裝置插上去之後,預設的位址是0,這樣HOST才能透過位址0來讀取Device Descriptor,然後再把這個裝置的位址設到不同的位址去。
  • Get Descriptor:基本上HOST透過這個要求取得USB裝置的所有資訊。
  • Set Configuration:就是選擇USB裝置提供的設定,完成Set Configuration裝置才算進入Configured狀態。
其實最重要的就是Get Descriptor。提到這個要求得先提USB Descriptor。USB Descriptor有分幾種,下面只列常用的:
  • Device Descriptor
  • Configuration Descriptor 1
    • Interface Descriptor
      • Endpoint Descriptor
  • String Descriptor
請注意,他們有些是有階層概念的,Configuration Descriptor主要是描述這個裝置所提供的組態。大多數的裝置都只會提供一種組態,有的會提供兩個以上,主要是電力需求的不同。Configuration Descriptor最重要的資訊就是這個組態最大吃多少電流,以及這個組態支援幾個Interface。要選擇那個組態是HOST決定的,而對應的就是Set Configuration這個要求。

Interface Descriptor主要描述這個裝置有哪些功能(function),一個Interface代表一個功能,所以當你看到一個Configuration Descriptor裡面有包含兩個Interface時,基本上就是只這個裝置支援多種功能,也就是Composite Device。但是,還是有但是,USB後來又有出一種叫做IAD(Interface Association Descriptor)這種東西,它可以把兩個Interface組成一種功能,所以世事無絕對...。

Interface Descriptor主要描述它所支援的功能,以及它支援的Endpoint數目跟種類。它裡面還有一個叫做Alternate Setting的欄位,這個欄位主要是描述這個Interface支援哪幾種頻寬設定。還記得Interrupt跟Isochronous傳輸是有頻寬保證的嗎?這種保證是需要HOST來提供。那HOST要怎知道它能不能保證Device提出的頻寬需求?就是透過Interface Descriptor啦。Alternate Setting可以讓這個Interface提供多種Interrupt或Isochronous傳輸的組合。舉個例子,Interface Descriptor可以提供三種Alternate Setting:


  • 0:需要每個SOF能夠傳輸64 byte的Interrupt Endpoint
  • 1:需要每個SOF能夠傳輸512 byte的Interrupt Endpoint
  • 2:需要每個SOF能夠傳輸1024 byte的Interrupt Endpoint
然後HOST可以根據目前的剩餘頻寬,選擇適合的Alternate Setting。為什麼要搞這麼複雜?因為其他的裝置可能也需要HOST保證一些頻寬,所以得這樣搞。不過我很少遇到這種狀況就是了,尤其是如果都沒Interrupt或Isochronous Endpoint的話,其實只要提供Alternate Setting 0就好了,因為Bulk傳輸並不需要保證頻寬。

而HOST要怎麼選擇Alternate Setting?當然是透過Set Interface這個需求。如果一個Interface只提供一種Alternate Setting,沒有Set Interface其實也可以。

Endpoint則是說明這個Endpoint的類型以及最大傳輸量。

String Descriptor很煩,它主要是提供一些對於Device、Configuration、Interface的描述,也就是人可以看得懂的字串。它一定得提供Unicode字串,而且還有語系之分,但是因為實在太煩了,所以大家都只用英文語系....也造成Unicode字串根本沒有用...。一般就是提供Manufacturer、Product跟SerialNumber這三個字串而已。WHCK機車的地方就在於,它會要你插上兩個同樣Vendor ID跟Product ID的裝置,然後這兩個裝置所提供的SerialNumber還得不一樣。

總結一下,當USB裝置插上HOST時,HOST會SetAddress、Get Descriptor,抓完所有Descriptor之後,Set Configuration選擇適當的組態,然後再Set Interface選擇適當的頻寬需求,結束。接下來就可以透過支援的Endpoint傳輸資料了。說真的,這些東西都不難,只是規格絕對不會跟你講HOST應該會怎麼做,而這也是最機車的地方:每種HOST的實作方式都不同,所以流程絕對不同,光是插上去的流程,就足夠引起一堆相容性問題了。

解這種相容性問題最最重要的就是一台USB Analyzer....,它可以幫你省掉很多猜測的時間。

最後,你以為這樣就完了嗎?當然沒有,如果Chapter 9有這麼簡單,我也不會到現在還在翻它...。

第一,除了Standard Request之外,它還定義了Class Request跟Vendor Request。Class Request之後會提到,每種USB Class都會規定它專屬的Class Request。Vendor Request則是這個裝置特有的要求,說真的很少裝置會提供...就算提供,HOST也不一定會讓程式發出這類要求。

第二,還記得USB裝置必須支援Test Mode來量測眼圖嗎?要怎麼進Test Mode?當然就是透過Set Feature這個要求啦。








USB 簡介[5]

接下來是protocol layer。

第一,USB是little endian,不管是Byte或是Bit順序。

第二,免不了是一堆封包的格式規範,這個看看就好。比較重要的有:

  • SOF(Start of Frame):SOF很重要,對HOST而言。如果你是作Device端的,看看就好。SOF基本上只有HOST可以發,如果是HS的話,是每125us發一次,每個裝置都要去聽SOF,因為後面就會開始資料傳輸了。FS的話是1ms發一次。
  • HandShake封包:基本上就是收到資料回ACK,沒有資料回NAK(不是資料錯誤喔)。有問題回STALL,下一次的資料來不及準備,回NYET(但是這一次的已經收下)。ERR我沒見過,因為是HUB專用。
  • HOST要讀資料之前,一定會發 In-Token,然後Device吐資料。注意喔,HOST在收到資料後,是不能回NAK的。這是因為HOST沒空間可以存資料幹嘛發In-Token?
  • 同理,HOST要寫資料之前,一定會發Out-Token,然後吐資料給Device。
  • Control Endpoint的資料傳輸比較特別,如果是Control In的話,順序是Setup packet --> Data In --> 0 byte Data Out --> Device Ack。如果是Control Out的話,順序是Setup packet --> Data Out --> In-token --> Device send 0 byte data --> HOST Ack。至於為什麼要定這麼奇怪的協定,我也不清楚...。一般工程師很容易犯的錯誤就是在Control Out的時候,最後沒發0 byte的資料,然後HOST就等在那邊,然後還會怪HOST沒做對...。
  • 其他傳輸類型都是 In/Out Token --> Data --> ACK。Isochronous傳輸沒有ACK。
第三,如果資料有錯誤,HOST會嘗試重傳三次。當然,這個對Isochronous傳輸不適用。基本上錯誤處理大多是硬體方面的處理,軟體能派上用場的機會不高。我遇過最好玩的一個錯誤是,Device沒等HOST的In-Token來就把資料送到BUS上了,結果就是babble錯誤。這個也很容易發現,用USB Analyzer抓log,它就會幫你把錯誤標示出來。千萬不要用什麼軟體USB Analyzer,這些軟體通常只能用來紀錄上層通訊協定的資料,對底層是無能為力的,而且它們還不會幫你檢查錯誤。現在一台USB Analyzer很便宜,網路上看到一台"Mercury T2 Protocol Suite"才特價台幣七八萬塊,這台十年前可是要價台幣一百萬呢。它已經這麼便宜了,沒必要再省了...。

Monday, July 21, 2014

USB 簡介[4]

本章主要介紹USB電器訊號。因為我不是唸硬體的,所以有錯請包涵。

電器訊號好像對軟體工程師不用看喔?這個想法有點天真,因為出問題別人一定要你先釐清問題倒底是硬體還是軟體出錯,所以多看看是沒錯的。

第一點,HOST是怎麼知道一個USB裝置插上來了呢?絕對不是看VBUS訊號。其實它是偵測D+或D-,如果D+有被PULL-UP,就表示有個Full Speed 裝置插入,如果是D-被PULL-UP,那就是Low Speed。

那High Speed呢?High Speed裝置其實也是先進Full Speed,然後HOST會再透過一些協定(chirp)跟這個FS裝置溝通,如果成功,雙方就會進HS模式。如果失敗,那就維持在FS。很詭異是吧?其實這就是為了向下相容的緣故,因為只有兩根線,沒辦法生出第三種辨識方式了。

由上可知,其實HOST是沒辦法直接移除一個USB裝置的,因為PULL-UP是由裝置端控制。所以當HOST根本就沒偵測到硬體時,這一定是USB裝置的問題。另外一點是,如果你的裝置老是進FS,記得換條好一點、短一點的USB線,或是換個USB插槽試試看,有些線或插槽的訊號真的很糟...。

第二點就是eye-pattern,中文叫眼圖,因為他真的長得很像一隻眼睛。作USB裝置一定得通過眼圖測試。這點就不是軟體工程師要量了,但是軟體工程師還是得讓USB裝置進入一個叫測試模式的狀態,不然硬體工程師沒辦法量測。一般的USB裝置一定支援測試模式,如果沒有,那就換一家chip...。

第三點,Reset、Suspend、跟Resume是硬體訊號。基本上如何偵測跟應對,規格書寫的一清二楚。比較值得注意的是Suspend,在Suspend模式下,一般狀況下,裝置是不能吃HOST超過500uA的電。這個規定很嚴格,基本上就是叫你把整個裝置都斷電的意思。如果你的裝置沒辦法整個斷電,就不要從HOST吃電,改吃電池即可。沒有電池?不好意思,那就不要去過認證...。

第四點,0/1的資料還要透過NRZI編碼,然後再透過J/K訊號傳輸。這是因為USB界面並沒有clock線路,所以只能把clock編進資料裡。而如果資料是一堆0或1的話,會讓D+/D-一直維持在同一個狀態,這樣雙方根本無法維持一定的clock,所以NRZI基本上就是讓一堆0或1會有所變化。不過不用擔心,這個都是直接硬體就做掉了,錯了一定不是軟體的錯。

第五點,電源管理。一個USB裝置只能吃HOST最多500mA的電。吃超過,對不起,無法過認證。至於HOST會怎樣,則是看HOST的實作,有的HOST比較好心,還是會讓這個裝置抽電,有的則是直接斷電。我認為最標準的作法是斷電,因為這樣可以保護HOST不會過載。

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,那結果就是效能低落,然後還怪別人或自己的硬體效能差。




USB 簡介[2]

USB就速度來分類的話,目前有四種:
  1. Low speed(LS): 最慢,只有1.5Mbps。
  2. Full speed(FS): 有點慢,12Mbps。
  3. High speed(HS): 快,480Mbps。
  4. Super speed(SS): 超快,5Gbps。這系列文章不會談到Super speed,因為我也沒做過。規格書是有唸過,但是不知道人家實際上是怎麼設計的。
HS必須下相容於FS。所以如果你的裝置是HS,很抱歉,你還得支援FS。一般而言,我們會把HS稱為USB2.0,這個基本上有點問題,因為USB2.0規格書還包含了FS跟LS。

在規格書裡,function這個名詞記一下,它對應到device端的功能部分,因為USB規定,一個裝置可以擁有超過一個的function,所以function有時候不等於device。至於compound device跟composite device的差別:compound device是一個實體裝置,但是它其實是一個hub跟多個function組成的,compound device的一個例子是一個支援hub的鍵盤。而composite device則是一個支援多個function的實體裝置,實際上的例子是現在的Android手機幾乎都同時支援MTP跟MSC功能,這種就是composite device。

compound device現實生活中比較難見,我猜原因是因為價錢因素吧。Hub功能比device難作多了,所以compound device會比一般的裝置貴,但是很難說服消費者用比較貴的價錢去買,因為hub的價錢已經被打爛了...。

接下來就是幾乎每個初學者都很頭痛的pipe。一開始看到規格書上的pipe,第一個想法一定是『它在講什麼』。要知道pipe是什麼,你得先從它整個架構上來看。而這也就是USB2.0規格第五章的核心:架構要先懂。

要了解一個架構,基本上不是bottom-up就是top-down方法。我是比較習慣用bottom-up的方式去了解,USB2.0規格則是用top-down方法。這裡我用bottom-up方法講。

USB2.0最底層的實體傳輸只有兩根線,D+跟D-,其他兩根是傳輸電力的,不用管。D+跟D-事實上是用來構成differential signal(台灣翻成差動訊號,後面都用這個名詞)。

差動訊號基本上就是用兩根訊號的準位差來表示一個準位。為什麼要用差動訊號呢?以前的訊號基本上都是用GND來當基準點,但是這會有缺點:萬一兩邊的GND準位不同,同一個電壓會對兩方有不同的意義。舉個例子,如果兩方一個GND 1.5V,一個0V,那萬一一方傳一個1.7V的訊號,一方會辨識成Low(0.2V),一方可能會變High(1.7V)。 差動訊號沒有這個困擾,而且抗干擾的能力變強,因為D+跟D-同時被干擾,但是相減就把干擾去掉了。另一個差動訊號的好處是,同樣的壓差,準位的差距可以變大,訊號的內容就可以變多,因為差距由(0V~5V)變成(5V ~ -5V)。因為差動訊號有這些優點,所以後來有很多的周邊都改為差動訊號了。

在這裡,你只要知道D+跟D-可以構成0跟1即可。實際上的0跟1準位判斷,USB2.0規格的第七章講得一清二楚。知道0跟1之後,往上層就是用這些0/1去構成一個個USB封包。這些封包的內容基本上就是說明這個封包要傳給哪個裝置,或者是由哪個裝置傳出來的。為什麼要這樣?這是因為USB是BUS架構,而實體傳輸又是只靠兩根線在傳輸,如果沒有封包的定址能力,雙方根本無法知道實體傳輸上的資料是要給誰啊。而USB並不滿足於裝置定址能力,它還規定每個裝置可以擁有特定的傳輸通道,也就是Endpoint,或者稱為Pipe(以下都用Endpoint稱呼)。Endpoint基本上是個虛擬的資料傳輸通道,它在USB Bus上其實也就是一個個封包,或者是一堆0/1的組合,但是人總是無法直接解譯0/1,所以越往上層越是抽象。所以下次人家跟你講Endpoint或者是Pipe時,不要再一臉狐疑了,這只會讓人家知道你不懂USB。

USB2.0規格對Endpoint型別有四種規範:

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

這四種基本上比較會用到的就是Control跟Bulk。Control Endpoint是雙向傳輸,其他三種都是單向傳輸,也就是說,如果你要雙向傳輸Bulk資料,你的裝置得支援兩個Bulk Endpoint才行。

在這邊又得提一個觀念,USB的資料傳輸方向一律是以HOST為視角,所以IN就是表示HOST要收資料、Device要寫資料。而OUT則是相反,HOST要寫資料、Device要收資料。

所以你會常常看到 Bulk-In、Bulk-Out、Interrupt-In、Interrupt-Out、Isochronous-In、Isochronous-Out這類的名詞。請搞清楚他們的方向性。要支援那些Endpoint是裝置端的責任跟權力。

一旦知道Endpoint,最上層的應用程式只要對這些Endpoint做讀寫就好,事情就變得比較簡單一點。而這也就是USB2.0的圖5-9所要表達的意思:每一層都把它自己的工作做好,事情會變得比較簡單。



Sunday, July 13, 2014

USB 簡介[1]

USB,全名是Universal Serial Bus。顧名思義,它是Serial介面,而且是BUS架構。Universal當初應該是希望能夠通吃所有裝置吧,就結果來看它也達成這個目標。

先來研究為什麼會設計成這樣(我的理解):

  1. Serial介面:這個應該是硬體設計思維。Parallel介面在高速的clock之下很難維持資料的同步,所以用serial傳輸會省掉一些麻煩。
  2. BUS架構:因為USB支援Plug and Play,所以設計成BUS架構很合理,擴充容易。


看起來沒有很厲害啊?是的,但是它堪用。一個東西能不能成功,往往不是一個因素或是技術很厲害造成的。USB過去跟現在之所以流行,我認為其實是很多因素造成的:

  1. 它不需要授權金
  2. 規格公開
  3. Windows支援
  4. balabala

這幾個理由就夠人家試試看了。至於價格便宜,那是後話了(台灣IC設計所賜)。

USB架構

USB是Master-Slave架構。USB Host一定是Master。通常USB Host就是指PC,但是現在行動裝置流行,也有可能是ㄧ些支援USB Host的行動裝置。而Slave就是指USB裝置,最有名的代表就是隨身碟(我討厭大陸用語[大拇哥],Mass Storage還比較有科技感)。

這邊先講一些基本知識,免得雞同鴨講。其實這些知識都是[計算機概論]或[計算機結構]課程的一部分,沒讀過或是懶得讀的也可以用google查到。

Master-Slave架構的特點如下:

  1. Master才能發起一個Request。
  2. Slave只能回應Master發出的Request。

至於BUS的特點:

  1. 大家共用線路。最大的優點是省線路,在很早以前能省線路就是省錢的年代,這個很重要。
  2. 沒了。

BUS架構很簡單對不對,但是衍生的問題很多。

第一,共用線路代表同一時間只能有一個裝置可以用到線路。所以如何讓BUS的使用率到達最高,是個很難的問題。你可以想像如果有個慢速裝置在BUS上傳一筆很大的資料,這樣的BUS使用率會有多糟。

第二,如果有裝置不遵守規矩怎麼辦?所以BUS會制訂它專屬的通訊協定,讓這件事情比較容易偵測。但是如果一個裝置真得要亂搞,也真的沒辦法。如果你知道Ethernet的CSMA/CD(Carrier Sense Multiple Access/Collision Detection)的話,你大概會知道可以在偵測到網路碰撞時,讓等待時間最小化,如此你的網路卡表現就可以比別人好。這樣是不合規範的,可是還真的沒辦法防止。

USB針對BUS架構的缺點,提出了它的解決方式,這也是大多是BUS架構的解決方式,就是Master-Slave架構。因為Master-Slave架構可以有效解決BUS使用率的問題,並且有限度的防止惡意裝置亂搞。用一句話就可以說明:你們這些USB裝置通通聽USB HOST命令,一個口令一個動作。

這邊不談OTG(USB On-The-Go),它是個變種。

USB 簡介 - 前言

其實USB簡介很早就應該寫了,因為光是這幾年就不知道為其他人上過幾次相關課程了。只不過那時都是用投影片,所以也沒辦法很深入。

算一算USB都已經快要問世20年了(今年剛好20,1994年開始設計),可是就我的觀察,還是很多做USB相關的工程師不是很懂。沒辦法,USB實在太複雜了,我自己也不是全懂。

台灣我看就ChamberPlus有在分享他的經驗,不過他的經驗主要是在實作跟USB1.1方面,而且透過8051基本上有一些SOC控制部分會有差異。我這邊大概只能分享一些SOC如何控制USB controller的部分,以及USB2.0。

為什麼USB會這麼難呢?我的感覺是因為有些事情是硬體做掉,有些是軟體做掉,而工程師大部分都不是軟硬通吃的,再加上有一些東西真的是要做了,或是有人教,才會知道。這造成很多軟體工程師都是一知半解在做USB產品,想當然爾問題就很多了。

Saturday, July 12, 2014

SPI 簡介

SPI,全名是Serial Peripheral Interface。他是master-slave架構。顧名思義,他也是用來跟各種裝置溝通。

標準的SPI需要四根線,分別是SCLKMOSIMISO,以及CS
SCLKclock,一定是由master拉。
MOSImaster-output-slave-inputMaster寫資料到Slave
MISOmaster-input-slave-outputSlave寫資料到Master
CS則是chip-select。當有兩個以上的SPI裝置的時候,CS有拉的SPI裝置才可以回應。

I2C很類似,不過還是有點不同:
1.      SPI沒有定義protocol,請參考每個SPI裝置的datasheet
2.      SPI多了兩根線。不過如果可以的話,MOSIMISO擇一就可。因為通常SPI裝置只會支援獨或寫。而這種三根線的SPI,有人叫3-wire。不過還是要跟對方確認清楚,因為3-wire泛指[只用三根線來通訊]的東西。萬一對方講的不是SPI,那就糗了。
3.      SPI可以跑比較快。為什麼可以跑比較快,我不是很清楚
4.      SPI基本上不算BUS架構(雖然同一個master可以接多個裝置),所以不會有裝置衝突的問題,但是缺點就是,如果要支援多個SPI裝置同時跑,就需要多個SPI master

在跟SPI裝置溝通時,要注意的事項基本上跟I2C差不多:
1.      Polarity:到底是clockrising edge還是falling edge要抓取或寫出資料。
2.      Clock skew:波型不要跟datasheet差太多即可。有些客戶很龜毛,一定要符合datasheet上的要求,如果你是用8051SPI的話,請自求多福吧。如果是硬體做掉,那就直接看硬體的支援程度了,一翻兩瞪眼。
3.      Debug也是用示波器就可以了。幾MHZ的波型基本的示波器都可以抓到。

在這邊順便提一下,台灣軟體工程師分兩種:一種是完全不碰硬體的,一種則是會碰(廢話)。如果你是前者,建議你不要碰I2CSPI。因為這兩種基本上一定要看波型,而這一定需要硬體工程師的幫忙(不然示波器要從哪裡來)。硬體工程師至少要幫你設定好環境(或是教你怎麼操作示波器),至於看波型,就看你跟硬體工程師交情了。


我基本上不太喜歡求人,所以最多就是去跟硬體工程師借示波器,了不起就是問一下怎麼操作。波型還是得自己看。我曾經看過有些軟體工程師一直凹硬體工程師幫他把波型存起來給他看,或是直接說是硬體的問題,叫硬體工程師debug的。我知道這是公司文化使然,但是這個真的很不好。如果你想請人幫忙,至少先做個功課吧。

Tuesday, July 08, 2014

I2C 簡介

I2C,念法應該是[ I-squared-C],不過不必糾結於念法,老美也有亂念的,像是[I-Two-C],聽得懂就好。

I2C只需要兩根線就可以。一根是SCLSerial Clock?),另外一根是SDASerial Data?)。SCL顧名思義,就是提供clock的線,SDA則是要跟clock對齊的資料。

I2Cmaster-slaveBUS架構,master是大多數只有一個,slave則是可以有很多個。而只有master可以拉SCL

因為只有一根線可以傳資料,所以必須定義SDA訊號的內容。I2C超簡單,只有幾種:
1.      Start condition:傳輸開始
2.      End condition:傳輸結束
3.      8-bit address:因為是BUS架構,必須指定這次傳輸要傳給哪個裝置。很好玩的是,I2C並沒有動態指定address的協定,所以每個裝置的address都是先講好的。所以記得檢查你的I2C bus上有沒有address衝除的裝置。每個裝置的datasheet都會說明它自己的address。有一個bit是拿來表示這次的傳輸是讀還是寫,所以其實只有7-bit可以用,所以address最大是127
4.      8-bit or 16bit data
5.      ACK:表示資料收到了

在這邊又衍生出另外一個問題:SDA到底要先傳most significant bit還是最後傳?google了一下發現是先傳。

I2C協定有許多變種,所以就不列波形圖(其實是懶),每個裝置的datasheet都會列出它需要的波形圖,唯一可以相信的就是這個。其實I2C對於波形的準確性不是很在意,意思到了就會動,而這也代表著它的傳輸速度不會太快,了不起100Kbps吧。請注意,100Kbps是指clock rate,也就是100Khz,實際上有效資料有到50Kbps就可以偷笑了。

我以前沒想過的是,用8051就可以拉出I2C需要的波型。後來想想也對,反正先拉SCL再拉SDA即可,反正容許誤差很大,這樣也會動。但是速度一定是慢,而且用8051寫這個可是一件苦差事。

還有一種是直接透過硬體控制I2C,只要填填register就好。這種比較簡單,而且速度比較快。

I2C debug很簡單,直接用示波器量訊號,一翻兩瞪眼,是誰的問題一目了然。

debug時,另外一個問題是(怎麼這麼多問題),到底誰會在哪個時候拉SDA?這個就是大哉問了。大部分都是master,裝置應該是只會在回資料跟ACK才會需要拉吧。這點一定要注意,不然到時候就會錯怪忠良了。


Monday, July 07, 2014

ARM-based SOC vs 8051-base USB device solution

目前我遇到的USB device控制方案有兩種:一種是8051-based,另外一種是ARM-based。這兩種控制方案基本上是兩種不同的硬體思維所產生的。

8051-based USB devices

會採用這種方式的公司通常是要生產[固定功能]的USB裝置,也就是這家公司出的USB裝置幾乎只有一種功能(了不起再多一種)。要改成其他的,不好意思,等下一版IC吧。

因為USB功能大多固定,所以許多功能直接用硬體做掉會比較有效率。相較之下,CPU只是拿來做一些客製化或流程控制用,因此用8051綽綽有餘了。當然,重點是[授權金很便宜,甚至不用錢],這永遠是台灣IC設計的最愛

我之前的公司就是做這一類的,8051負擔的工作很簡單:

1.          初始化USB controller
2.          提供 USB descriptors USB Host
3.          處理一些 standard/class/vendor requests

有沒有發現,USB資料傳輸根本不需要8051介入,狠一點的公司可能可以連8051都不要了。

優點

1.          便宜(功能固定)
2.          效能好(還是因為功能固定)

缺點

1.          支援的記憶體大小有限。雖然大多數的8051開發環境宣稱支援C,但是為記憶體大小的關係,大多數還是得用組合語言寫程式。更慘的是,用C編出來的組合語言有時還會有問題。而且幾乎不可能在8051上執行OS,這代表所以事情都得自己來。
2.          支援的周邊有限,擴充能力有限。

ARM-based USB devices

會採用這種方式通常是希望同一顆IC可以支援的USB功能越多越好。這種想法所導致的結果就是USB device controller的功能會非常有彈性,而CPU控制所有事情。8051當然沒辦法負擔這種差事-它跑太慢了,而且支援的周邊有限。

ARM架構就不用多說,用google可以查出一狗票資料。

優點

1.          有彈性,不論是硬體或軟體
2.          支援很多周邊

缺點

1.          比較貴,不過現在ARM已經有便宜版
2.          效能一般會比純硬體的裝置差

結論

就軟體工程師的角度來看,當然是後者比較好玩,因為軟體複雜度比較高,可以調整的東西比較多。

今年寫作計畫

實在是太久沒寫技術性文章了,擬訂計劃來強迫自己複習一些東西。

1.      ARM-based SOC vs 8051
2.      I2C
3.      SPI
4.      USB
A.          Protocol
B.          MSC
C.          MTP
D.         UART
E.          Implementation

                            i.                Libusb

就這樣,今年應該夠吧。

Sunday, July 06, 2014

雜感 - 2014 年中

今年上半年就是在做 damage control 的準備啊,果不其然,一進到六月就一堆[原本不屬於我的]事情掉到頭上來。

故事情節很老套,公司老闆請了一位據說很厲害的人來搞了一個新的系統,他很神,說要把原本我們部門的工作(USB)接去做。

我不是老美,也不是老中,我只是想好好領錢過爽日子,聽到有人說要把那個[屎缺]拿去,當然直接說好。

就這樣相安無事過了一年。當然,期間還是會有交接的問題,這個我們能回答的就回答了。不過,漸漸地就感覺到不對勁了:

  1. 他的 team 完全沒有人對 USB 熟。
  2. 他覺得 USB 很簡單。
用膝蓋想就知道結果會是甚麼了....現在只要是有 USB 三個字的問題,直接找我。我勒,幸好上半年有去看他的新系統,不然就真的是加班加到死了。

至於那位很厲害的人?我一點都不覺得他厲害:
  1. 說話不算話。到現在為止我還沒看到他為他的錯誤道歉。所以到最後如果案子結束,他還是會說都是他做的。他甚至連 "Thank You" 都沒說過喔。
  2. 連 Version Control System 是拿來幹甚麼用都不知道的人...無言。

Windows Driver Programming PDF 版本

感謝 Google Drive,有興趣的人可以直接去抓 PDF 版本

這個版本是用 MicroSoft Word 2013 製作的 (不要還懷疑,我有買),因為真的受夠了 HTML跟 OpenOffice了,樣式老是無法如意。

codeblock