文獻標識碼: A
DOI:10.16157/j.issn.0258-7998.2017.07.014
中文引用格式: 胡唯唯,王宜懷,張永. 基于K64的USB驅動構件化設計[J].電子技術應用,2017,43(7):55-58.
英文引用格式: Hu Weiwei,Wang Yihuai,Zhang Yong. The development of USB driver component based on K64[J].Application of Electronic Technique,2017,43(7):55-58.
0 引言
USB現已成為嵌入式設備的一種主要通信接口,但是由于USB協議的復雜性和硬件平臺的多樣性,使得USB驅動程序開發存在難度大、成本高、可移植差、難以維護等缺點。為了解決這些問題,本文在深入分析USB協議的基礎上,對USB設備的功能進行抽象,并采用驅動構件化的設計思想開發USB驅動構件[1]。同時,在Kinetis Design Studio 3.0集成開發環境下,使用恩智浦半導體公司的K64微控制器對該構件進行測試,將其作為一個HID設備與上位機程序進行通信。上位機軟件在VS 2010環境下使用C#語言開發,可以動態找到目標設備,實現快速連接和通信。另外,將該通信系統用于3D打印中,通過對打印產品的紋理進行分析,驗證本文所開發的USB構件的穩定性。
1 USB協議分析
USB驅動程序主要完成USB設備的初始化、枚舉和數據傳輸。USB主機與USB設備之間有4種數據傳輸類型,分別是批量傳輸、中斷傳輸、同步傳輸和控制傳輸,每種傳輸方式執行一次需要多個事務處理[2]。對于控制傳輸,其只能用于USB設備枚舉,包括3個階段,分別為設置階段、數據階段和狀態階段。設置階段是一次SETUP事務處理,數據階段是多個IN或者OUT事務處理,狀態階段是一次無數據傳輸的IN或者OUT事務處理。USB設備枚舉完成后,將使用其他傳輸方式用于實際數據收發,具體使用哪種方式則取決于設備的類型。USB設備連接到PC后,PC便開始對其進行枚舉[3]。不同操作系統下枚舉過程可能會有所不同,Windows操作系統下的USB設備枚舉過程為:
(1)用戶將USB設備插入到PC(USB主機)的USB端口上,USB主機給USB設備上電,USB設備獲取100 mA的電流,并處于上電狀態;
(2)USB主機檢測USB設備是全速還是低速設備,如果D+數據線上有高電平則是全速設備,如果D-數據線上有高電平則是低速設備;
(3)USB主機復位USB設備,復位時間至少10 ms。復位結束后USB設備處于默認狀態,并使用默認的地址0和端點0與USB主機進行通信;
(4)USB主機獲取USB設備的18 B的設備描述符,完成一次控制傳輸。這是USB主機第一次得到設備描述符,主機并不會分析各個字段的含義,只會得到設備描述符中端點0所支持的最大數據包長度(設備描述符的第8字節);
(5)USB主機再一次復位USB設備,這一步在USB 2.0協議中并不要求。另外,對于高速設備,Windows 8及以上版本會跳過這一步;
(6)USB主機給USB設備分配一個唯一的地址,USB設備進入地址狀態,之后USB設備將使用這個新的地址與USB主機進行通信。只要USB設備不被移除、復位或者重新啟動,那么這個地址將一直存在;
(7)USB主機獲取配置描述符,及其從屬的接口和端點描述符。如果還有字符串描述符,則繼續獲取。對于HID類設備,USB主機還會獲取報告描述符;
(8)獲取以上USB設備的相關信息后,USB主機會為USB設備分配并加載一個合適的設備驅動程序;
(9)USB主機對USB設備進行配置,USB設備進入配置狀態。對于HID類設備,則初始化一個上行傳輸IN端點和一個下行傳輸OUT端點,上行傳輸是USB設備向PC上傳數據,下行傳輸是PC向USB設備發送數據[4]。
枚舉完成后,USB設備可以和USB主機進行數據傳輸。枚舉和枚舉完成后的數據傳輸過程中執行一次事務處理就會產生一次中斷。USB中斷包括復位中斷、令牌中斷、STALL中斷和SOF中斷等,其中令牌中斷包括SETUP令牌中斷、IN令牌中斷和OUT令牌中斷。一次事務處理由令牌包、數據包和握手包組成,令牌包表明此次事務處理的目的,數據包中包含了要傳輸的數據,握手包表明此次事務處理的完成狀態[5]。圖1是USB設備枚舉和數據收發的執行流程圖。
2 USB驅動構件設計
驅動構件的設計應滿足可復用性、可移植性和可維護性,其中復用性是設計目標,是軟件成熟的標志。軟件的復用可以降低軟件開發的難度、減少重復勞動、降低開發成本、提高開發效率和軟件質量、縮短軟件開發周期[6]。驅動構件由.c源文件和.h頭文件組成。源文件是構件的功能函數實現,函數分為對外接口函數和內部函數,對外接口函數供外部調用,內部函數僅內部調用;頭文件是構件的功能描述,其中包含了對外接口函數聲明、相關宏定義和類型定義等。在實際使用時,構件應滿足兩點:無需打開源文件,只要通過讀頭文件就知道如何使用;在不同芯片上使用時,只需要做少量修改或者無需修改。
K64要作為USB設備使用,必須初始化USB模塊。上電后需要完成設備枚舉,設備枚舉過程需要做很多處理,但是所有USB設備的枚舉過程基本上是一樣的,因此設備枚舉可以作為一個函數進行集中處理。USB總線是輪詢式的,所有的通信都是由USB主機發起的,因此設備不能主動向USB主機發送數據,只能將要發給USB主機的數據準備好等待USB主機來取。為了方便向USB主機發送數據,在構件中封裝一個發送數據函數。如果有數據要發送給USB主機,則調用該函數將要發送的數據填入指定的緩沖區內即可,在下一次事務處理中由USB主機取出,使得USB設備可以“主動”發送數據。基于以上分析, USB驅動構件將封裝4個函數,分別是初始化函數usb_init、枚舉處理函數usb_enumerate、發送數據函數usb_send和接收數據函數usb_recv。
2.1 usb_init函數
初始化函數usb_init完成對USB模塊的初始化,主要包括內存分配、時鐘源使能和使能USB中斷等。每一個USB設備都有一個序列號,同VID和PID一起作為設備的標識符,當兩個VID和PID都一樣的USB設備插入到PC時,序列號可以起到進一步區分的作用。序列號實際上是一個字符串描述符,考慮其用于唯一性標識USB設備的作用,將其作為USB設備的名稱,并傳入初始化函數中,這樣開發者就能夠方便命名自己的USB設備。
2.2 usb_enumerate函數
枚舉處理函數usb_enumerate完成枚舉過程中的控制傳輸,該函數一般情況下無需改動。本驅動構件是針對HID設備的,如果要開發為其他類型的設備,在修改描述符后,只需要對該函數做少量修改即可。以MSD設備為例,將HID設備的描述符文件usb_hid_device_descriptor.c替換為MSD設備的描述符文件usb_msd_device_descriptor.c。比較這兩個描述符文件,發現前者比后者多一個報告描述符,同時字符串描述符也不同。為了盡量減少對usb_enumerate函數代碼的修改,可以將MSD設備的設備描述符、配置描述符及其從屬的接口和端點描述符的名稱根據HID設備作對應修改。這樣,只需要刪除usb_enumerate函數中對報告描述符的處理即可。
2.3 usb_send和usb_recv函數
發送數據函數usb_send和接收數據函數usb_recv用于數據的收發。為了方便數據的收發,這兩個函數都有兩個參數。usb_send函數的兩個參數為SendBuff和DataLenght,usb_recv函數的兩個參數為RecvBuff和DataLength。進行數據發送時,只要將待發送數據的緩沖區地址和發送的數據長度傳入發送數據函數usb_send的SendBuff和DataLength即可,下一次事務處理結束后,相應緩沖區中的數據就會被發送出去。接收數據和發送數據的執行是一樣的,只是接收的數據已經在本次事務處理中,只要使用usb_recv函數從相應端點的BD中取出即可,RecvBuff用于存放取出的數據,DataLength是取出的數據長度。
3 上位機軟件設計
上位機軟件使用Windows提供的API函數對HID設備進行訪問,這些API函數包含在hid.dll、setupapi.dll、kernel32.dll文件中,分別起到與HID設備通信、尋找與識別設備、交換數據的作用[7],關于相關API函數的介紹可以查看MSDN。
PC與USB設備建立連接的第一步就是找到該設備,上位機軟件必須時刻能夠檢測到USB設備的插入和移除事件,因此必須在相關窗體句柄創建時將這些事件通過RegisterDeviceNotification函數進行注冊,該函數位于user32.dll文件中。
當檢測到一個新的USB設備插入或者被移除時,Windows將向應用程序發送一個WM_DEVICECHANGE消息,該消息宏定義為0x0219。然后由默認的消息處理函數WndProc進行處理,程序中對WndProc進行了重寫,以滿足尋找目標設備的要求[8]。WndProc函數首先獲取USB總線上指定類型的設備列表,通過調用setupapi.dll文件中函數SetupDiGetClassDevs實現。SetupDiGetClassDevs函數的第一個參數是HID GUID,GUID是設備類型的唯一標識符,HID類設備的GUID可以通過hid.dll文件中的HidD_GetHidGuid函數獲取,為固定值4d1e55b2-f16f-11cf-88cb-001111000030。該函數的返回值是當前USB總線上所有HID類設備的信息,并保存于InfoSet隊列中。為了從InfoSet隊列中找到目標設備,需要調用setupapi.dll 文件中的SetupDiEnumDeviceInterfaces函數遍歷InfoSet隊列,并將每個設備的信息保存于DeviceInterfaceData 結構體變量oInterface中。接著,從oInterface中獲取該設備的VID和PID,然后和目標設備的VID和PID進行匹配檢查,以確定該設備是否為目標設備[9]。如果匹配則找到了目標設備,否則繼續調用SetupDiEnumDeviceInterfaces函數,獲取下一個設備的信息并繼續進行匹配檢查,直到找到目標設備或者InfoSet隊列中的設備都查找完畢為止。
如果沒有找到目標設備,則回收InfoSet占用的內存。如果目標設備找到,則使用該設備路徑作為參數并調用CreateFile函數打開該設備,之后就可以像讀寫文件一樣操作該設備。圖2是上位機軟件尋找USB設備和執行數據傳輸的流程圖。
4 構件測試與分析
圖3為數據和局部波形圖,圖3(a)是獲取設備描述符時使用TravelBus協議分析儀采集的數據,圖3(b)是對應的局部波形。枚舉過程中USB主機首先獲取USB設備的設備描述符。USB主機向USB設備發送一個SETUP令牌包,然后是DATA0數據包,該數據包中包含了8個字節的十六進制數據80 06 00 01 00 00 40 00,該8個字節的數據是獲取設備描述符的標準設備請求。USB設備接收到該請求后開始處理并向USB主機返回一個ACK握手包,表明此次SETUP事務處理是成功的,從而完成控制傳輸的設置階段。隨后USB主機發送IN令牌包開始取設備描述符,但是USB設備此時并沒有將設備描述符準備好,因此USB設備直接向USB主機發送一個NACK不確認包。
USB主機繼續發送獲取設備描述符的IN令牌包,USB設備返回準備好的18個字節的設備描述符12 01 00 02 00 00 00 40 A2 15 7F 00 01 01 01 02 00 01,其中PID是0x15A2(第9和第10字節),VID是0x007F(第11和第12字節)。之后,USB主機向USB設備發送一個ACK確認包,完成控制傳輸的數據階段。最后,USB主機發送一個OUT令牌包,再發送一個無數據的DATA1數據包,USB設備接收到之后返回一個ACK握手包,從而完成此次控制傳輸的狀態階段[10]。設備枚舉成功后,PC將USB設備掛載到設備列表中。
5 應用
目前使用DLP技術的3D打印機需要與PC進行通信,通信的實時性和穩定性至關重要。將該USB通信系統應用于3D打印中,可以提高打印的穩定性和實時性。打印過程中數據丟包率低、實時性高,使得所打印的產品紋理的連續性高(無斷層)、效果逼真。打印成品與局部紋理放大20 000倍效果如圖4所示。
6 結論
本文在深入分析USB協議的基礎上,按照構件化設計思想編寫USB驅動構件,同時以恩智浦半導體公司的K64作為測試對象,并編寫上位機軟件,實現與PC之間的USB通信。另外,將該USB通信系統用于實際項目3D打印中,打印的產品滿足要求。本文所設計的USB驅動構件封裝簡單合理、設備枚舉清晰、代碼移植性高、通信穩定高效,可以作為驅動程序的開發模板,同時對USB驅動程序開發的規范性和可移植性具有很高的參考意義。
參考文獻
[1] 龍飛,何欽銘.構件化開發方法在J2EE 項目中的應用[J].計算機工程與設計,2007,28(3):591-594.
[2] 黃櫻,劉君,劉卉,等.基于ARM的嵌入式USB主機系統設計[J].微計算機信息(嵌入式與SOC),2007,22(2):156-157.
[3] ZHU J,WANG S,ZHANG S Y,et al.Embedded diver system for USB mouse[C].International Conference on Electrical & Control Engineering,2011:180-183.
[4] 侯代文,孫濤,鄧磊明.TMS320VC33與主機通信的USB接口設計[J].電子設計工程,2015,23(7):166-170.
[5] 王宜懷,吳璟,蔣銀珍.嵌入式系統原理與實踐—ARM Cortex-M4 Kinetis微控制器[M].北京:電子工業出版社,2012.
[6] 呂明琪,薛錦云,胡啟敏.基于軟件體系結構的可復用構件模型[J].計算機應用研究,2008,25(1):120-122.
[7] 楊晶晶,江春華.USB HID設備驅動程序設計[J].微計算機信息(嵌入式與SOC),2006,22(6):140-142.
[8] 郭夏夏.動平衡測試系統的關鍵技術研究[D].上海:上海交通大學,2014.
[9] WATANABE H,MASAOKA H,OHIGASHI T,et al.Supporting USB devices for the global migration[J].IPSJ International Symposium on Applications & the Internet,2010:153-156.
[10] DONG Z Y,ZHAO H.Data transfer principles and implementation in USB microwave power sensor[C].Seventh International Symposium on Computational Intelligence & Design,2014:76-79.
作者信息:
胡唯唯1,王宜懷1,張 永2
(1.蘇州大學 計算機科學與技術學院,江蘇 蘇州215006;2.蘇州華祥信息科技有限公司,江蘇 蘇州215006)