基于Linu_的USB主、從設(shè)備之間的三種通信方式.doc_第1頁
基于Linu_的USB主、從設(shè)備之間的三種通信方式.doc_第2頁
基于Linu_的USB主、從設(shè)備之間的三種通信方式.doc_第3頁
基于Linu_的USB主、從設(shè)備之間的三種通信方式.doc_第4頁
基于Linu_的USB主、從設(shè)備之間的三種通信方式.doc_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余1頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

基于Linux的USB主/從設(shè)備之間的三種通信方式隨著簡單易用的USB接口日益流行,在嵌入式系統(tǒng)中添加對USB接口的支持已成為大勢所趨。本文通過介紹Linux中支持USB的各種模塊和庫,分析了在Linux上利用USB實(shí)現(xiàn)高速串口和以太網(wǎng)連接等通信方式的具體方法。 通用串行總線(USB,Universal Serial Bus)是一種非常實(shí)用的通信接口,其應(yīng)用日益廣泛。有三種方法可以使運(yùn)行Linux操作系統(tǒng)的嵌入式系統(tǒng)支持USB接口,本文將對這三種方法逐一進(jìn)行介紹。 基于Linux的USB設(shè)備與USB主機(jī)一般有以下三種通信方式:1一些功能最完備結(jié)構(gòu)也最復(fù)雜的設(shè)備采用用戶定制內(nèi)核模塊來實(shí)現(xiàn)在標(biāo)準(zhǔn)USB總線上運(yùn)行復(fù)雜的高級協(xié)議,而由USB主機(jī)上相應(yīng)的用戶驅(qū)動程序和應(yīng)用來完成連接。2另一些基于Linux的USB設(shè)備則利用USB總線來實(shí)現(xiàn)與主機(jī)上所運(yùn)行的某個應(yīng)用的簡單的點(diǎn)對點(diǎn)串行連接。主機(jī)上的應(yīng)用雖然利用了主操作系統(tǒng)所提供的USB編程接口,但表面看來卻似乎是在通過一個典型的串口進(jìn)行通信。3最后,還有些設(shè)備以主計算機(jī)作為網(wǎng)關(guān),將USB設(shè)備連接到辦公局域網(wǎng)或互聯(lián)網(wǎng)上,從而使USB設(shè)備看起仿佛構(gòu)成了一個以太網(wǎng)。這種方法專業(yè)性較強(qiáng),但通??尚?,是主機(jī)驅(qū)動程序使該方法成為可能。 在這三種方法中,您可以根據(jù)預(yù)留給開發(fā)的時間長短和期望USB接口在嵌入式應(yīng)用中所扮演的角色來決定選用那一種方法比較恰當(dāng)。為了幫助您做出正確的選擇,下一節(jié)將向您介紹這三種方法分別應(yīng)用于基于Linux的USB設(shè)備時的情況,但首先讓我們對USB接口做一個大致介紹。 USB概述 USB是一種方便快捷的接口,可用于為計算機(jī)工作站連接一些小配件。根據(jù)USB規(guī)范的定義,鼠標(biāo)、鍵盤、音頻播放和錄音設(shè)備、照相機(jī)、大容量存儲設(shè)備以及許多其他設(shè)備均可以通過USB接口,以高達(dá)480Mbps的速度連接到一臺主計算機(jī)。協(xié)議定制者對USB上運(yùn)行的這種復(fù)雜的主從式協(xié)議做出了仔細(xì)的說明,這就幫助保證了所有這些設(shè)備之間具備互操作性和兼容性。例如,該協(xié)議規(guī)定,USB設(shè)備只有在被詢問時才可以回答,并且USB主機(jī)會根據(jù)所連接的USB設(shè)備類型的不同,采用某些特定的格式,在某些特定的時間段從不同的設(shè)備獲取數(shù)據(jù)。 USB設(shè)備和主機(jī)之間通常通過專用的總線控制芯片建立連接。在USB主機(jī)上,名為UHCI或OHCI等的控制芯片通過插卡形式加入主機(jī)或直接集成到工作站的主板上。在主機(jī)一端的總線控制驅(qū)動程序管理著主機(jī)控制芯片,它同時還跟蹤監(jiān)視著主機(jī)目前連接的是哪些USB設(shè)備,從而決定應(yīng)如何與它們通信。 可用于連接照相機(jī)和鼠標(biāo)之類USB設(shè)備的總線控制器有很多種。其中的一種就在一塊芯片上同時集成了USB接口以及另一端的串口、I2C接口或并口。USB控制器(包括主機(jī)上的和USB設(shè)備上的控制器)也可能集成到英特爾StrongARM或 Hitachi H8之類的微控制器中去。這些芯片及其外圍部件有點(diǎn)類似以太網(wǎng)和CAN控制器,不同的是他們用于連接USB設(shè)備,并運(yùn)行USB協(xié)議。 很多人都知道Linux操作系統(tǒng)中包含了USB主機(jī)控制器的驅(qū)動程序,因而USB鍵盤、數(shù)碼相機(jī)以及其他一些USB設(shè)備都可以在一個運(yùn)行Linux操作系統(tǒng)的桌面工作站上使用。但很少有人知道Linux中還包含了一組USB設(shè)備控制器的驅(qū)動程序,尤其是集成到StrongARM SA1110處理器中的控制器。有了這些控制器驅(qū)動程序,基于Linux的嵌入式系統(tǒng)就能利用USB接口來與主計算機(jī)(運(yùn)行Linux或其他操作系統(tǒng))通信。大多數(shù)USB通信的實(shí)現(xiàn)過程都是雙端的。主機(jī)利用一個內(nèi)核模塊或驅(qū)動程序來與USB設(shè)備通信,而USB設(shè)備則通過其自身的驅(qū)動程序來與主機(jī)通信。根據(jù)主機(jī)和USB設(shè)備所采用的通信風(fēng)格的不同,驅(qū)動程序可以很簡單明白,也可以很復(fù)雜,很具挑戰(zhàn)性。本文主要關(guān)注USB設(shè)備端的通信過程,但也在適當(dāng)?shù)牡胤桨岁P(guān)于主機(jī)端通信過程實(shí)現(xiàn)的信息。 以下討論的技術(shù)應(yīng)當(dāng)引起讀者的注意。本文的目的是介紹如何在數(shù)碼相機(jī)和PDA等基于Linux的USB設(shè)備上使用Linux。此處所指的USB設(shè)備是嚴(yán)格意義上的USB設(shè)備,即帶正方形連接器的完整的設(shè)備,而不是哪些連接器形狀為扁平矩形的設(shè)備。此外,USB連接的另一端(通常是一臺PC工作站),應(yīng)該是一臺USB主機(jī)。 關(guān)于USB信息包的格式和通信參數(shù)的詳細(xì)信息,見本文的參考文獻(xiàn)。 通過編寫內(nèi)核模塊添加USB接口 1. USB設(shè)備端通信過程 向一個基于Linux的設(shè)備中添加USB接口的第一種方法是編寫一個用戶定制的Linux內(nèi)核模塊,這也是可實(shí)現(xiàn)最完備功能的一種做法。采用這種方法時通常需要針對主機(jī)的操作系統(tǒng)(Windows, Linux等)開發(fā)相應(yīng)的驅(qū)動程序。 一旦在設(shè)備中實(shí)現(xiàn)了用戶定制的內(nèi)核模塊,就可以使該設(shè)備完成相當(dāng)復(fù)雜的功能,例如仿真一個文件系統(tǒng),從而允許嵌入式應(yīng)用將其USB主機(jī)當(dāng)作一個遠(yuǎn)程存儲設(shè)備。除此以外,采用這種方法之后,設(shè)備還可以具備存儲轉(zhuǎn)發(fā)(store-and-forward)的功能,因而能夠在與USB主機(jī)的連接建立之前對來自嵌入式應(yīng)用的數(shù)據(jù)流進(jìn)行緩沖。 在基于StrongARM的Linux設(shè)備中,內(nèi)核代碼用于管理芯片所攜帶的USB設(shè)備控制器外設(shè),通過調(diào)用函數(shù)sa1100_usb_open()來初始化。在初始化之后,內(nèi)核模塊還會調(diào)用函數(shù)sa1100_usb_get_descriptor_ptr() 和sa1100_usb_set_string_descriptor()來設(shè)置在設(shè)備查詢期間傳送給USB主機(jī)的描述符,其中包含設(shè)備的數(shù)字廠商號和產(chǎn)品標(biāo)識符,以及可以讓主機(jī)用來識別設(shè)備的字符串,甚至還有一個序列號域,以便主機(jī)可以唯一地識別一個連接在USB接口上的設(shè)備,或者在同種型號的多個設(shè)備中進(jìn)行區(qū)分。 設(shè)備查詢過程是由USB設(shè)備控制器驅(qū)動的,并且一旦和USB主機(jī)連上之后會自動執(zhí)行,所以內(nèi)核模塊必須在USB通信開始之前設(shè)置好每個設(shè)備的描述符。當(dāng)準(zhǔn)備工作就緒之后,USB設(shè)備模塊就會調(diào)用函數(shù)sa1100_usb_start()來通知內(nèi)核接收主機(jī)發(fā)來的USB連接請求。如果設(shè)備模塊在連上USB 主機(jī)之前調(diào)用了函數(shù)sa1100_set_configured_callback(),那么接著內(nèi)核模塊就會在查詢過程結(jié)束時調(diào)用回調(diào)函數(shù)。回調(diào)函數(shù)很適合用來在設(shè)備上發(fā)出警告或給出一些形象的暗示,說明連接已經(jīng)建立。 如果不再需要進(jìn)行USB通信,那么設(shè)備的內(nèi)核模塊就會先調(diào)用函數(shù)sa1100_usb_stop(),然后調(diào)用sa1100_usb_close(),來關(guān)閉SA1100上的USB控制器。 StrongARM的 USB控制器支持bulk-in和bulk-out兩種數(shù)據(jù)傳送方式。當(dāng)接收來自USB主機(jī)的數(shù)據(jù)包時,內(nèi)核模塊會調(diào)用sa1100_usb_recv(),將一個數(shù)據(jù)緩沖區(qū)的地址和一個回調(diào)函數(shù)送給它。然后內(nèi)核中的USB設(shè)備控制代碼會從主機(jī)取回一個bulk-out數(shù)據(jù)包,將其內(nèi)容存入制定的緩沖區(qū),接著調(diào)用回調(diào)函數(shù)。 下一步,回調(diào)函數(shù)從接收緩沖區(qū)中提取出數(shù)據(jù),將其存放到其他地方,或者將緩沖區(qū)空間添加到一個隊列中,然后分配一個新的緩沖區(qū)來接收下一個數(shù)據(jù)包。然后,如果還有數(shù)據(jù)需要接收,那么回調(diào)函數(shù)會重新調(diào)用sa1100_usb_recv(),準(zhǔn)備接收另一個數(shù)據(jù)包。 向USB 主機(jī)發(fā)送數(shù)據(jù)的過程與此類似。內(nèi)核模塊收集了一幀數(shù)據(jù)之后,將數(shù)據(jù)的存放地址、數(shù)據(jù)長度和回調(diào)函數(shù)的地址送給sa1100_usb_send()函數(shù)。接著,在數(shù)據(jù)傳送結(jié)束之后,內(nèi)核模塊會調(diào)用回調(diào)函數(shù)。 在/code.htm(arch/arm/mach-sa1100/usb-char.c)可以找到一個叫做usb-char的模塊,這是一個很好的設(shè)備端SA1110 Linux USB模塊的例子。該模塊將USB設(shè)備與USB 主機(jī)之間的連接變成一種高速串行鏈接。此外, usb-eth( arch/arm/mach-sa1100/usb-eth.c)模塊也是個不錯的例子,該模塊將USB變成了一種虛擬的以太型網(wǎng)絡(luò)。后面會深入探討這兩種模塊。 2. USB主機(jī)端通信過程 有些很好的主機(jī)端USB驅(qū)動程序的例子是隨主流Linux操作系統(tǒng)的發(fā)布而提供的,位于The Linux Kernel Archives ()發(fā)布的原始內(nèi)核源代碼中。其中,Handspring Visor 模塊(drivers/usb/serial/visor.c)是一個編寫得更清晰,也更易理解的模塊,它同時也是USB 主機(jī)端模塊(drivers/usb/usb-skeleton.c)的模板。 利用USB實(shí)現(xiàn)高速串行通信 1. USB設(shè)備端通信過程 為了達(dá)到最實(shí)用的效果,我們可以將USB總線簡單地看作一個高速串口,然后,在一些嵌入式設(shè)備和應(yīng)用中,我們就可以用USB接口來模擬串口。StrongARM處理器的Linux內(nèi)核就提供了一個名為usb-char的USB設(shè)備驅(qū)動程序,它所完成的恰好就是用USB模擬串口的功能。 當(dāng)需要與USB 主機(jī)通信時,Linux操作系統(tǒng)中的USB設(shè)備應(yīng)用只是簡單地打開一個與其usb-char設(shè)備節(jié)點(diǎn)的連接(連接類型為字符型,major number 為10, minor 為240),然后就開始讀寫數(shù)據(jù)。在與USB 主機(jī)的連接建立之前,read()和write()操作均返回一個錯誤信息。一旦連接建立好,并且設(shè)備查詢完成之后,USB接口就開始象一個點(diǎn)對點(diǎn)的串口一樣與主機(jī)進(jìn)行通信。 這種進(jìn)行USB數(shù)據(jù)傳送的方法非常簡單有效,因而usb-char設(shè)備模塊發(fā)布之后一直很受歡迎。而且,該模塊還為通過其他方法進(jìn)行USB通信提供了一個參考。 在usb-char中,真正的操作開始于usbc_open()函數(shù),列表1給出了函數(shù)的一部分代碼。筆者由于臨時的興趣,對該代碼做了一點(diǎn)修改,取消了錯誤和超時句柄。在此向代碼的原作者Brad Parker、Nicolas Pitre 和Ward Willats致歉。 twiddle_descriptors()函數(shù)用于設(shè)置設(shè)備的USB描述符。在描述符設(shè)置好之后,我們就可以開始進(jìn)行設(shè)備查詢,并從USB 主機(jī)接收一幀數(shù)據(jù)。kick_start_rx()函數(shù)段的代碼主要用于調(diào)用sa1100_usb_recv(),建立回調(diào)。 在USB主機(jī)發(fā)送一個數(shù)據(jù)包時,設(shè)備的內(nèi)核模塊會通過回調(diào)方式調(diào)用rx_done_callback_packet_buffer()函數(shù),將數(shù)據(jù)包的內(nèi)容送入一個FIFO隊列,以便能通過read()函數(shù)將該數(shù)據(jù)包返回給usb-char設(shè)備節(jié)點(diǎn)。 2. USB主機(jī)端通信過程 對于運(yùn)行Linux操作系統(tǒng)的USB 主機(jī),與usb-char相應(yīng)的USB 主機(jī)模塊叫做usbserial。大多數(shù)Linux版本中都包含了該模塊,但它并不總能自動加載。通常應(yīng)在主機(jī)與USB設(shè)備之間的連接建立之前利用modprobe 或insmod加載該模塊。 USB設(shè)備查詢完成之后,主機(jī)上的一項(xiàng)應(yīng)用就會利用某個usbserial設(shè)備節(jié)點(diǎn)(字符型, major 為188, minor 大于等于0)與其通信。這些節(jié)點(diǎn)通常叫做/dev/ttyUSBn。Usbserial模塊會報告它將哪一個節(jié)點(diǎn)分配給了哪一臺USB設(shè)備,并將這一信息按如下方式記載在內(nèi)核消息記錄中: = usbserial.c:檢測到一般轉(zhuǎn)換器 usbserial.c:將一般轉(zhuǎn)換器加入ttyUSB0 = 這種連接一旦建立,USB 主機(jī)上的應(yīng)用就可以通過向特定的節(jié)點(diǎn)讀或?qū)懙姆绞脚c某USB設(shè)備通信。 此時,筆者并未考慮在運(yùn)行Win32或其他類型操作系統(tǒng)的主機(jī)上已有類似usbserial的模塊。但用于這些主機(jī)上的任何USB驅(qū)動程序,只要能夠進(jìn)行bulk-in 和 bulk-out數(shù)據(jù)傳輸,就很可能是一個近乎完整的驅(qū)動程序,只需進(jìn)行一定的產(chǎn)品調(diào)整,并添加與產(chǎn)品綁定的廠商ID。 Linux主機(jī)上還有另一種類似usbserial模塊的庫,叫做libusb (參見)。該庫通過低級的內(nèi)核系統(tǒng)調(diào)用而不是通過usbserial模塊來完成USB數(shù)據(jù)傳輸,因而在Linux kernel版本上更容易設(shè)置和使用。同時,該庫還能提供大量實(shí)用的調(diào)試功能,十分利于對USB鏈接上運(yùn)行的復(fù)雜的通信協(xié)議進(jìn)行調(diào)試。 為了通過libusb與一個采用了usb-char模塊的USB設(shè)備進(jìn)行通信,Linux主機(jī)應(yīng)用首先通過庫中的usb_open()函數(shù)與設(shè)備建立連接,然后利用函數(shù)usb_bulk_read()和usb_bulk_write()與設(shè)備交換數(shù)據(jù)。Libusb中含有幾個程序范例。 利用USB實(shí)現(xiàn)以太網(wǎng)連接 1. USB 設(shè)備端通信過程 如果利用USB連接來實(shí)現(xiàn)高速串口并非您所希望,那么您還可以將所有USB連接用作一個以太網(wǎng)。不論在主機(jī)端還是在設(shè)備端,Linux均有模塊能實(shí)現(xiàn)這一功能。iPAQ(掌上電腦)的Linux內(nèi)核就獨(dú)一無二地采用了這種通信策略,因?yàn)閕PAQ硬件中既沒有可訪問的串口也沒有專門的網(wǎng)絡(luò)接口。 StrongARM Linux內(nèi)核中,有一個叫做usb-eth的模塊(arch/arm/mach-sa1100/usb-eth.c),它利用USB作為物理媒介,模擬出一個虛構(gòu)的以太網(wǎng)設(shè)備。一旦這種網(wǎng)絡(luò)接口創(chuàng)建起來之后,就可以為它分配IP地址,并且外部環(huán)境均將其作為一個普通的以太網(wǎng)硬件對待。一旦USB 主機(jī)連接建立起來,usb-eth模塊就允許USB設(shè)備“瀏覽”因特網(wǎng),拼其他的IP地址,甚至通過DHCP、HTTP、NFS或者遠(yuǎn)程網(wǎng)“交談”,以及收發(fā)電子郵件。簡而言之,任何能夠在真正的以太網(wǎng)接口上運(yùn)行的應(yīng)用都可以原封不動地在usb-eth 上運(yùn)行,因?yàn)檫@些應(yīng)用無法識別它們所使用的其實(shí)并非真正的以太網(wǎng)硬件。 2. USB 主機(jī)端通信過程 相應(yīng)的,在運(yùn)行Linux操作系統(tǒng)的主機(jī)一端,可用來在USB上實(shí)現(xiàn)以太網(wǎng)連接的內(nèi)核模塊叫做usbnet。安裝了該模塊之后,一旦主機(jī)與USB設(shè)備的連接建立起來,它就會創(chuàng)建一個虛擬的以太網(wǎng)接口,在主機(jī)一端的內(nèi)核模塊以及用戶應(yīng)用看來,這個虛擬的接口與真正的以太網(wǎng)接口別無二致。主機(jī)端的應(yīng)用可以通過拼一個USB設(shè)備的IP地址來檢查該設(shè)備是否已經(jīng)連上,如果拼操作成功,那么就表

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論