2011年5月23日 星期一

USB DIY-- 自學計畫(八)

想瞭解之前的...可以點選以下連結:
USB DIY-- 自學計畫(六)


USB DIY-- 自學計畫(五) -----
關於F3xx 系列有關於USB 應用參考韌體程式有兩支:
1 : USB_Bulk : 就是我在(一)~(五)中所用的。 這一隻範例您是需要外掛屬於自己的
PC 端的驅動程式的。我想這一種USB應用大家可能都比較害怕吧。
2 : USB_HID : 這一隻範例程式用的是標準Microsoft 的驅動程式,但我想您也不會只拿來寫
滑鼠或鍵盤吧,自從iPhone/iPad 創造流行之後,作滑鼠、鍵盤的廠商應該都在那剉著等吧。
鍵盤的就不用說了。至於滑鼠功能,我想多點觸控屏的特性應該跟傳統滑鼠的定義不同吧。
當初USB 在HID 中定義滑鼠時,應該也沒想到多點觸控吧。---詳細的規格我就不知道了。
-----
我們也發現這兩支範例程式的程式風格,應該是不同人員撰寫的,所以,如果您要同時參考
這兩支範例程式時,最好有心理準備。以我自己本身經驗稍微看了一下他們的程式的架構,
不要說其他USB 特殊應用功能,光是處理USB Chapter 9 標準命令來說:我都覺得
這兩支原廠的範例程式都寫得不好。尤其對於USB新手要學習 USB都有不容易的盲點。
更何況當您是沒有寫過多少 8051 單晶片C 語言的新手來說:可能更難了。
我們就以USB_HID 這一支程式來簡單說明一下,我之前在USB DIY 一系列的基礎USB
系統說明中有說過,所有USB MCU IC 幾乎全都採用所謂的Interrupt Event 來處理
所有USB 匯流排上的所有USB Token (包括RESET、SUSPEND、STALL 、SETUP、
IN 及OUT 等,尤其是後面那三個SETUP 、IN及OUT 幾乎就是佔去絕大多數的USB
 匯流排 Event 。)
所以,如果您真的沒有好好的掌握這些USB 匯流排上的Interrupt Event 的話,
您要好好的維護您的USB 韌體程式是很辛苦的,您以別以為只要套用原廠的範例程式,
稍微改寫一下就好像很好用了,其實不然,如果您的USB 系統應用稍微偏離一下原廠
的範例功能外,您可能就完全掌握不到人家原廠USB MCU IC 的精髓了...
---
(其實,我也沒說人家原廠USB MCU IC 就一定很好用,或是說您就非用不可,
我說過了,現在賣MCU IC 就像士林夜市賣蚵仔煎一樣,大家賣的都是差不多的東西,
就看您自己喜好程度,不喜歡的您就再換一家嘛!像這系列的USB MCU IC 也沒有
想像中那麼容易掌握,您別看他一些 Registers 好像不多,更何況還有一些像廢物一般的
無用的Registers ...連原廠的範例程式都沒用,譬如:FRAMEL/FRAMEH、INMAX、
OUTMAX等等這些暫存器,以我們用過USB 經驗來說:反正都還要定義自己的傳輸參數,
給這些也沒用,就算我們拿來檢查一些USB 狀況來說:如果這些東西都已經出錯了,
那大概這一棵USB MCU IC 也不能用了,也會被應用市場給唾棄了吧!
所以有些搞IC 設計的老是會偏離系統應用角度,搞一些有的沒有的暫存器給我們用,
也都不一定對於我們系統應用有所正面幫助的...這一點您自己本身要有一定的判斷能力。)
----
我們就作一些簡單的示範來說明一下:
(注意:我們講的還是很基礎的USB Chapter 9 標準命令的韌體程式的掌握程度,
這一部份套用在另一支USB_BULK 範例程式也是一樣的!)

首先我們先把一個簡單的 I/O Toggle 擺在 USB_ISR 中,來觀察所有的USB interrupt Event,
只要有任何USB Interrupt Event 發生就可以觀察得到,然後我們就可以利用USB 分析儀
來觀察每一個USB Interrupt Event 的發生點(程式進入點)。

結果,這是一個最簡單最基礎的USB Enumeration 第一組命令:Get Device Descriptor 。
我們就可以發現每一個 SETUP/IN/OUT Token ,,,我們的USB MCU IC 都會收到Interrupt
Event。但是原廠的範例程式並沒有把每一個Interrupt Event 作適當的判斷與處理。
當然啊,如果您真的覺得您USB 系統功力真的很好,您都可以把這些Interrupt Event
 視而不見,我也沒意見,但我說過了,等下回您突然要又不同的USB 系統應用時,
