焦杰,王英濤
(1.吉林省廣播電視研究所,長春130041;2.吉林省廣播電視技術中心臺)
?
用于遠程廣播監(jiān)測的組合USB設備接口設計
焦杰1,王英濤2
(1.吉林省廣播電視研究所,長春130041;2.吉林省廣播電視技術中心臺)
介紹了一種應用在遠程廣播無人監(jiān)測點的組合USB設備,使用一片STM32F407單片機的單個OTG_FS同時設計出兩個設備接口,其中一個是監(jiān)測專用的自定義USB設備,另一個是標準HID設備。整個系統(tǒng)除了具備廣播信號監(jiān)測接收功能之外,還帶有計算機運行監(jiān)控看門狗、遠程電源遙控器和一個遠程USB鍵盤。對于64位Windows不允許安裝未簽名的自定義設備驅動程序問題,采取了WinUSB方案解決。
廣播監(jiān)測;USB;組合設備;WinUSB;STM32F407
在廣播電視監(jiān)管工作中,需要設置一些遠程的無人監(jiān)測站,用于收測當地的廣播無線電信號,并對節(jié)目的內容進行自動語音分析,然后利用網絡把監(jiān)測信息回傳到監(jiān)測中心。系統(tǒng)主要由信號接收監(jiān)測主機、監(jiān)測計算機和網絡設備組成。為保證系統(tǒng)長期穩(wěn)定運行,還需要具備系統(tǒng)看門狗、遠程電源遙控、遠程HID鍵盤等附加功能。監(jiān)測主機使用一片STM32F407單片機,利用OTG_FS接口設計出一種具備信號監(jiān)測、系統(tǒng)看門狗、遠程鍵盤等多種功能的組合USB設備,在實際應用中取得了良好的效果。
為了直截了當地解決困擾USB相關研發(fā)過程中的幾個實際問題,本文用實例講述研究過程中涉及的主要技術點。
① 如何設計多功能的USB組合設備: 在一片STM32F407的OTG_FS接口上實現兩個USB設備,一個是自定義的廣播監(jiān)測接收設備,另一個是HID鍵盤設備。
② 怎樣解決64位Windows系統(tǒng)的驅動程序: 64位Windows不允許安裝未簽名的驅動程序,限制了自定義USB設備的應用。針對這一問題,本文介紹一種采用WinUSB的解決方案,可以實現從Windows XP SP2到Windows 10,無論32位還是64位系統(tǒng)全兼容。
③ 實現Windows系統(tǒng)中應用程序: 設計應用程序與自定義USB設備通信、控制設備,并傳輸大量的廣播節(jié)目聲音數據。
④ 系統(tǒng)管理與遠程HID鍵盤: 利用USB通信實現系統(tǒng)運行看門狗,并結合網絡實現遠程電源遙控和遠程HID鍵盤功能。
整個監(jiān)測前端由信號接收監(jiān)測主機、監(jiān)測計算機和網絡設備三大部分組成,其中的信號接收監(jiān)測主機也兼用作遠程電源遙控器、遠程USB鍵盤和系統(tǒng)運行看門狗。遠程廣播監(jiān)測前端結構框圖如圖1所示。
圖1 遠程廣播監(jiān)測前端結構框圖
信號接收監(jiān)測主機中的接收電路完成廣播信號的接收,編碼后的聲音數據由STM32F407單片機利用USB接口送給監(jiān)測計算機。監(jiān)測主機具有網絡接口,可以接收監(jiān)測中心的電源遙控命令,遠程開啟或關閉計算機,甚至可以遠程關閉網絡設備的電源。
監(jiān)測計算機需要定期向單片機的USB控制接口發(fā)送握手命令,如果單片機在較長的時間內不能收到USB握手信息,那么就認為監(jiān)測計算機發(fā)生故障,利用電源控制電路關閉計算機電源,過一段時間再自動打開,實現自動重啟計算機。
單片機在一個OTG_FS接口上組合了兩個USB設備:一個具有聲音數據接口及控制接口的自定義設備和一個HID遠程鍵盤。當監(jiān)測計算機發(fā)生特殊故障,不能進入系統(tǒng)時,利用這個遠程鍵盤可以幫助遠程排除故障。
單片機采用USB接口與計算機通信的電路非常簡單,只需把STM32F407的OTG_FS引腳經匹配電阻聯接到計算機的USB口即可。單片機USB接口部分電路圖如圖2所示。
圖2 單片機USB接口部分電路圖
可以在一個USB接口上實現多個USB設備,最常見的是那種只有一個USB插頭的無線鍵盤鼠標組合。有兩種方法能夠在一個USB接口上實現多個設備:一種是復合設備(Compound Device),另一種是組合設備(Composite Device)。復合設備就是把幾個獨立的USB設備用HUB連接在一起,每個設備有各自獨立的設備ID。而組合設備是在一個設備上實現多個接口,它們共用同一個設備ID。復合設備中有HUB,具有繼續(xù)向下級連其他設備的潛力,但是這種設計比較復雜,占用資源較多。相比之下,如果想要實現同樣的功能,設計組合設備會更為簡單方便。
2.1 實現USB組合設備框架
因為USB設備比較復雜,所以從零開始設計絕對不是個好主意,利用現成的例子進行改造會方便得多。在STM32F407單片機固件庫中,有一個USB FS Examples USB_Device_Examples HID例子,可以在它的基礎之上修改得到所需要的USB功能。其中有兩個關鍵問題:需要知道在哪里改和明白應該改成什么。
首先需要修改那些描述符,實現設備的基本框架。因為設備描述符部分只需要改PID和VID,比較容易,所以主要的工作內容是修改配置描述符、接口描述符和端點描述符。例子程序把這幾個描述符按順序排列在USBD_HID_CfgDesc數組中。原來描述符結構需要修改成新結構,如圖3所示。
圖3 描述符結構的修改
2.1.1 修改USB設備ID
所有PNP設備都必須具有設備ID,修改usbd_desc.c中的USBD_VID和USBD_PID,改成不會與其他設備沖突的數值,這兩個數值還要寫到安裝驅動程序所需的那個INF文件中。
2.1.2 設計通信端點
在usbd_conf.h中添加聲音及其他端點號,并設定端點包長度。因為原始例子是HID鼠標,所以只有HID_IN_EP一個IN端點。改成鍵盤需要增加一個OUT端點HID_OUT_EP,它可以接收到鍵盤上指示燈的狀態(tài)信息。為了能傳輸大量的聲音數據,需要再新加兩個IN端點VENDOR_IN_EP_AUDIO1和VENDOR_IN_EP_AUDIO2,并多加一個OUT端點VENDOR_OUT_EP,用于向自定義設備寫出數據。因為鍵盤的數據包比鼠標大,所以需要改大HID端點包長度為64。
2.1.3 配置端點FIFO
使用STM32F407單片機的OTG_FS進行設計,需要修改usb_conf.h,為各端點重新分配FIFO長度。必須注意在原始例子默認狀態(tài)下,只有EP0和EP1是可用的,其他端點因沒有分配過FIFO所以還不能用。需要用哪個端點就必須給它分配FIFO,特別要注意STM32F407的FIFO總共有320字節(jié),各端點FIFO加起來的總數量不可以超過這個總長度。
2.1.4 修改配置描述符
在usbd_hid_core.c設計配置描述符,也就是修改USBD_HID_CfgDesc數組,把bNumInterfaces從1改成2,表示有HID鍵盤和自定義設備共計兩個接口。再把接口描述符的bNumEndpoints從1改成2,表示這個HID鍵盤接口上有兩個端點;nInterfaceProtocol從2改成1表示把鼠標改成鍵盤。
在原來HID端點描述符之后,仿照原來的IN端點添加一個新的HID_OUT_EP端點描述符。注意鍵盤鼠標端點的bmAttributes是3,表示采用中斷傳輸模式。
2.1.5 添加自定義設備的描述符
在HID端點描述符之后添加自定義設備的接口描述符,可以復制前面的HID接口描述符,在其基礎上進行修改:
① bInterfaceNumber是順序號,在前面的HID接口描述符里是0,所以輪到這個需要用1。注意這個值與后面驅動程序安裝有關,在后面介紹WinUSB驅動程序安裝時會再次看到它的作用。
② bNumEndpoints是端點數量,自定義的監(jiān)測設備有3個端點(bInterfaceClass、bInterfaceSubClass、nInterfaceProtocol),改成0xff、0x00、0x00表示自定義的設備。在接口描述符后面,依次羅列這三個端點描述符,仿照HID端點描述符填寫即可。
2.1.6 修改HID報告描述符
HID鍵盤還需要一個報告描述符,因為這個鍵盤不需要支持特殊的按鍵和指示燈,所以可以隨便找一個現成的例子。替換原來的鼠標報告描述符HID_MOUSE_ReportDesc,并注意修改程序中所有涉及到報告描述符的長度數值。
2.2 實現USB組合設備的固件接口程序
把修改數據之后形成的組合設備框架編譯寫入STM32F407,接到計算機上就可以看到在設備管理器窗口中會多出來三個設備:USB Composite Device、HID鍵盤和沒有驅動程序的未知設備。
2.2.1 新添加端點的打開與關閉
在usbd_hid_core.c中添加新端點的打開與關閉消息調用程序代碼。USBD_HID_Init函數中,原來有一個DCD_EP_Open,它只打開了鼠標的IN端口。仿照樣子添加打開新定義的HID_OUT_EP、VENDOR_OUT_EP、VENDOR_IN_EP_AUDIO1和 VENDOR_IN_EP_AUDIO2端口。在USBD_HID_DeInit函數中添加DCD_EP_Close,把這幾個新端口關閉。
2.2.2 非0端點數據收發(fā)
非0端點可以進行中斷傳輸或塊傳輸,在usbd_hid_core.c中添加自定義設備與計算機軟件塊傳輸的接口程序代碼,固件庫采用函數回調的方式來添加這些功能。在數據結構USBD_HID_cb中有一個DataOut,在那里設置一個回調函數USBD_VENDOR_DataOut (void *pdev, uint8_t epnum)。當計算機發(fā)送數據到設備的非0端點時,會觸發(fā)這個函數回調,并傳入參數epnum表明數據要發(fā)送到哪個端點,用USBD_GetRxCount庫函數可以取得本次單片機收到的數據字節(jié)數。
在數據結構USBD_HID_cb中有一個SOF和一個DataIn,在那里設置兩個回調函數,即USBD_VENDOR_SOF(void *pdev)和USBD_VENDOR_DataIn (void *pdev, uint8_t epnum)。USB總線的SOF信號會引起周期性地回調USBD_VENDOR_SOF,可以把這個函數回調作為可以向計算機上傳數據的啟動信號。每當設備向計算機發(fā)完一組數據之后,都將回調USBD_HID_DataIn函數。因此配合運用SOF回調結合USBD_HID_DataIn函數,在它們的處理函數中再使用DCD_EP_Tx庫函數,可以高速向計算機發(fā)送大批量的數據。非零端點數據發(fā)送中斷回調與主程序聯動流程圖如圖4所示。
圖4 非零端點數據發(fā)送中斷回調與主程序聯動流程圖
利用“正發(fā)送標志”來協(xié)調運用這兩個回調函數,可以快速傳輸大量的聲音數據。
2.2.3 專用控制端點0的數據收發(fā)
端點0是特殊的控制端點,在usbd_req.c中,有一個USBD_StdDevReq函數,每個對設備EP0的控制傳輸都會調用這里。USB_SETUP_REQ 結構保存著從計算機發(fā)來的控制數據。對于查詢少量數據信息的命令,可以直接調用USBD_CtlSendData庫函數傳送一些數據應答到計算機。而對于執(zhí)行較慢的設置,有必要聯合運用主程序main函數設計成異步工作方式。圖5是單片機異步控制、主程序聯動工作流程圖。
圖5 端點0異步控制中斷回調與主程序聯動流程圖
上位計算機把一個慢速異步設置分解成“設置”和“查詢”兩個步驟,先通知單片機進行設置,之后需要定期查詢設置被執(zhí)行的結果。單片機收到“設置”命令之后,緩存設置參數退出EP0控制傳輸處理子程序;然后主程序取得緩存的參數執(zhí)行這個設置,把設置結論緩存起來供上位計算機進行查詢。整個“設置”與“查詢”兩個任務過程的協(xié)調核心數據是“執(zhí)行狀態(tài)標志”變量,0表示空閑沒有任務;1表示已收到任務命令但還未執(zhí)行;2表示任務已開始執(zhí)行;3表示任務已經執(zhí)行完畢可查詢到執(zhí)行結果。
2.2.4 HID鍵盤收發(fā)數據
前面在定義端點時,HID鍵盤使用兩個中斷類型端點HID_IN_EP和HID_OUT_EP收發(fā)數據。利用HID_IN_EP端點,可以把從網絡遠程傳來的數據轉成鍵盤按鍵信息。
一條按鍵信息有8個字節(jié):
第一字節(jié)為SHIFT、CTRL等特殊控制鍵的位組合,每位代表一個按鍵;
第二字節(jié)為保留字節(jié);
后面字節(jié)為每一個字節(jié)都可以填入鍵盤掃描碼,支持6個鍵同時按下。
主程序可以調用DCD_EP_Tx庫函數向計算機發(fā)送鍵盤信息,一次鍵盤信息由一個按鍵通碼和一個斷碼組成。用于系統(tǒng)維護的遠程鍵盤不需要支持同時多按鍵功能,也不需要特殊控制鍵。如果想要按一下回車鍵,那么發(fā)送通碼數據是{0,0,0x28,0,0,0,0,0},斷碼是8個0。
在Windows系統(tǒng)中,組合USB設備的這個HID鍵盤不需要額外的驅動程序,而自定義的USB設備必須安裝驅動程序。64位系統(tǒng)對驅動程序的要求較為嚴格,只有經過數字簽名的驅動程序才可以正常安裝。本文介紹使用系統(tǒng)自帶的WinUSB驅動程序可以滿足自定義USB設備的需要。
3.1 WinUSB簡介
WinUSB是Windows系統(tǒng)自帶的USB驅動程序,用它可以讓自定義的USB設備在XP、Vista、Win7、Win8、Win10上得到全面的支持,不論是32位還是64位,都能兼容。驅動開發(fā)工作僅僅是再提供一個INF文件去安裝自定義的USB設備。
3.2 WinUSB驅動程序安裝
在MSDN,有一篇名為《WinUSB (Winusb.sys) 安裝》[3]的文章,里面可以找到安裝過程的介紹。除非有特殊的問題要查找,否則不需要細看那些內容,直接從“編寫適用于WinUSB安裝的自定義INF”那段復制INF例子內容,在其基礎上修改成自己的安裝程序。
對于普通的USB設備,只需找到%DeviceName% =USB_Install, USBVID_0547&PID_1002那行,改成前面在usbd_desc.c中的USBD_VID和USBD_PID就可以了。然而對于本文介紹的這種組合USB設備,還需要在PID的后面增加接口序號。在前面介紹接口描述符時,自定義設備的接口號是1,所以設備名要寫成:USBVID_0547&PID_1002&MI_01。
INF文件中還有一節(jié):
[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
需要注意這行與應用程序枚舉驅動程序有關,這個GUID在本文后面設計應用程序時會用到。
應用程序必須調用Winusb.dll與自定義的USB設備通信,其接口說明在參考文獻[4]中有介紹,應用程序接口設計在參考文獻[5]中有較詳細的介紹,并提供了代碼。這里不重復介紹其內容,只對容易出現的問題提供解決方法。
4.1 準備Winusb.dll的接口H文件
為了讓應用程序代碼適用于多種編譯環(huán)境,建議采用動態(tài)加載Winusb.dll的方法來控制自定義的USB設備。對應的接口H文件Winusb.h可以在WDK中找到。
4.2 枚舉自定義的組合USB設備
在MSDN中介紹了用SetupDiGetClassDevs和SetupDiEnumDeviceInterfaces這兩個API來枚舉USB設備,需要注意輸入的GUID參數。本文在前面介紹INF文件提到過這行:
圖6 用控制線程強制退出數據讀阻塞的流程
HKR,,DeviceInterfaceGUIDs,0x10000,"{9f543223-cede-4fa3-b376-a25ce9a30e74}"
必須用這里的GUID進行枚舉,才能正確找到這個自定義設備。在枚舉成功之后,用Setup DiGet Device Interface Detail取得設備驅動的設備路徑實例,應用程序可以利用WM_DEVICECHANGE消息,在處理函數中枚舉設備在線情況,可以對USB的熱插拔進行及時處理。
4.3 打開與關閉設備驅動
用API函數CreateFile打開設備,可以得到自定義設備的文件句柄。為了使用WinUSB,要求這個API的參數必須設置FILE_FLAG_OVERLAPPED標志。
在WinUSB.dll中,所有函數都用WinUsb_開頭。WinUsb_Initialize利用設備的文件句柄創(chuàng)建一個WinUSB接口句柄,如果出錯,很可能是枚舉時用錯了GUID。成功創(chuàng)建之后就可以調用WinUSB的其他函數與單片機通信了。在程序退出或設備撤出時,必須調用CloseHandle關閉設備,用WinUsb_Free關閉WinUSB接口句柄。
4.4 控制端點EP0通信
本文在前面介紹單片機的控制端點EP0時,提到過USB_SETUP_REQ 結構。在WinUsb中有一個對應的WINUSB_SETUP_PACKET數據結構,它們是同樣的數據結構。也就是說,應用程序調用WinUsb_ControlTransfer時,會把WINUSB_SETUP_PACKET參數原樣送給單片機,然后單片機用USBD_CtlSendData庫函數應答的數據會填充到WinUsb_ControlTransfer的Buffer參數里返回給應用程序。
4.5 非0端點塊傳輸通信
應用程序調用WinUsb_WritePipe向單片機寫入塊數據,會觸發(fā)單片機中USBD_HID_cb結構上那個DataOut函數回調接收數據。單片機用DCD_EP_Tx庫函數發(fā)出的數據可以在應用程序中調用WinUsb_ReadPipe讀取。
通常為簡化程序設計,所以設置WinUsb_WritePipe和WinUsb_ReadPipe的Overlapped參數為NULL。在此情況下,這兩個函數都是阻塞的,如果出現某種情況,單片機不能提供足夠的數據供計算機讀取,或者不能接收計算機發(fā)出的數據,都會導致計算機程序鎖死在那里,不能繼續(xù)向下執(zhí)行。圖6描述了一個在數據讀取阻塞時,利用控制線程強制退出阻塞狀態(tài)的流程。因此有必要利用多任務把數據管道讀或寫的功能獨立到另一個線程中,主程序線程利用控制端點EP0來控制單片機那里對數據的接收和發(fā)送,在特殊情況下可以通知單片機強制接收并丟棄數據,或者胡亂發(fā)送一些填充數據,這樣就可以跳出WinUsb_WritePipe和WinUsb_ReadPipe的阻塞狀態(tài)。
對整個監(jiān)測系統(tǒng)的管理就是看門狗與遠程遙控管理,遠程控制功能有計算機遠程遙控軟件和網絡遠程遙控硬件兩個組成部分。
5.1 遠程電源管理器
計算機系統(tǒng)運行正常是所有計算機遠程遙控軟件可以正常使用的根本前提。一旦Windows系統(tǒng)死機或者進不去了,那么再優(yōu)秀的遙控軟件也都無計可施。在這種情況下,解決的辦法就只剩下計算機斷電重啟了。
使用STM32F407固件庫中的LwIP設計一個網絡WEB服務器程序,實現遠程在頁面上遙控單片機的一個I/O口電平,只需將這個I/O口連接到一個由三極管控制的繼電器上,就能實現對計算機電源的遙控功能。
用類似的方法可以設計網絡設備的遠程遙控電路。然而當網絡設備斷電之后,整個前端就無法再繼續(xù)遙控了,因此單片機對網絡的控制邏輯是斷電后延時幾分鐘再自動加電。
5.2 計算機系統(tǒng)運行看門狗
系統(tǒng)中有兩大看門狗,一個是計算機運行看門狗,另一個是網絡運行看門狗。計算機必須定期通過USB向單片機的VENDOR_OUT_EP端點發(fā)出喂狗命令,否則單片機就會認為計算機發(fā)生故障而自動關閉計算機電源,過幾分鐘自動通電再讓它重啟動。
在單片機中記錄著監(jiān)測中心服務器的IP地址,并且會定期主動聯接服務器的一個特定TCP端口。一旦單片機長時間始終無法與服務器聯接,就認為網絡設備發(fā)生故障,將自動對網絡設備斷電,然后延遲一段時間再上電,實現網絡設備遇到故障時的復位重新啟動。
5.3 遠程HID鍵盤
有時計算機會卡在系統(tǒng)啟動期間,需要現場操作鍵盤解決。例如64位WIN7有時發(fā)生故障會卡在“系統(tǒng)修復”界面,在這種情況下,如果沒人去按一下鍵盤回車鍵,那么就不能繼續(xù)啟動運行。這種系統(tǒng)故障發(fā)生時,因為系統(tǒng)沒起來,遠程軟件還沒啟動,所以任何軟件辦法都失靈,只有
依靠設計在組合USB設備中的HID鍵盤來執(zhí)行遠程系統(tǒng)修復了。在監(jiān)測中心利用網絡遠程登陸單片機的WEB服務器,在頁面上點擊“發(fā)送回車鍵”按鈕,單片機就可以把一個回車按鍵信息的一個通碼附加上一個斷碼從USB輸入計算機,就像在那個監(jiān)測點現場直接鍵入回車信息一樣。有了這樣一種遠程鍵盤,即使遠程無人前端進入不了系統(tǒng),或者沒有遠程遙控軟件,也可維護計算機了。
[1] 張秀娟,梁波.多功能USB組合設備的結構設計[J].單片機與嵌入式系統(tǒng)應用,2011(11).
[2] Microsoft提供的USB驅動程序[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff538853(v=vs.85).aspx.
[3] WinUSB (Winusb.sys)安裝[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540283.
[4] WinUSB Functions[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540046 (v=vs.85). aspx#winusb.
[5] 編寫基于WinUSB模板的Windows 桌面應用[EB/OL].[2016-05-30].https://msdn.microsoft.com/zh-cn/library/windows/hardware/dn376872(v=vs.85).aspx.
[6] STMicroelectronics.STM32F405xx/07xx advanced ARM-based 32-bit MCUs Reference manual,2013.
焦杰(工程師),主要研究方向為廣播電視信號監(jiān)測與控制技術;王英濤(高級工程師),主要從事調頻廣播和無線電視信號播出工作。
(責任編輯:楊迪娜 收修改稿日期:2016-09-30)
Design of USB Composite Device Interface for Remote Broadcast Monitoring
Jiao Jie1,Wang Yingtao2
(1.Radio&Television Research Institute of Jilin Province,Changchun 130041,China;2.Radio&Television Technology Center Station of Jilin Province)
In the paper,a USB composite device for broadcasting remote monitoring based on a STM32F407 microcontroller is introduced.Two device interfaces are designed by one OTG_FS circuit interface.The one is the custom USB device,the other one is the standard HID device.In addition to the radio signal receiving and monitoring,some other functions are designed,such as a power controller and a USB keyboard both from the remote network,and a watchdog of computer system is designed.For 64-bit Windows does not allow the installation of the unsigned custom device driver issues,the paper introduces WinUSB to solve it.
broadcasting monitoring;USB;composite device;WinUSB;STM32F407
TP37
A