2011年9月7日 星期三

USB HID 技術散記(一)

上回有提到那個關於支援同一系列USB產品卻要支援多組 USB 裝置的作法

就是利用USB 宣告中的 iSerial 字串方式。

後來我自己又做了許多實驗,發現:原來現在M$ 作業系統真的很喜歡玩我們這些

搞硬體的工程師們。好像存心就是要展現他們搞軟體就是比我們搞硬體的行。

您看以下一個在 WINDOWS XP SP3 下的一個宣告HID 的USB Enumeration 過程:

您看明明我們在宣告中按照USB 規格書 Chapter 9 所描述的字串宣告方式:

iMakefacture = 0x01 , iProduct = 0x02, iSerial = 0x03 ...當然我們也不會去宣告一個

很奇怪的數字。這也是在USB 韌體C 語言的程式寫法方便:

unsigned char* const STRINGDESCTABLE [] =
{
   String0Desc,
   String1Desc,
   String2Desc,
   String3Desc
};

很明顯的:我們不會亂跳這個順序...您以為每一顆USB MCU 的程式容量很大嗎?!

要把陣列搞很大的必要性嗎?!

好了...我們再來看真正USB Enumeration 的真實過程:

您跟我說:我哪裡有宣告過一個編號  0xEE 的字串描述? 作業系統就是會發這一個

問我編號 0xEE 的字串描述?!....根本擺明就是要玩我的嘛!

我跟您說:圖中那個回Stall 是我改寫原廠韌體程式得到的。原廠的範例程式根本沒有

處理這一個問題,就不知道從哪裡隨隨便便回一個根本不符合UNICODE 的字串。

當然答案是錯的。奇怪的是:作業系統啥事也沒發生。我想這是一般Get String Description

的標準韌體流程...只是走完標準Protocol。所以,一般人也不會留意。

但當然有些USB 單晶片 MCU 並不像這般有C 高階語言的寫法,尤其一些台製 USB MCU

為了省成本,或是有些原廠的系統應用工程師不是很用心的寫標準範例程式,

就有可能會陷入M$ 作業系統的這一種陷阱了。我想這應該就是M$ 想揪出這一種

不用心的系統廠商吧。....唉~原來搞USB 系統韌體程式是這麼累的一件事!

這些是一般市面上USB 書也都不會教您的,才會容易誤導大家以為USB 只要買一本市面上

的USB 參考書,翻一翻...按照書上的標準範例程式跑一遍,好像就很簡單似的。

所以,我要再以下一個範例來說明一般USB 教科書都不會交代的地方。

我們在HID 的描述中,有一個基本的PROTOCOL 要求:就是一定要有支援至少一組

 Interrupt In Token...而在Interrupt In Token 描述中,有一項為:bInterval 。單位為mSec 。

這個東西跟我們搞系統應用有啥關係?!其實這個東西就是宣告後給作業系統用的。

還記得我之前解說有關USB DIY 中那個HID 範例嗎?就是利用SiLabs 的BlinklyExample範例

他的描述是 10 (mSec)...我在軟體的相關解說中有說明:當您USB HID Device 一插入

PC HOST 之後,不管您有沒有叫出相關上層應用程式,基本上,作業系統就會自動來

跟您USB DEVICE 要資料了 ...而要資料的間隔時間就是這一個宣告值。

但很不幸的是:不是很準的 10 mSec...其實我已經算很給面子的計算從第一個SOF 算起

勉強還可以算出 9 mSec...但我們寫C 語言的也知道,在高階語言裡那個所謂以 mSec 為

單位的計算單位,都是參考用的啦!(譬如那個 OnTimer 呼叫副程式)應該沒有人會

相信M$ 會幫我們很精準的把這些 mSec 的值很準確的透過周邊裝置精準的送出吧!

當然啊...USB 的誤差已經算很少或是很『規律的』的精準了...以前用那一種UART 或

並列 port 的程式寫法,應該沒有人會相信吧...這一點還是USB 比這些介面強的地方吧。

但我們也發現:USB 裝置也沒有即時把資料準備好的回給PC HOST...所以就以NAK

完成這一個PROTOCOL...至少這已經不算 M$作業系統的錯,而是您USB DEVICE的問題。

好了,我們再以SiLabs 原廠的那一隻開發工具(Debug 外加燒錄器功能)的 Toolkits 為

範例:他是宣告為 1mSec...而且同時支援Interrupt In Token 與Interrupt Out Token。

這更狠吧...您 M$ 玩我USB Device...我反過來玩您M$ 作業系統,就是操您作業系統。

厲害吧 ...果然就是每隔一個 SOF 作業系統就是來要一次資料,當然我們USB Device

就只是純粹想玩您作業系統,我們資料處理速度也不可能麼快的啦...哈~哈~...所以,

也只好用NAK 讓您空手而回。當然這中間還穿插一個 Interrupt Out Token....

所以,從這一組範例演練中,我們就可以很清楚的瞭解到說:為何HID Class 會硬性規定

一定要有Interrupt In Token 而無法硬性要求要支援 Interrupt Out Token...因為這是由上層

APP 應用程式來發動這一個Interrupt Out Token,不關作業系統的事。所以人家 M$不會

鳥您的。----- 這個就是從實際系統應用演練中所得到的系統規格經驗。這當然一般市面上

不管是寫USB 系統應用或一般MCU 單晶片系統應用的參考書不會教您的地方。

那您怎麼在一般系統應用中去累積您個人的系統應用能力呢?!Follow 規格寫程式,

大家都會,那如果要您真正來規劃一個系統應用規範時?您會嗎?!

這個就是最近很流行的:APPLE 專利戰中的焦點。這個才是真正的系統價值。

-----

好了...您以為搞USB HID 不用搞USB 驅動程式就可以輕鬆上手嗎?!

當然答案就是錯的,在USB DIY 自學計畫(十一)我不是有舉例一個原廠

的範例程式嗎?那大家一定很好奇的是:那明明原廠已經有附上一支標準的範例程式,

而且我們也透過 M$ 的相關MSDN 說明,那大家應該就可以輕鬆上手了啊,

那為何原廠後來還要再發表另一個新範例?而且還用SLABHID.DLL 方式來處理

USB 上層應用程式呢?!那鐵定原來的範例程式還是有問題的...因為很簡單,

M$ 的作業系統沒有這麼容易被搞定的,如果大家這麼容易相信M$ ,這麼接受

M$...那當然就不會有Apple 的 iOS 或是 Goggle 的 Android 了。...

所以,不懂得要改變或害怕改變...是一個產品、人或企業邁向成功的重要關鍵。

至少在我個人的經驗裡,就是如此。這也是我們台灣電子業裡所面臨挑戰的

重要因素。

 

沒有留言:

張貼留言