您最好可以自行處理與應付。但我個人覺得:
如果新手在學USB 韌體時,沒有留意到這個東西與流程時,可能是很難掌握USB 韌體的。
對於這部分的韌體,我是覺得原廠這顆USB MCU 還有一個很搞笑的地方,
他裡面有定義一段韌體:

如果照原廠的說法:您發現這一個中斷旗標(SUEND)發生時,您就可以作如此處置。
但我是覺得如果在USB 匯流排上發生這個問題時,大概您的USB MCU 也掛了吧。
因為USB 匯流排上也不太可能只掛您一家的USB MCU 啊...而且現在USB MCU 的相容性都
很高了,我想會發生說:當您明明已經完成OUT Token 然後在等 In Token時,您的USB SIE
還可以解到一個屬於您的OUT Token...您該不會怪人家USB HOST IC(主機板南橋晶片)
有嚴重疏失吧?!這可能在早期還有可能,現在應該沒有了吧。至少我都沒碰過啊。
----
我們再回到之前那個USB Interrupt Event...我們可以看到明明有這些USB 中斷,那您知道
這些USB 中斷對應到您韌體程式的哪一段嗎?!...答案是:都沒有。原廠的範例程式沒寫。
所以,我們就稍微改寫一下原廠的範例程式:

加入這兩段程式,然後也Toggle 一些I/O 再來觀察實驗結果:

果然我們就完全掌握住每一個USB Interrupt Event 的程式進入點,至於您要不要做一些對應的
系統應用,就看您的本身在系統應用上的需求了啦。
---
當然啊,我們在真正的系統應用上,也不能只有加這兩行而已,否則,這種程式的寫法就是
貼狗皮膏藥的作法...真的不值得鼓勵去做。
最基本的問題是:原廠所附的這個程式在USB 控制流程上的韌體程式的寫法不夠
明確(這是我個人的看法。),其實,如果您也像我一樣看著USB 分析儀的答案也未必能夠
很快的去解讀程式的含意...但是難道沒有人跟原廠反映過嗎?!
-----
對於這一個這麼簡單的原廠韌體程式的修改實驗觀察,我們不是要說原廠的程式不能用,
我說過了,我也相信可能也有很多人都沒有留意到這一點,就劈里啪啦開始作系統應用
發展,對於一般基本的USB 應用應該還好,但如果您是要做類似USB_BULK 那一種有
自己驅動程式,有自己的Vendor Command 的...您還是最好熟悉下這一個問題吧,
但對於我來說:能改寫或作這個實驗,對於我們可以很快的熟悉及瞭解這一棵
USB MCU IC 的每一個USB 控制Registers 來說:是更容易明白與清楚其用法的。
或許您也可以參考這一個作法試看看。
----
PS : 其實,原廠這樣子寫USB 標準流程韌體(我們俗稱的USB HomeKeeping 程式),
不是很好的寫法,對於一些想學這一棵USB MCU IC 的工程師來說:真的沒那麼容易上手,
但我也說過了:對於許多USB新手工程師來說,大部分都不會太質疑或甚至改勇敢的去改寫
一個似乎可以用的程式...這個就是我們台灣科技教育制度的習慣,也造就了我們在工程技術
與產品開發上那一股"Me Too" 的產業文化。...這是值得大家思考的。
(待續)


USB DIY-- 自學計畫(六)


