新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 嵌入式Linux下的USB設(shè)備驅(qū)動(dòng)技術(shù)

嵌入式Linux下的USB設(shè)備驅(qū)動(dòng)技術(shù)

作者: 時(shí)間:2010-05-19 來源:網(wǎng)絡(luò) 收藏

以其穩(wěn)定、高效、易定制、硬件支持廣泛、源代碼開放等特點(diǎn),已在領(lǐng)域迅速崛起,被國際上許多大型的跨國企業(yè)用作產(chǎn)品的系統(tǒng)平臺(tái)。

是Universal Serial Bus (通用串行總線)的縮寫,是1995年由Microsoft、Compaq、IBM等公司聯(lián)合制定的一種新的PC串行通信協(xié)議。它是一種快速、靈活的總線接口。與其它通信接口相比較,接口的最大特點(diǎn)是易于使用,這也是的主要設(shè)計(jì)目標(biāo)。USB的成功得益于在USB標(biāo)準(zhǔn)中除定義了通信的物理層和電器層標(biāo)準(zhǔn)外。還定義了一套相對(duì)完整的軟件協(xié)議堆棧。這使得多數(shù)USB設(shè)備都很容易在各種平臺(tái)上工作。作為一種高速總線接口,USB適用于多種設(shè)備(如數(shù)碼相機(jī)、MP3播放器、高速數(shù)據(jù)采集設(shè)備等)。另外,USB接口還支持熱插拔,而且所有的配置過程都由系統(tǒng)自動(dòng)完成,無須用戶干預(yù)。

1 下的USB

內(nèi)核的不斷升級(jí)過程中,驅(qū)動(dòng)程序的結(jié)構(gòu)相對(duì)穩(wěn)定。由于USB設(shè)備也是外圍設(shè)備的一種,因此,它的驅(qū)動(dòng)程序結(jié)構(gòu)與普通設(shè)備的驅(qū)動(dòng)程序相同。Linux系統(tǒng)的設(shè)備分為字符設(shè)備(CharDevice)和塊設(shè)備(BlockDevice)。字符設(shè)備支持面向塊字符的I/O操作,它不通過系統(tǒng)的快速緩存,而只支持順序存取。塊設(shè)備則支持面向塊的I/O操作,所有塊設(shè)備的I/O操作都通過在內(nèi)核地址空間的I/O緩沖區(qū)進(jìn)行,可以支持幾乎任意長度和任意位置上的I/O請(qǐng)求。塊設(shè)備與字符設(shè)備還有一點(diǎn)不同,就是塊設(shè)備必須能夠隨機(jī)存取(RandomAccess),字符設(shè)備則沒有這個(gè)要求。典型的字符設(shè)備包括鼠標(biāo)、鍵盤、串行口等,而塊設(shè)備主要包括硬盤軟盤設(shè)備、CD-Rom等。由于USB設(shè)備主要都是通過快速串行通訊來讀寫數(shù)據(jù),因此一般都可作為字符設(shè)備來進(jìn)行處理。

2 Linux下的USB core

2.1 Linux中USB core與USB的結(jié)構(gòu)關(guān)系

Linux操作系統(tǒng)中有一個(gè)叫做“USB core”的子系統(tǒng),可提供支持USB程序的API和USB主機(jī)控制器的驅(qū)動(dòng)程序。同時(shí)提供有許多數(shù)據(jù)結(jié)構(gòu)、宏定義和功能函數(shù)來對(duì)硬件或設(shè)備進(jìn)行支持。在Linux下編寫USB設(shè)備的驅(qū)動(dòng)程序時(shí),從嚴(yán)格意義上講,就是使用這些USB core的子系統(tǒng)所定義的數(shù)據(jù)結(jié)構(gòu)、宏和函數(shù)來編寫數(shù)據(jù)的處理功能。在Linux下,core、host controller和driver三者之間的關(guān)系如圖1所示。



2.2 USB core的初始化

USB core從USB子系統(tǒng)的初始化開始。USB子系統(tǒng)的初始化則在文件drivers/usb/core/usb.c里。其代碼如下:

subsys_initcall(usb_init);
module_exit(usb_exit);

代碼中的subsys_initcall是一個(gè)宏,相當(dāng)于module_init,只不過因?yàn)檫@部分代碼是核心,開發(fā)者通常把它看作一個(gè)子系統(tǒng),而不僅僅是一個(gè)模塊。因?yàn)閁SB core模塊代表的不是某一個(gè)設(shè)備,而是所有USB設(shè)備賴以生存的模塊。因此,在Linux中,像這樣把一個(gè)類別的歸結(jié)為一個(gè)子系統(tǒng)(比如PCI子系統(tǒng)、scsi子系統(tǒng)等)。基本上,drivers/目錄下面第一層的每個(gè)目錄都可算作一個(gè)子系統(tǒng),因?yàn)樗鼈兇砹艘活愒O(shè)備。一般地,usb_init是真正的初始化函數(shù),而usb_exit()則是整個(gè)USB子系統(tǒng)結(jié)束時(shí)的清理函數(shù):



函數(shù)usb_init主要完成初始化和注冊(cè)設(shè)備。

2.3 USB里的設(shè)備模型

Linux里一個(gè)很重要的概念是設(shè)備模型。對(duì)于驅(qū)動(dòng)來說,設(shè)備的概念就是總線和與其相連的各種設(shè)備。在內(nèi)核里,總線、設(shè)備、驅(qū)動(dòng)也就是bus、device、driver是設(shè)備模型很重要的三個(gè)概念,它們都有自己專屬的結(jié)構(gòu)。在include/linux/devide.h里的定義為:

struct bus_type {……};
struct device {……);
struct device_driver {……};

每次出現(xiàn)一個(gè)設(shè)備都要向總線注冊(cè),每次出現(xiàn)一個(gè)驅(qū)動(dòng),也要向總線注冊(cè)。系統(tǒng)初始化時(shí),應(yīng)掃描連接許多設(shè)備,并為每一個(gè)設(shè)備建立一個(gè)struct device的變量。每一次都應(yīng)有一個(gè)驅(qū)動(dòng)程序,并要準(zhǔn)備一個(gè)struct device_driver結(jié)構(gòu)的變量。還要把這些變量加入相應(yīng)的鏈表(如把device插入devices鏈表,driver插入drivers鏈表)。這樣,通過總線就能找到每一個(gè)設(shè)備和每一個(gè)驅(qū)動(dòng)。然而,假如計(jì)算機(jī)里只有設(shè)備卻沒有對(duì)應(yīng)的驅(qū)動(dòng),那么設(shè)備將無法工作。反過來,倘若只有驅(qū)動(dòng)卻沒有設(shè)備,驅(qū)動(dòng)也起不了任何作用。對(duì)于USB設(shè)備,它可以在計(jì)算機(jī)啟動(dòng)以后再插入或者拔出計(jì)算機(jī)。由于device可以在任何時(shí)刻出現(xiàn),而driver也可以在任何時(shí)刻被加載,所以,每當(dāng)一個(gè)struct device誕生時(shí),它就會(huì)去BUS的drivers鏈表中尋找自己的另一半。如果找到了匹配的設(shè)備,就調(diào)用device_bind_driver,并綁定好。

Linux設(shè)備模型中的總線落實(shí)在USB子系統(tǒng)里就是usb_bus_type,它在usb_init函數(shù)中可用retval=bus_register(usb_bus_type)語句注冊(cè),而在driver.c文件里的定義如下:

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

上一頁 1 2 下一頁

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