基于Linux2.6的USB設備的驅(qū)動實現(xiàn)
摘要: 嵌入式linux系統(tǒng)環(huán)境以其易于移植裁減,、內(nèi)核小、效率高,、完整,、原代碼開放及性能優(yōu)異等特點,,在嵌入式領域得到了非常廣泛的應用,。Linux的USB設備端的源代碼中主要有USB device的海量存儲設備、串口設備,、網(wǎng)絡設備等設備驅(qū)動程序及各種USB device控制器芯片的驅(qū)動程序,。市場上USB設備控制器芯片種類繁多,大多數(shù)用戶需要針對特定應用來開發(fā)相關的USB設備控制器驅(qū)動程序,,才能使設備正常工作在linux操作系統(tǒng)下,。
Abstract:
Key words :
嵌入式linux系統(tǒng)環(huán)境以其易于移植裁減、內(nèi)核小,、效率高,、完整、原代碼開放及性能優(yōu)異等特點,,在嵌入式領域得到了非常廣泛的應用,。Linux的USB設備端的源代碼中主要有USB device的海量存儲設備、串口設備,、網(wǎng)絡設備等設備驅(qū)動程序及各種USB device控制器芯片的驅(qū)動程序,。市場上USB設備控制器芯片種類繁多,大多數(shù)用戶需要針對特定應用來開發(fā)相關的USB設備控制器驅(qū)動程序,,才能使設備正常工作在linux操作系統(tǒng)下,。
1 USB設備端驅(qū)動系統(tǒng)
Linux Gadget子系統(tǒng)主要分為三層:第一層為芯片驅(qū)動層,負責將各種USB device控制器抽象為統(tǒng)一的函數(shù)接口,,以供上層驅(qū)動程序調(diào)用,;第二層主要是對操作函數(shù)的簡單封裝;第三層為設備驅(qū)動層,,可根據(jù)系統(tǒng)的需求實現(xiàn)所對應的功能。圖1所示是Linux Gadget子系統(tǒng)的驅(qū)動層次,。Linux Gadget子系統(tǒng)的設備驅(qū)動層主要根據(jù)各個類別的規(guī)范及協(xié)議實現(xiàn)各種設備的驅(qū)動,,本設計需要使一個嵌入式設備擁有移動硬盤的功能,所以,,可以根據(jù)海量存儲類的規(guī)范及協(xié)議來實現(xiàn)該功能,。
1.1 UDC驅(qū)動的基本構架
圖2所示是UDC驅(qū)動的基本構架圖。在控制器驅(qū)動程序中,,首先應注冊platform驅(qū)動,,調(diào)用其probe函數(shù)搜索設備,并在probe函數(shù)內(nèi)初始化usb_ep和usb_gadget等結構,,然后注冊設備,,并申請中斷,接著等待中斷進入中斷服務子程序,,最后聲明和實現(xiàn)usb_gadget_register_driver注冊函數(shù)并輸出給上層驅(qū)動,。在該過程中,,聯(lián)系它們的紐帶是一些全局結構體變量。
1.2 Gadget API
Gadget API為Gadget系統(tǒng)定義了統(tǒng)一的數(shù)據(jù)結構和接口函數(shù),,它和主機端的USB Core地位類似,,但功能僅限于提供編程接口,如用結構體usb_gadget_ops和usb_ep_ops對設備控制器驅(qū)動操作函數(shù)和端點操作函數(shù)進行重新封裝,。比較特殊的是Gadget驅(qū)動程序注冊函數(shù)usb_gadget_register_driver,,它們是由設備控制器(UDC)驅(qū)動直接提供的,用于將UDC綁定到gadget driver,。這增加了Gadget Driver和UDC之間的依賴性,。
在設備端,Gadget系統(tǒng)雖然類似主機驅(qū)動系統(tǒng)分了三層結構,,但Gadget API只定義了一些數(shù)據(jù)結構、宏和功能函數(shù),,并對UDC驅(qū)動程序進行了簡單包裝,,而沒有驅(qū)動管理等功能。
1.3設備應用驅(qū)動程序
設備端應用程序(Gadget Driver)用于控制USB設備功能的實現(xiàn),,使設備表現(xiàn)出“網(wǎng)絡連接”,、“打印機”或“大容量存儲設備”等特性。本文以大容量移動存儲設備為例來實現(xiàn)移動硬盤的功能,。
BULK ONLY傳輸指的是主機和大容量存儲設備之間的一種數(shù)據(jù)傳輸方式,。
2設備端驅(qū)動調(diào)度
在嵌入式Linux操作系統(tǒng)中,Gadget driver和Gadget API可完成部分USB協(xié)議處理,、BULK ONLY等傳輸協(xié)議以及指令的解析處理,,用戶只需要在設備控制器驅(qū)動程序中完成部分USB協(xié)議處理和Gadget API的銜接工作。
圖3所示的流程圖給出了USB設備端驅(qū)動程序的基本調(diào)度思想,。該方案的主要思路是被動的接受主機端的傳輸命令(任何類型的通信都由USB主機發(fā)起,,USB設備間不能直接通信),然后通過中斷觸發(fā)的方式完成主機端的數(shù)據(jù)傳輸,。當產(chǎn)生設備端中斷時,,設備控制器驅(qū)動程序首先判斷中斷類型。當其為批量傳輸端點IN中斷時,,驅(qū)動程序會將該EP下鏈接的REQ中的數(shù)據(jù)依次寫入USB2.0 OTG IP的設備控制器的內(nèi)存區(qū),;當其為批量傳輸OUT中斷時,驅(qū)動程序會將設備控制器內(nèi)存區(qū)的數(shù)據(jù)讀入REQ中的buffer中,;當其為端點0的控制傳輸中斷時,,驅(qū)動程序?qū)⒆x取端點緩沖區(qū)的數(shù)據(jù),并解析當前的設備請求,。如果主機傳輸給設備的設備請求為USB REO SEDRESS(設置設備地址),、USB_REQ_GET_STATUS(獲取設備狀態(tài)),、USB_REQ_SET_FEATURE(設置設備特性),設備控制器驅(qū)動程序會自行響應請求,。但是,,如果是其它設備請求,如GET_DESCRIPTOR(獲取設備描述符)時,,設備控制器驅(qū)動便會將該請求提交給Gadget Driver,,然后由Gadget Driver排隊將該設備請求提交給端點,以等待下次控制端點中斷,。
控制傳輸比較復雜,,它需要完成建立階段、數(shù)據(jù)傳輸階段和狀態(tài)階段,。整個控制端點中斷的處理可通過四個狀態(tài)實現(xiàn),,分別是:端點0空閑(EP0_IDLE)、 數(shù)據(jù)IN傳輸(EP0 IN DATA_PHASE),、數(shù)據(jù)OUT傳輸(EP0 OUT DATA_PHASE)和狀態(tài)階段(EPO_STATUS),。
EP0_IDLE狀態(tài)主要處理建立階段的setup令牌,并根據(jù)獲得的設備請求處理能夠處理的設備請求,,同時把不能處理的設備請求(如獲取設備描述符,,配置描述符等)提交給上層Gadget Driver;EP0_OUT_DATA_PHASE狀態(tài)主要處理數(shù)據(jù)階段的OUT傳輸,;EP0_OUT_DATA_PHASE狀態(tài)主要處理數(shù)據(jù)階段的IN傳輸,;EP0_STATUS狀態(tài)則主要完成控制傳輸過程中的狀態(tài)階段。
在圖3所示的流程圖中,,EP0為控制傳輸端點,,EP1、EP2,、EP3為批量傳輸端點,,它們主要包括端點傳輸類型、端點緩沖區(qū)大小等信息,。REQ為Gadget Driver提交的端點請求,,主要包含傳輸?shù)臄?shù)據(jù)長度和地址。
3 UDC的設計與實現(xiàn)
設備控制器驅(qū)動主要分為Gadget Driver接口模塊,、Gadget API函數(shù)模塊,、中斷處理模塊、數(shù)據(jù)結構定義,、初始化模塊,、硬件讀寫模塊等,各模塊可以單獨進行設計,。
3.1 數(shù)據(jù)結構定義
根據(jù)Gadget API提供的數(shù)據(jù)結構,,可以定義自己的數(shù)據(jù)結構(如設備數(shù)據(jù)結構otg_udc,,端點數(shù)據(jù)結構otg_udc_ep等)來描述該USB設備控制器。
定義完特定的設備控制器驅(qū)動的數(shù)據(jù)結構后,,再進行相應的映射(static struct otg_ip_udcmemory),,以便將具體的設備控制器、設備端點和Gadget的抽象數(shù)據(jù)結構聯(lián)系起來,。
3.2 Gadget Driver接口模塊
UDC驅(qū)動提供有usb_gadget_driver_register模塊,,該模塊可實usb_gadget_register_driver等綁定函數(shù)的功能,以綁定UDC和Gadget Driver,。
3.3 Gadget API函數(shù)模塊
Linux USB gadget driver API定義了一個通用的gadget driver的接口,,利用gadget driver可通過API與底層USB controller driver進行通信。該API屏蔽了底層硬件的不同,,故可使gadget driver只注重功能的實現(xiàn),,而盡量與硬件無關。其代碼如下:
該模塊主要實現(xiàn)Gadget API定義的函數(shù)功能,,如結構體usb_ep_ops和usb_gadget_ops中的函數(shù),,以及usb_gadget_register_driver注冊函數(shù)等。這些函數(shù)可供Gadget Driver調(diào)用,。
3.4 中斷處理模塊
由于設備是被動的接受主機的控制,設備的所有行為都是基于設備中斷的觸發(fā),,因此,,函數(shù)主要處理Reset中斷、Resume中斷,、Suspend中斷,、EP0中斷以及其他端口中斷。
3.5 初始化模塊
初始化主要是打開中斷,、打開并設置端點,、設置最大總線轉(zhuǎn)向時間(此時問即包間最大等待時間),還要設置最大緩沖區(qū)長度等,。
3.6 硬件讀寫模塊
和主機控制器驅(qū)動程序類似,,設備控制器的讀寫方式分為PIO讀寫和DMA讀寫兩種模式,讀寫內(nèi)容也分為寄存器讀寫和端點緩沖區(qū)讀寫,。在讀寫過程中,,所有讀寫地址都必須是雙字節(jié)對齊模式。
4 驅(qū)動測試結果
本文研究的HCD已經(jīng)應用于實際的工程中,,驅(qū)動測試的硬件環(huán)境如圖4所示,。
本系統(tǒng)的硬件平臺是Realview EB,這是一個高度集成的開發(fā)板,,其母板上的硬件資源包括:一個FPGA (Xilinx Virtex-II XC2V6000),、靜態(tài)和動態(tài)內(nèi)存,、集成外圍設備和兩個用于Core Tiles連接的tile連接器。設計時可通過增加一個額外的Core Tile(ARM926EJS CORE)來創(chuàng)建一個微處理系統(tǒng),。Logic Tile(Xilinx XC2V6000)中包含有一塊具有主機控制器功能的芯片otg_ip,,otg_ip可通過片內(nèi)總線AHB掛載在母板EB上。在該開發(fā)板上運行Linux系統(tǒng)時,,可通過交叉編譯調(diào)試環(huán)境將開發(fā)報與一臺PC機相連,,這樣,調(diào)試信息就可以通過串口打印在該主機的終端上,。otg_ip可通過ULPI接口連接PHY芯片,,并與USB設備相連。
設備控制器驅(qū)動模塊otg_ip_udc.ko和g_filestorage.ko成功加載后,,再將其作為移動優(yōu)盤插入電腦主機的USB接口,,驅(qū)動即可成功識別。圖5所示是內(nèi)核打印的信息結果,。
USB通用串行總線具有傳輸速率高,、功耗低、可熱插拔和發(fā)展快速等優(yōu)點,,而Linus操作系統(tǒng)則具有易于移植和裁減,、內(nèi)核小、效率高,、原代碼開放等特點,,本文通過將其結合而給出的Linux環(huán)境下的USB設備驅(qū)動方法,可以快速地實現(xiàn)大容量的存儲功能,,實驗表明:該系統(tǒng)的數(shù)據(jù)讀寫速度可以達到681 kB/s,,而且效果良好。
此內(nèi)容為AET網(wǎng)站原創(chuàng),,未經(jīng)授權禁止轉(zhuǎn)載,。