USB DIY-- 自學計畫(五) -----
關於F3xx 系列有關於USB 應用參考韌體程式有兩支:
1 : USB_Bulk : 就是我在(一)~(五)中所用的。 這一隻範例您是需要外掛屬於自己的
PC 端的驅動程式的。我想這一種USB應用大家可能都比較害怕吧。
2 : USB_HID : 這一隻範例程式用的是標準Microsoft 的驅動程式,但我想您也不會只拿來寫
滑鼠或鍵盤吧,自從iPhone/iPad 創造流行之後,作滑鼠、鍵盤的廠商應該都在那剉著等吧。
鍵盤的就不用說了。至於滑鼠功能,我想多點觸控屏的特性應該跟傳統滑鼠的定義不同吧。
當初USB 在HID 中定義滑鼠時,應該也沒想到多點觸控吧。---詳細的規格我就不知道了。
-----
我們也發現這兩支範例程式的程式風格,應該是不同人員撰寫的,所以,如果您要同時參考
這兩支範例程式時,最好有心理準備。以我自己本身經驗稍微看了一下他們的程式的架構,
不要說其他USB 特殊應用功能,光是處理USB Chapter 9 標準命令來說:我都覺得
這兩支原廠的範例程式都寫得不好。尤其對於USB新手要學習 USB都有不容易的盲點。
更何況當您是沒有寫過多少 8051 單晶片C 語言的新手來說:可能更難了。
我們就以USB_HID 這一支程式來簡單說明一下,我之前在USB DIY 一系列的基礎USB
系統說明中有說過,所有USB MCU IC 幾乎全都採用所謂的Interrupt Event 來處理
所有USB 匯流排上的所有USB Token (包括RESET、SUSPEND、STALL 、SETUP、
IN 及OUT 等,尤其是後面那三個SETUP 、IN及OUT 幾乎就是佔去絕大多數的USB
 匯流排 Event 。)
所以,如果您真的沒有好好的掌握這些USB 匯流排上的Interrupt Event 的話,
您要好好的維護您的USB 韌體程式是很辛苦的,您以別以為只要套用原廠的範例程式,
稍微改寫一下就好像很好用了,其實不然,如果您的USB 系統應用稍微偏離一下原廠
的範例功能外,您可能就完全掌握不到人家原廠USB MCU IC 的精髓了...
---
(其實,我也沒說人家原廠USB MCU IC 就一定很好用,或是說您就非用不可,
我說過了,現在賣MCU IC 就像士林夜市賣蚵仔煎一樣,大家賣的都是差不多的東西,
就看您自己喜好程度,不喜歡的您就再換一家嘛!像這系列的USB MCU IC 也沒有
想像中那麼容易掌握,您別看他一些 Registers 好像不多,更何況還有一些像廢物一般的
無用的Registers ...連原廠的範例程式都沒用,譬如:FRAMEL/FRAMEH、INMAX、
OUTMAX等等這些暫存器,以我們用過USB 經驗來說:反正都還要定義自己的傳輸參數,
給這些也沒用,就算我們拿來檢查一些USB 狀況來說:如果這些東西都已經出錯了,
那大概這一棵USB MCU IC 也不能用了,也會被應用市場給唾棄了吧!
所以有些搞IC 設計的老是會偏離系統應用角度,搞一些有的沒有的暫存器給我們用,
也都不一定對於我們系統應用有所正面幫助的...這一點您自己本身要有一定的判斷能力。)
----
我們就作一些簡單的示範來說明一下:
(注意:我們講的還是很基礎的USB Chapter 9 標準命令的韌體程式的掌握程度,
這一部份套用在另一支USB_BULK 範例程式也是一樣的!)

首先我們先把一個簡單的 I/O Toggle 擺在 USB_ISR 中,來觀察所有的USB interrupt Event,
只要有任何USB Interrupt Event 發生就可以觀察得到,然後我們就可以利用USB 分析儀
來觀察每一個USB Interrupt Event 的發生點(程式進入點)。

結果,這是一個最簡單最基礎的USB Enumeration 第一組命令:Get Device Descriptor 。
我們就可以發現每一個 SETUP/IN/OUT Token ,,,我們的USB MCU IC 都會收到Interrupt
Event。但是原廠的範例程式並沒有把每一個Interrupt Event 作適當的判斷與處理。
當然啊,如果您真的覺得您USB 系統功力真的很好,您都可以把這些Interrupt Event
 視而不見,我也沒意見,但我說過了,等下回您突然要又不同的USB 系統應用時,
您最好可以自行處理與應付。但我個人覺得:
如果新手在學USB 韌體時,沒有留意到這個東西與流程時,可能是很難掌握USB 韌體的。
對於這部分的韌體,我是覺得原廠這顆USB MCU 還有一個很搞笑的地方,
他裡面有定義一段韌體:

