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