2020年11月4日 星期三

STM32_USB_DIY(三) --- Custom HID (三) :PC 端應用軟體及韌體開發

上回已經把我們所需要的驗證開發平台都做一個簡單的整理與介紹了。

接下來我們就可以開始拿原廠所附的參考原始碼做一個簡單的驗證開發了。

不過,因為USB 的東西,肯定是需要PC 端的軟體配合,尤其是這一種屬於

比較客製化的 Custom HID 的東西,雖然HID 是不需要PC端的驅動程式,

但還是得要準備自己的上層應用軟體,這個不像一般標準的Virtual COM 可以

用超級終端機;或是用一般俗稱隨身碟的MSDC,可以用電腦的檔案管理員。

Custom HID 就得要有自己的應用程式,上一篇我們也有提到原廠也有針對

這個範例程式所提供的應用程式:USB HID Demonstrator (V1.0.2):



但這個程式真的太複雜了,一般新學者對於這樣子的軟體真的太難了。

我是有自己的軟體開發習性,還是選一個自己比較上手的方式開發吧。

當然啊,原廠所提供的程式就是給我們一個參考,就像原廠這支Custom HID 韌體

我們也只是先參考一下,然後還是會依照我們的實際需求,而進行改寫的。

就看每個人對於這樣子的學習條件與未來系統需求而定吧。

只不過,現在因為軟體開發工作跟我們那個年代不同了,不是每個人都還那麼

喜歡用 C 語言來開發上層應用軟體,那還是得看你如何從你所熟悉的工具去找出

適當的軟體開發工具平台吧,我們老人家用的方式你就加減參考一下吧。

上圖這個是我自己用我自己比較習慣的方式所寫的上層應用軟體。

他是用微軟的 Visual Studio 2010 的 MFC  所寫成的。重點還是在於USB 的相關功能吧。

因為軟體的東西,基本上是看不到你的裝置端系統所採用的USB MCU的,

這個東西基本上跟你所採用的 USB MCU (不管是八位元或32位元的MCU)都是一樣的。

所以有些東西你也可以參考以前我在八位元所講的軟體東西:

USB DIY-- 自學計畫(十)


USB DIY-- 自學計畫(十一)

---

當然這個軟體的架構,基本上還是跟你USB 裝置所宣告的USB HID Report Descriptor

內容是息息相關的,上一篇文章的最後我們也有交代一下原廠這一支範例程式的

一些USB 相關宣告,所以我們主要就是有SET REPORT 及SET FEATURE的輸出,

及EP1 的INTERRUPT 輸入,軟體上我們也是用類似原廠軟體的LED 燈號控制方式

來下達USB HID 輸出,而在EP1 的輸入方面,我們就用一個簡單的 List Control 表單

依序把USB 裝置所回報的USB 內容顯示出來。好吧,我們就先直接結果吧:




在影片中:我們可以透過UART 的超級終端機與PC 端的軟體操作,我們就可以

很快地了解到USB Custom HID 與PC 軟體如何交互作用關係了。

用USB 來搞PC 端的資料交換或控制方式無非就是如此這般而已。

我說過:基本上還是跟一般UART 的TX/RX 道理是一樣的。

---

但這個展示影片中有一個很奇怪的現象:


那就是我們用EP0 的SET Feature 的方式下命令時,我們的韌體卻會執行兩次點燈

控制,而用一般EP1 的SET Report 方式不會。

所以我跟你常說過:人非聖賢,原廠的工程師也是人啊,他們也是會犯錯的。

你不要以為拿到原廠範例程式,就認為這個程式就標準無誤的程式,你自己真的要小心

了。很搞笑的是:這是最新版本 4.1.0 的錯誤,舊版不會有這個問題。而且更搞笑的是:

原廠在程式庫更新說明中,還特別強調說:這個就是為了解某些BUG 而修改的,

Update History

V4.1.0 / 26-May-2017