如果照原廠的說法:您發現這一個中斷旗標(SUEND)發生時,您就可以作如此處置。
但我是覺得如果在USB 匯流排上發生這個問題時,大概您的USB MCU 也掛了吧。
因為USB 匯流排上也不太可能只掛您一家的USB MCU 啊...而且現在USB MCU 的相容性都
很高了,我想會發生說:當您明明已經完成OUT Token 然後在等 In Token時,您的USB SIE
還可以解到一個屬於您的OUT Token...您該不會怪人家USB HOST IC(主機板南橋晶片)
有嚴重疏失吧?!這可能在早期還有可能,現在應該沒有了吧。至少我都沒碰過啊。
----
我們再回到之前那個USB Interrupt Event...我們可以看到明明有這些USB 中斷,那您知道
這些USB 中斷對應到您韌體程式的哪一段嗎?!...答案是:都沒有。原廠的範例程式沒寫。
所以,我們就稍微改寫一下原廠的範例程式:

加入這兩段程式,然後也Toggle 一些I/O 再來觀察實驗結果:

果然我們就完全掌握住每一個USB Interrupt Event 的程式進入點,至於您要不要做一些對應的
系統應用,就看您的本身在系統應用上的需求了啦。
---
當然啊,我們在真正的系統應用上,也不能只有加這兩行而已,否則,這種程式的寫法就是
貼狗皮膏藥的作法...真的不值得鼓勵去做。
最基本的問題是:原廠所附的這個程式在USB 控制流程上的韌體程式的寫法不夠
明確(這是我個人的看法。),其實,如果您也像我一樣看著USB 分析儀的答案也未必能夠
很快的去解讀程式的含意...但是難道沒有人跟原廠反映過嗎?!
-----
對於這一個這麼簡單的原廠韌體程式的修改實驗觀察,我們不是要說原廠的程式不能用,
我說過了,我也相信可能也有很多人都沒有留意到這一點,就劈里啪啦開始作系統應用
發展,對於一般基本的USB 應用應該還好,但如果您是要做類似USB_BULK 那一種有
自己驅動程式,有自己的Vendor Command 的...您還是最好熟悉下這一個問題吧,
但對於我來說:能改寫或作這個實驗,對於我們可以很快的熟悉及瞭解這一棵
USB MCU IC 的每一個USB 控制Registers 來說:是更容易明白與清楚其用法的。
或許您也可以參考這一個作法試看看。
----
PS : 其實,原廠這樣子寫USB 標準流程韌體(我們俗稱的USB HomeKeeping 程式),
不是很好的寫法,對於一些想學這一棵USB MCU IC 的工程師來說:真的沒那麼容易上手,
但我也說過了:對於許多USB新手工程師來說,大部分都不會太質疑或甚至改勇敢的去改寫
一個似乎可以用的程式...這個就是我們台灣科技教育制度的習慣,也造就了我們在工程技術
與產品開發上那一股"Me Too" 的產業文化。...這是值得大家思考的。
(待續)

2 則留言:

  1. DBpin2說明在控制傳輸過程中的setup + data +status 三個階段都會產生USB中斷?(應該是這樣)
    SETUPINPhase =0 , 表示是setup ..SETUPINPhase =1 , 表示是data .......SETUPINPhase =2 , 表示是status.
    經過您的說明~我自己在看了程式. 如果是取得描述元...步驟如下
    SETUPINPhase =0 .....MCU 將資料填入fifo0..
    SETUPINPhase =1.......因為是IN~所以是PC將資料收走後產生的中斷~MCU在中斷內沒做什麼事情
    SETUPINPhase =2.......MCU內會寫入SSUEND暫存器表示結束.....
    以上三個步驟~完成取得描述元.....  以上我的敘述有錯誤嗎?請指正.謝謝
    對於USB初學者~或許知道控制傳輸的三個步驟~但是對應到程式碼中~還真的不容易看清楚看三個不走在哪? (我也不知道我上述的說明是否正確..)
     

    回覆刪除
    回覆
    1. 關於您補充說明的部分:
      SETUPINPhase = 0 。對的。
      SETUPINPhase = 1,也對的 。
      SETUPINphase = 2 。不對...其實,這一個中斷沒有任何對應的Registers 可以對應。程式也沒有做什麼。但是他真的有發中斷。...這一點真的很重要了。
      因為我之前有提過一個重要觀念:有許多USB 系統應用是要先完成USB Protocol 之後,才執行PC HOST的相關指定動作。但如果您沒有留意到後面這兩個中斷(原廠原始的參考程式)。貿然的提早執行相關應用程式的話,您有可能因為這兩個莫名的中斷造成您其他應用的 Stack 或參數(因為BANK 切換)錯亂。這一種BUG 是很難查的。...
      所以,我才會說:一定要先搞清楚這一個問題與他原始的CPU 動作。
      關於這一部份我會另外Post 文說明的。敬請期待。 :> ...

      刪除