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