朱恩亮,趙臘才,茹 偉,胡宇凡
(中航工業(yè)西安航空計(jì)算技術(shù)研究所 民用機(jī)載電子設(shè)備研究室,陜西 西安 710068)
Linux環(huán)境下USB設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)
朱恩亮,趙臘才,茹偉,胡宇凡
(中航工業(yè)西安航空計(jì)算技術(shù)研究所 民用機(jī)載電子設(shè)備研究室,陜西 西安710068)
摘要在介紹Linux設(shè)備驅(qū)動(dòng)程序、USB邏輯組織的基礎(chǔ)上,針對(duì)某數(shù)據(jù)采集系統(tǒng)與PC機(jī)之間的USB通信實(shí)時(shí)性要求高、數(shù)據(jù)帶寬高的特點(diǎn),采用URB并結(jié)合DMA的方法,開(kāi)展Linux環(huán)境下USB設(shè)備驅(qū)動(dòng)程序的設(shè)計(jì)。通過(guò)讀取大容量數(shù)據(jù)對(duì)驅(qū)動(dòng)程序進(jìn)行測(cè)試,單個(gè)USB端點(diǎn)數(shù)據(jù)讀取速度可達(dá)30 MB/s,能滿足系統(tǒng)需求。
關(guān)鍵詞Linux;字符設(shè)備驅(qū)動(dòng);USB邏輯組織;USB設(shè)備驅(qū)動(dòng)
Development of USB Device Drivers of Linux
ZHU Enliang,ZHAO Lacai,RU Wei,HU Yufan
(Civilian Vehicle-borne Electronic Devices Research Section,AVIC Xi’an Aeronautic Computing
Technique Research Institute,Xi’an 710068,China)
AbstractLinux platform is widely used now while the requirements of device driver based on this platform are needed by more and more developers.A URB combining with DMA development method for the real-time and high bandwidth USB communication between a data collection system and a PC is provided after a brief introduction to Linux device drivers and USB logical organization.The system requirements can be satisfied by this development method after large capacity data reading test of the driver.The reading speed of a single USB endpoint reaches 30 MB/s.
KeywordsLinux;character device driver;USB logical organization;USB device driver
Linux平臺(tái)上的設(shè)備驅(qū)動(dòng)程序采用模塊化設(shè)計(jì)方式,使得硬件設(shè)備能響應(yīng)各個(gè)內(nèi)部編程接口[1-2]。這些編程接口使得設(shè)備對(duì)用戶而言將變得透明,用戶無(wú)需關(guān)注設(shè)備的工作細(xì)節(jié),其只需通過(guò)系統(tǒng)調(diào)用接口即可訪問(wèn)硬件設(shè)備。在Linux平臺(tái)下,將系統(tǒng)調(diào)用與設(shè)備具體操作相關(guān)聯(lián)的組件即為驅(qū)動(dòng)程序[3]。
某數(shù)據(jù)采集系統(tǒng)與計(jì)算機(jī)(PC)之間的USB通信邏輯架構(gòu)如圖1所示,PC通過(guò)USB接口實(shí)時(shí)獲取數(shù)據(jù)采集系統(tǒng)所采集的多路圖像數(shù)據(jù),并存儲(chǔ)在網(wǎng)絡(luò)服務(wù)器硬盤(pán)上。系統(tǒng)要求該采集系統(tǒng)與PC之間數(shù)據(jù)傳輸速率不低于20 MB/s。一般USB設(shè)備驅(qū)動(dòng)主要用于解決對(duì)設(shè)備存儲(chǔ)區(qū)的訪問(wèn)、對(duì)設(shè)備進(jìn)行簡(jiǎn)單的控制,對(duì)數(shù)據(jù)傳輸?shù)膶?shí)時(shí)性和帶寬要求不高,本文的目的是解決Linux環(huán)境下USB設(shè)備實(shí)時(shí)、高速數(shù)據(jù)傳輸問(wèn)題[4]。
圖1 數(shù)據(jù)采集系統(tǒng)與PC之間的USB通信邏輯架構(gòu)
1字符設(shè)備驅(qū)動(dòng)
Linux操作系統(tǒng)將外部設(shè)備分為3種基本類型[5]:分別為字符設(shè)備,塊設(shè)備和網(wǎng)絡(luò)設(shè)備。本文所討論的USB設(shè)備本身為簡(jiǎn)單設(shè)備,可歸屬為字符設(shè)備,關(guān)于字符設(shè)備驅(qū)動(dòng)程序的結(jié)構(gòu)如圖2所示。當(dāng)驅(qū)動(dòng)通過(guò)Insmod加載后,應(yīng)用程序即可使用標(biāo)準(zhǔn)的系統(tǒng)調(diào)用接口實(shí)現(xiàn)對(duì)字符設(shè)備的操作。同時(shí),應(yīng)用程序還可使用C庫(kù)函數(shù)進(jìn)行編程;出于代碼可移植性的考慮,本文建議使用C庫(kù)函數(shù)方式。
圖2 Linux下字符設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)
2USB設(shè)備的邏輯組織
USB設(shè)備復(fù)雜,由眾多不同的邏輯單元構(gòu)成,具體如圖3所示[6]。
圖3 USB設(shè)備邏輯組織
一個(gè)USB設(shè)備可包含一個(gè)或多個(gè)配置信息,而不同的配置則使USB設(shè)備具有不同的功能[7];配置亦由各接口所組成,一個(gè)配置中所包含的接口可同時(shí)有效,并可被不同的驅(qū)動(dòng)程序所連接;同樣,接口亦由每個(gè)端點(diǎn)所組成,并代表著該USB設(shè)備對(duì)應(yīng)的每個(gè)基本功能,是USB設(shè)備驅(qū)動(dòng)程序所要控制的對(duì)象;端點(diǎn)中則包含有該端點(diǎn)所屬類型、地址、數(shù)據(jù)傳輸方向(相對(duì)USB Host是輸入或輸出)、數(shù)據(jù)傳輸方式(同步、中斷、批量、控制)、數(shù)據(jù)包最大長(zhǎng)度、輪詢數(shù)據(jù)傳輸端點(diǎn)的時(shí)間間隔等USB通信時(shí)必須用到的信息。
3USB設(shè)備驅(qū)動(dòng)
在Linux內(nèi)核中,USB設(shè)備的驅(qū)動(dòng)將通過(guò)結(jié)構(gòu)體usb_driver來(lái)進(jìn)行描述。usb_driver中則包含著上文所述的所有描述符。對(duì)USB設(shè)備的注冊(cè)和注銷通過(guò)調(diào)用usb_register與usb_deregister兩個(gè)函數(shù)完成[8-9]。
int usb_register(struct usb_driver *new driver);//在module_init的usb_skel_init函數(shù)中完成
void usb_deregister(struct usb_driver *driver);//在module_exit的usb_skel_exit函數(shù)中完成
結(jié)構(gòu)體usb_driver中含有USB設(shè)備ID映射表,并定義了探測(cè)函數(shù)probe()和斷開(kāi)函數(shù)disconnect()。在USB設(shè)備驅(qū)動(dòng)設(shè)計(jì)時(shí),probe()和disconnect()將分別在USB設(shè)備被插入和移除時(shí)被自動(dòng)調(diào)用。
當(dāng)USB設(shè)備被插入U(xiǎn)SB主機(jī),且該USB設(shè)備被USB主機(jī)識(shí)別(即該USB設(shè)備與上文已注冊(cè)的USB設(shè)備相匹配)時(shí),則探測(cè)函數(shù)將自動(dòng)被調(diào)用;探測(cè)函數(shù)主要任務(wù)是分配資源,對(duì)USB設(shè)備進(jìn)行初始化,獲得USB設(shè)備的接口和端點(diǎn)信息,注冊(cè)該USB設(shè)備本身所屬設(shè)備。
本文所描述的USB設(shè)備為簡(jiǎn)單字符設(shè)備,在設(shè)計(jì)過(guò)程中將通過(guò)usb_register_dev(interface,&skel_class)函數(shù)來(lái)完成該USB設(shè)備驅(qū)動(dòng)程序的注冊(cè)。其中,interface為USB設(shè)備的接口描述符,skel_class中包含著設(shè)備名稱和將系統(tǒng)調(diào)用與該驅(qū)動(dòng)程序關(guān)聯(lián)起來(lái)的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)file_operations;而結(jié)構(gòu)體file_operations中則包含著skel_open、skel_read()、skel_ioctl()等函數(shù),這些函數(shù)的實(shí)現(xiàn)將是該USB設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)的關(guān)鍵部分,并且會(huì)在應(yīng)用程序進(jìn)行open()、read()、ioctl()等系統(tǒng)調(diào)用時(shí)被最終調(diào)用。
skel_read()主要用于將USB設(shè)備的數(shù)據(jù)搬移到Linux系統(tǒng)內(nèi)核中,然后再將這些數(shù)據(jù)傳遞給用戶。在該過(guò)程中,URB(USB Request Block,USB請(qǐng)求塊)發(fā)揮著重要作用。USB設(shè)備數(shù)據(jù)傳輸時(shí),在一個(gè)USB端點(diǎn)所對(duì)應(yīng)的URB隊(duì)列被清空前,一個(gè)典型的URB處理過(guò)程如圖4所示。
圖4 URB處理流程
基于URB的USB讀取數(shù)據(jù)(skel_read())關(guān)鍵代碼如下[10]
skel_read(struct file *file,char *userbuf,size_t num,loff_t *ppos)
{
Dmabuf=usb_buffer_alloc(dev→udev,num,GFP_KERNEL,& urb→transfer_dma);//創(chuàng)建DMA緩沖區(qū)以提高USB數(shù)據(jù)傳輸速度
usb_submit_urb(urb,GFP_KERNEL);//提交urb
copy_to_user(userbuf,Dmabuf,num);//將內(nèi)核空間數(shù)據(jù)拷貝到用戶空間
}
結(jié)構(gòu)體file_operations中定義的其它成員函數(shù)的實(shí)現(xiàn)與skel_read()相類似。
當(dāng)USB設(shè)備被移除或USB驅(qū)動(dòng)程序無(wú)法繼續(xù)控制該USB設(shè)備時(shí),斷開(kāi)函數(shù)將自動(dòng)被調(diào)用;斷開(kāi)函數(shù)主要用于釋放已經(jīng)申請(qǐng)的資源,注銷該USB設(shè)備本身所屬設(shè)備。本文所描述的USB設(shè)備為簡(jiǎn)單字符設(shè)備,在設(shè)計(jì)過(guò)程中將通過(guò)調(diào)用usb_deregister_dev()函數(shù)來(lái)完成該USB設(shè)備驅(qū)動(dòng)程序的注銷。
在使用USB時(shí),若用戶需要對(duì)USB設(shè)備進(jìn)行一些簡(jiǎn)單的控制,則需要驅(qū)動(dòng)程序提供相應(yīng)的ioctl()函數(shù)。當(dāng)然,該控制功能可以通過(guò)上述URB方法實(shí)現(xiàn),但大多數(shù)情況下,USB驅(qū)動(dòng)程序僅是為了完成從USB設(shè)備接收或發(fā)送一些簡(jiǎn)單控制命令,這時(shí)則可通過(guò)usb_control_msg()來(lái)快速實(shí)現(xiàn)該功能[11]。
4測(cè)試驗(yàn)證
在完成驅(qū)動(dòng)程序的設(shè)計(jì)編碼工作后,通過(guò)make命令對(duì)該驅(qū)動(dòng)進(jìn)行編譯,并將編譯后的驅(qū)動(dòng)程序通過(guò)insmod命令加載到Linux內(nèi)核中。在Linux環(huán)境下開(kāi)發(fā)該USB驅(qū)動(dòng)的測(cè)試程序,通過(guò)在用戶輸入的時(shí)間內(nèi)連從數(shù)據(jù)采集系統(tǒng)讀取數(shù)據(jù),累計(jì)讀取的數(shù)據(jù)量,得到單位時(shí)間內(nèi)的平均數(shù)據(jù)讀取速度,具體如圖5所示。
圖5 USB驅(qū)動(dòng)程序測(cè)試
5結(jié)束語(yǔ)
本文以某數(shù)據(jù)采集系統(tǒng)與PC之間的USB高速數(shù)據(jù)通信為例,在介紹Linux環(huán)境下設(shè)備驅(qū)動(dòng)程序的基礎(chǔ)上,結(jié)合USB總線標(biāo)準(zhǔn),開(kāi)發(fā)了Linux環(huán)境下USB設(shè)備驅(qū)動(dòng)程序。通過(guò)實(shí)際測(cè)試驗(yàn)證,該驅(qū)動(dòng)程序最終實(shí)現(xiàn)的單路USB接口平均通信速率為30 MB/s,滿足了數(shù)據(jù)采集系統(tǒng)與PC機(jī)之間高速數(shù)據(jù)傳輸?shù)男枨蟆?/p>
參考文獻(xiàn)
[1]方騫,倪遠(yuǎn)平.基于Linux的最小USB驅(qū)動(dòng)程序框架設(shè)計(jì)[J].微處理機(jī),2012(3):48-50.
[2]王義華,黃道平,劉少君.基于Linux系統(tǒng)的實(shí)時(shí)USB驅(qū)動(dòng)研究[J].組合機(jī)床與自動(dòng)化加工技術(shù),2011(1):75-78.
[3]陳佐,冉再,涂員員,等.3G通訊模塊設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)技術(shù)與發(fā)展,2011(5):214-218.
[4]Cypress Semiconductor.EZ-USB FX2 technical reference manual V2.2[M].Germany:Cypress Semiconductor,2003.
[5]宋寶華.Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解[M].北京:人民郵電出版社,2008.
[6]Jonatban Corbet,Alessandro Rubini,Greg Kroab-Hartman.Linux設(shè)備驅(qū)動(dòng)程序[M].3版.魏永明,耿岳,鐘書(shū)毅,譯.北京:中國(guó)電力出版社,2012.
[7]李麗宏,郝志剛.嵌入式Linux的USB驅(qū)動(dòng)設(shè)計(jì)[J].電子設(shè)計(jì)工程,2011,19(11):170-173.
[8]張旋.基于Linux環(huán)境下USB設(shè)備驅(qū)動(dòng)移植的研究[J].計(jì)算機(jī)與現(xiàn)代化,2012(6):144-146.
[9]張義棟,孫未.Linux下USB大容量存儲(chǔ)設(shè)備驅(qū)動(dòng)分析與實(shí)現(xiàn)[J].電子世界,2013(1):9-11.
[10]黎春波,陳維峰,賴學(xué)錦.嵌入式Linux系統(tǒng)下的USB驅(qū)動(dòng)程序開(kāi)發(fā)[J].中國(guó)集成電路,2013(1):45-48.
[11]楊俊成,于德海,李艷波.嵌入Linux按建驅(qū)動(dòng)程序開(kāi)發(fā)[J].電子科技,2008,21(12):57-60.
作者簡(jiǎn)介:朱恩亮(1983—),男,碩士,工程師。研究方向:計(jì)算機(jī)應(yīng)用。
基金項(xiàng)目:航空科學(xué)基金資助項(xiàng)目(20141931001)
收稿日期:2015- 05- 20
中圖分類號(hào)TP361.85
文獻(xiàn)標(biāo)識(shí)碼A
文章編號(hào)1007-7820(2016)01-108-03
doi:10.16180/j.cnki.issn1007-7820.2016.01.029