2011年5月29日 星期日

USB DIY-- 自學計畫(九)

想瞭解之前的...可以點選以下連結:
----------
上回有提到說:我們在一般USB 的Homekeeping 韌體管理程式一定要搞清楚,
所有USB SIE 發給我們MCU 的中斷點,因為我們有提過說:如果您沒有留意
這一點的話,您根本很難塞進相關的USB 應用程式,我們拿著人家USB MCU IC
又不是只是拿來學學好玩而已,也不是像老師上課,教完了就沒事,怎麼用?
所有市面上相關的書籍都不會教您這個問題,您碰到問題想問也問不到,
甚至怎麼問?要問誰都不知道?往代理商丟?人家工程師搞不好也是菜鳥,
搞不好還要您教他呢!....
為什麼這個問題很重要?因為:我之前在USB DIY 系列文章中有提到說:
USB MCU IC 一定要優先處理完USB Protocol 的程式,再來處理PC HOST 交辦的
事宜。否則,當您收到一個USB Token Interrupt 就匆匆忙忙的急著執行相關
應用程式的話,結果,哪知道USB Protocol 上,USB SIE 還發給您MCU 一大堆
中斷,我們都知道:中斷程式都會影響我們韌體程式的Stack 及變數(以8051 來說:
就是那個RAM  Bank的切換),而這一種程式的Bug 卻又是最難追的(問題發生點
每一次不一定一樣,很難複製!)。
在我們一般觀念裡,不管哪一家USB  MCU IC ,大致上這一部份的架構都是差不多的。
至少我還沒有看過不一樣的,所以,我一開始接觸到這一棵新的USB MCU IC 時,
我就有想到這一個問題,但是他原廠資料,也只有交代說:USB 上許多Setup/In/Out ,
甚至Stall 或Reset 等都會發中斷...而原廠給的範例程式也沒有交代,甚至程式裡
根本都沒有處理這一部份的程式。
而您在使用上又沒留意到時,結果批哩啪啦寫了一大堆應用程式,整個韌體程式已經
寫得像狗皮膏藥,或是說:已經一大堆應用工程師們都塞了他們自己程式之後,
在產品實際驗證測試時,才發現好像都一些不尋常的靈異現象,又不容易抓,
最後大家只好全推給原廠,就開始怪人家的IC 不好,不穩...甚至都可以把所謂EMI/EMC ,
全抬出來...一股腦往人家身上推,結果呢?那您還要不要再換另一個MCU 啊?
大家就重新再搞一次?作事情的永遠是最可憐的工程師,如果您自己還不長進的話,
這種事情讓您多作個N 遍,再讓您多換幾家公司也是一樣的啦。
-----------------
好吧,我就從最簡單:在USB插拔時,Enumeration 第一個Get Device Descriptor 來看:

因為他是SETUP-In-外加一個Null-Out ...就是教科書說的:SETUP-Data-Status 啦。
(但是另一種為SETUP-Out- Null-in 也是SETUP-Data-Status...有不一樣嗎?
當然不一樣的啦。所以,看中文書或教科書還是要認真一點。也不要光看書啦!)
這一種Get Device Descriptor 就是先Setup 出USB 標準Command (8 Bytes) ,
然後就要跟您USB DEVICE 要資料了。然後PC Host 收到資料後,會回您一個
Null- out 跟您說他收到了。
從上圖中與我的解析說明:您可以看到說:PC Host 是很厲害的啦,他一下完 Setup 之後,
就開始一直跟您要資料:您有看到 143~157 那一大堆回NAK 的IN...代表您韌體都還沒
處理完呢。然後當您好不容易回完資料後,他又一下子就回您Null-out (ZeroSize Packet)。
所以,我們就可以看到實際上我們有收到三個 SIE發給我們MCU 的的三個中斷,
如圖中藍色箭頭所示。注意一點依原廠所附的範例程式來看,其中:從收到SETUP 中斷
之後,一直到MCU 回資料時,其實,我們的韌體程式是一直停留在SETUP 那一個
ISR (中斷服務程式)裡的。所以就說:他一回完資料之後,就又馬上被中斷叫回!
然後又被另一個Null_OUT 中斷叫回。.....
好了,以上是基本的 Setup _In_NullOut 的動作。
那另一種Setup- Out-Null_IN呢?!...他代表的是說:PC HOST會把一些數據資料
輸出給您MCU...這一種在一般標準 USB Enumeration中是沒有的,他需要跑一些
應用程式才有。....他跟Setup -In-Null_Out 不一樣的地方是:
他是Output(Setup)-Output(out)-Input(Null_IN) ,而 Setup -In-Null_Out是Output-Input-Output。