Main Changes

  • Official release to support  STM32F302x8 and STM32F303xE devices
  • Use latest version of STM32F10x, STM32L1xx STM32F30xx HAL  and CMSIS (for more details refer to each component's release notes)
  • STM32_USB_FS-Device_Driver
    • usb_core.c
      • Add test variable (DevRemoteWakeup) to solve issue regarding the device cannot wake USB host when receiving a second SUSPEND.
      • Fix issue in function DataStageOut regarding reporting status results for status IN stage.

而且這個問題已經更新三年多了,竟然也沒人發現。他的這段程式如下:


他的說法是為了USB Spec:Section 8.5.3.1 的規格說明。但這一部分早在USB 1.1 就有了。

只是他所加入的那行程式碼的位置不對,而應該移到上圖所示位置。

你應該要知道原廠的程式為什麼要這麼寫的?因為當USB 傳輸出了問題(STALL),

我們系統應用程式怕會斷了,死在那裏,所以乾脆在回STALL 之後,執行一下

我們的應用程式,但如果系統沒有發生問題時,那原廠這支程式會跑兩次

    (*pProperty->Process_Status_IN)();

這段程式碼,原來在正常完成USB 標準協議之後,本來就會跑一次了。

真的是不改還好,越改BUG 越慘...唉,這個程式還是標準程式庫裡的函數呢。

(一般我們都會把他鎖住,而不能修改的。)

----
好了,你以為原廠的程式就這樣子而已嗎?錯,他還有另一個問題:




因為他原廠原來的程式是一開始時,四顆LED 是亮著的,然後在USB 插入時,

才會把LED 關掉,這好像很合理,但他程式裡關燈的程式碼是在上圖中。

我們透過UART 除錯軟體監看時,發現:他根本在我們USB 插入時,執行了兩次,

這當然不合理啊,所以他所給的範例程式也是錯的,很簡單:他程式中把一般標準

Chapter 9 標準命令跟一般 Class 的應用命令給混在一起了。

如果你沒有留意這一點的話:你系統當然就會覺得怪怪的,怎麼會突然會被其他

不明原因給干擾了?尤其USB 的東西非常在意系統相容性問題的。

而且USB 插入偵測與USB系統初始化,也不是這樣子做的。可見這是一般寫軟體的人

用自己寫PC 軟體概念寫的東西。

所以這個問題的解法是:將一般USB Chapter 9 標準命令與我們Class 命令組,

分開處理:


如上圖所示,這樣子我們就可以把這個問題給解了。

基本上,光我自己在驗證跑原廠所提供的USB Custom HID 範例程式時,

就發現了這些問題,有些還是屬於原廠所提供的標準底層函數庫的內容。

所以你平常要使用這些函數庫時,還是要多留意一點。

---
當然這些都不是一個很簡單就可以察覺發現的問題,有些真的是我個人經年累月

所得的一些經驗,當我在跑USB 這些程式時,往往有些我一覺得不對的地方,

他就可能會出錯,可能就是所謂的"莫非定律"吧。

而這些基本上還是都是屬於很基本的 Tx/Rx 的在系統上的使用的基本概念。

當然原廠這支範例程式跟我們一般USB 或是 UART 通訊協定程式還差很遠,

因為這些命令在下達或資料在交換時,還是沒有系統上檢查機制,

雖然USB 已經幫你保證傳輸內容無誤了,但在系統上的 Handshake 或是

系統穩定性的問題,這些原廠程式都沒有幫妳做到,這些還是都需要你自己

慢慢地去完善他,當然啊,基礎上,你就得對USB 的基本傳輸功能規格,

及PC 端應用軟體與韌體開發之間的關係還是要掌握才行。

而以我本身的經驗,這樣子簡單的三個步驟與三篇文章的交代,

我是可以掌握到 stm32 這一顆MCU 關於USB 介面的處理方式了。

不知道你還缺哪方面的了解呢?當然啊,USB 的系統應用千百種,

每一個人或每一個案子的系統需求與規範都不同,甚至還要求做到

以USB 介面完成韌體升級功能等等,這些都是從這些很基本的USB

架構出發的。

所以關於 stm32 USB 的 Custom HID 的說明的介紹,就先告一段落,

往後關於 stm32 的USB 系統應用可能就不會再從這個原廠的範例程式

再說明了。

感謝你的點閱。下回繼續。謝謝。
 










12 則留言:

  1. 請教一下,
    HID 跟 CDC 都可以進行資料傳輸,它們應用的情境差異在哪?
    哪種情況較適合 HID? 哪種情況較適合 CDC ? 謝謝

    回覆刪除
    回覆
    1. 我說過:基本上所有的資料傳輸都只是Tx/Rx 而已。

      只不過還是要看在市場上對於這些通訊系統的維護問題而已。

      之前大家也有討論過USB 轉UART 晶片相容性問題,如果這個東西這麼好搞,

      那市場上就不會有這些相容性問題聲音了。

      另外我提一個我自己的經驗:那就是我之前搞的那個可程式化CDI 的東西,

      我原本也是提供UART 功能而已啊,客人隨便去買個USB 轉UART 的東西就好了。

      但我碰到的問題是:你要教客人懂得去找是哪一個COM port,不是每一台電腦或

      每個人都懂得你這個是在講甚麼?還何況甚麼是Baudrate 這種名詞耶。

      因為你的客人可能連電腦或USB 是甚麼東西都搞不懂的。

      我後來還是用一般HID 就解決了。所以你提這個問題就不用從技術角度來看這些事。

      你就想像一下:你把你的東西交給一個大媽使用時,她可以簡單上手就可以了。

      那你就知道哪一種技術方法是最好的、最洽當適合的。

      所有的東西都是一樣的:若是要客人可以簡單一點的,在技術上你就得花多一點功夫。

      你不想花太多時間或技術時,你就期望你的客人"聰明一點",但往往事情就是如此。

      我搞技術也想簡單快樂一點啊,只是有時候客訴是比甚麼艱深的技術還難搞啊。

      刪除
  2. 謝謝回覆, 受教了

    回覆刪除
    回覆
    1. 你可以參考看看,或許有些時候,你可以用CDC 就可以搞定,

      省去軟體與韌體之間繁雜的溝通與協調工作,也是可以完成老闆所交差的事啊。

      刪除
  3. https://medium.com/coinmonks/stm32-blue-pill-usb-bootloader-how-i-fixed-the-usb-storage-serial-dfu-and-webusb-interfaces-36d7fe245b5c
    wireshark也支援USB封包除錯,那天我試試,也許不用到封包檢測器也可以看封包內容。

    回覆刪除
    回覆
    1. 感謝你所提供的資訊,有需要的朋友可以依據所提供的連結網頁參考一下。

      現在網路資訊真的很發達,其實只要你用心找一下都應該可以找到你所要的資訊,

      也可以依據每個人的需求,自行考量下載或是參考使用。

      有時候都覺得自己搞的東西也好像沒那麼偉大的或多艱深的技術與學問。

      無非就是花苦工拼拼湊湊實現一些東西而已。

      所以現在搞東西不是做不做出來的問題,而是你們公司是要找多少人來完成而已。

      像我現在許多東西,都是別人認為這樣子的東西也好像不太需要長期養一堆人搞。

      先找個一兩個人,也好像就可以解決許多產品開發或技術評估的工作,

      等真正有需要時,再說了吧。你會算,老闆更會算的啦。

      刪除
  4. 今天和某大廠RD在爭論HID Report Descriptor的問題。因為是現在產品升級PC軟體是固定的,我寫uart-USB橋接器,就去和大廠要HID設定,結果對方沒有給Report設定資料,我回頭去問,對方答沒有,還說本來就沒有為何要給?還拿Bus Hound錄到的資料和我說,就給64byte的資料,為何還有report格式?
    沒辧法,只好去借對方舊機來抓report設定內容。
    不過真的沒有HID Report Descriptor會動? 我猜對方是純軟。

    回覆刪除
    回覆
    1. 喔~如果是走 Custom HID 的話,還是需要有一點傳統系統傳輸觀念比較好一點。

      因為還是牽涉到許多自行定義的資料格式與內容。

      我是不知道你所指的HID Report Descriptor 是哪一種HID ?

      我是知道有人是用Generic 那一類。而非 Vendor 那一類。Generic 那一類我沒用過。

      所以他們可能就沒有使用到 Report ID 這一種方式,雖然宣告簡單,但後續當系統

      命令複雜度一增加,就非常容易搞混...會造成維護上的困難,

      況且因為沒有Report IC 區別,所以所有USB Packet 資料長度只有一種:

      你所說的就是 64 Bytes...嗯,這的確是純軟的人想法,因為其實有些資料訊息

      真的不需要這麼常資料,譬如那個 Interrupt IN,是每隔幾個 mSec 就給一筆。

      如果可以用一兩個 Bytes 可以處理的,幹嘛要用 64 Bytes 來佔用系統頻寬

      降低系統效能呢?(其實更麻煩的是Debug ...)

      不過,這也不意外,因為純軟的人也不太想花心思在USB Device 端的應用,

      更不會替USB device 的工程人員想的。

      祝福你吧。

      刪除
  5. https://eleccelerator.com/usbdescreqparser/
    已經用wireshark取得mouse的HID Report Descriptor,再加上上面的分析器。只等對方的機器了。

    回覆刪除
    回覆
    1. 其實USB 的應用,只有一開始在定義雙方 Protocol 時,才需要用到所謂的

      分析儀或查看資料內容。真正大部分的USB 系統發展還是屬於傳統的Tx/Rx

      在系統上如何資料同步與傳輸資料控管。

      所以重點還是在於一開始如何定義雙方的Handshake 或Protocol 的格式。

      但往往沒有多少人願意把這些東西事先在筆記本上先推導或定義清楚。

      常常是邊寫韌體,邊定義...其實這都很容搞亂自己的系統架構。

      沒把這些事先工作做好,當然事後,大家就得更憑自己的本事,用各種分析儀資料

      來佐證自己的想法是對的...但事實真的如此嗎?

      當你證明別人是錯的時候,也並不代表你自己就是對的答案啊。

      所以為什麼我都自己先把第一關打通(PC APP 與USB Device 之間的Handshake與Protocol)。

      否則,我發現:這樣子搞真的很浪費生命啊。不管是有形的健康的肝或血壓指數,

      或是無形的負面情緒累積...其實這些都對自己年紀增長而不健康的啦。

      供各位參考一下吧。

      刪除
  6. WebUSB沒有支援HID,是因為分出來WebHID。也就是一般HID裝置是用webHID介面。個人是覺得支援game裝備需求比較重。

    回覆刪除
    回覆
    1. 我在猜啦,因為如果越是容易客製化的,隨著不同應用而有非常多變化的東西,

      就更不容易包成固定的格式或用固定的形式來讓大家直接套用吧。

      USB Class 的東西雖然是儘量包山包海的把許多大部分的應用給標準化了。

      但還是有可能會有一些"漏網之魚"的特殊應用吧。

      這就像我們以前用RS232 或並列埠的觀念一樣:明明一開始RS232 就是

      給你們MODEM 用的,就是用AT 命令,而並列埠就是拿來搞印表機的。

      但就是有許多人拿這些介面搞一些奇奇怪怪的周邊產品應用,甚至後來的工控等等。

      所以USB 最後還是會有一堆奇奇怪怪的周邊應用吧。

      至少光USB Custom HID 就是很明顯的一種。

      (當然啊,隨身碟的 MSDC 還是有人在系統規範中找出 SCSI pass-through command


      的做法,偷偷的偷渡自己的東西在標準產品介面裡啊。)


      規格書寫的是死的,人的腦袋應用是活的,就看每個人的功力展現了囉。

      刪除