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-- 自學計畫(五)

沒有留言:

張貼留言