上圖就是一個利用原廠所附的上層應用程式所完成的一組Endpoint 0 的Setup Command。
這是一個HID Class 的Command ,就是 Set Feature 的一個動作。
同樣的,當PC Host 下完Setup Token 之後,我們的USB MCU 也沒辦法馬上可以接收
PC Host 下過來的資料,我們USB MCU 中的SIE 就會幫我們擋著。
直到我們把USB FIFO 清楚整理完畢才可以。...結果,PC Host 一送完資料就又馬上跟
我們要另一個Null-IN 的Status 的回覆,相對於之前提到那個Set Device Descriptor 來看。
連我們回給PC Host這麼一個簡單的Zero Size Packet 的NULL-In  都還會產生NAK。
之後,PC會緊接著下另一組Get Feature 命令,他也是屬於一般Endpoint 0 的Setup Token 。
您可以自行比對一下他跟Get Device Descriptor 是一樣的動作的。就不再解說了。
但是,並不是所有的Endpoint 0 的命令與動作都是如此的,有些命令是沒有帶任何
資料傳輸的...他可能只是一個簡單的USB 的Protocol 動作。
像我們在USB 的Enumeration 中,最後一個Endpoint 0 命令Set configuration就是:

這些命令您就自行參考原廠標準範例就可以了。這一種東西都已經是標準了。
也沒什麼好解說的。所以,我才一直強調說:USB 其實不難,他比UART(RS232)
還簡單,因為您根本無法在這些標準動作外,加入屬於自己的東西。
-------------------
除了這些東西以外還有沒有其他的?當然有啊。萬一傳輸的內容大小超過一個
In Token 或Out Token 的最大Packet Size時,他又是如何?在一般來說:
在Endpoint 0 中的  In Token 或Out Token 的最大Packet Size是 64 Bytes的。

上圖就是傳輸資料超過 64 Bytes 時的傳輸結果,我們就可以發現他每一個
In Token 都會產生Interrupt Event 的,這代表著我們的USB MCU IC 對於每一筆我們要
傳輸的資料內容都是要我們自己一筆一筆慢慢整理的..所以您就看到一大堆IN - NAK 。
所以我上回說:那個暫存器的那個幫我計數的Packet Counter 是一點鳥用都沒有。
除非他是反過來定義說:我可以把一大筆傳輸資料先塞進FIFO 中,然後SIE 他自己
可以一口氣傳完再發中斷給我們MCU。..這樣子鐵定效能是比較好的!
但是這一種有點類似DMA 的作法,不是每一個使用者容易搞得清楚的。
我之前也一直強調:傳得快,不如傳得穩。所以,人家這一種USB MCU 的設計方式
我們一點也不覺得奇怪。所以啦。下回如果您要做什麼高效能的USB傳輸介面時,
當您要選擇這一種通用型USB MCU時,就不要太在乎他的傳輸效能了,
您也不要老是把那個 USB 1.1/ 2.0 甚至USB 3.0 老是掛在嘴上。沒有人會理您的啦。
-----------------------
我相信我這樣子精闢的解說,外面應該沒有任何USB 教科書或參考書會教您的啦。
因為人家都不會理您這些最基本問題,人家只要把規格拿出來講一講,然後把人家
USB MCU 用力的 Promotion一下,剩下的就是您自己的事了...啊,您自己還要花
多少時間摸?搞不好,買一本看不懂,講不清楚,然後又得再找另一本,
買了一大堆,看來看去總覺得每一本講的內容還是都差不多,甚至還辛辛苦苦的買
了人家的開發版,結果,搞了老半天還是搞不懂。我相信有許多讀者,從我發表
第一篇USB DIY 文章之後,也就想好好學學USB...但是您真的有抓到學習重點嗎?
等我把這一系列的USB  HID 做完、講完之後,應該就沒有什麼好講的了,
那您學起來沒有呢?!...您要好好加油了囉。
(待續)





USB DIY-- 自學計畫(五)

沒有留言:

張貼留言