娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

Linux驅動之USB總線驅動程序框架簡析

發布者:DreamySerenity最新更新時間:2024-08-19 來源: cnblogs關鍵字:Linux驅動  USB總線 手機看文章 掃描二維碼
隨時隨地手機看文章

通用串行總線(USB)是主機和外圍設備之間的一種連接。USB總線規范有1.1版和2.0版,當然現在已經有了3.0版本。USB1.1支持兩種傳輸速度:低速為1.5Mbps,高速為12Mbps。USB2.0的傳輸速度可以高達480Mbps。USB2.0向下兼容USB1.1,可以將USB1.1的設備連接到USB2.0控制器上,也可以把USB2.0的設備連接到USB1.1控制器上。S3C2440的USB主機控制器支持USB1.1總線規范。

USB總線的拓撲結構如下圖所示:USB主機控制器(USB Host Controller)通過根集線器(Root Hub)與其他USB設備相連。集線器也屬于USB設備,通過它可以在一個USB接口上擴展出多個接口。除根集線器外,最多可以層疊5個根集線器。一條USB主線上最多可以外接127個設備,當然包括根集線器和其他集線器。整個結構圖是一個星型結構,一條USB總線上所有設備共享一條通往主機的數據通道,同一時刻只能有一個設備與主機通訊

通過USB主機控制器來管理外接的USB設備。USB控制器實際上由USB控制器硬件+USB控制器軟件組成的。USB主機控制器分為3種:UHCI、OHCI、EHCI。UHCI與OHCI支持USB1.1協議;EHCI支持USB2.0協議。UHCI,它的硬件比較簡單,所以軟件相對就比較復雜;而OHCI,它的硬件具備更多性能,相反的軟件做的事情就比較少。S3C2440的USB主機控制器支持OHCI主機控制器。HCI的英文全稱為(Host Controller Interface)。

根據以上知識可以知道其實USB驅動程序可以分為兩類:USB主機控制器驅動程序(Host Controller Drivers)、USB設備驅動程序(USB device drivers)。它們在內核中的層次如下圖所示

USB主機控制器驅動程序提供訪問USB設備的接口,它只是一個數據通道,至于這些數據有什么作用,這要靠上層的USB設備驅動程序來解釋。USB設備驅動程序使用下層的驅動提供的數據接口來訪問USB設備,不需要關心具體的傳輸細節。在Linux2.6中,USB主機控制器驅動程序已經幫我們寫好了,下面就簡單分析一下USB主機控制器驅動程序。

1、在分析USB主機控制器驅動程序之前先來看幾個問題:

當把你的安卓手機通過USB接口接到電腦上的USB口時,會有如下現象

1、右下角彈出“發現andrido phone”。

2、跳出一個對話框,提示你安裝驅動程序。

那么問題便來了

問題1、既然還沒有“驅動程序”,為何能知道是“andrido phone”
答1:windows里已經有了USB的總線設備驅動程序,接入USB設備后,是“總線驅動程序”知道你是“andrido phone”,提示你安裝的是“設備驅動程序”,USB總線驅動程序負責:識別USB設備,給USB設備找到對應的驅動程序

問題2、USB設備種類非常多,為什么一接入電腦就能識別出來?
答2:PC和USB設備都得遵守一些規范。
比如:USB設備接入電腦后,PC會發出“你是什么?”USB設備必須回答“我是XXX”,并且回答的語言必須是中文;
USB總線驅動程序會發出某些命令獲取設備信息(描述符),USB設備必須返回“描述符”給PC。

問題3、PC機上接有非常多的USB設備,怎么分辨它們?
答3:接在USB總線上的每個USB設備都有自己的編號(地址),每一個USB設備接入PC時,USB總線驅動程序都會給它分配一個編號,PC機想訪問某個USB設備時,要先發出的命令都含有對方的編號(地址)

問題4、USB設備剛接入PC時,還沒有編號,那么PC怎么把“分配的編號”告訴它?
答4:新接入的USB設備的默認編號是0,在未分配新的編號前,PC使用0編號和它通訊。

問題5、為什么一接入USB設備,PC機就能發現它(又沒有中斷)
答5:USB接口只有4條線:5V、GND、D-、D+。PC的USB口內部D-和D+接有15K的下拉電阻,未接USB設備時為低電平;USB設備的USB口內部,D-或D+接有1.5k的上拉電阻:它一接入就會把PC USB口D-(全速)或D+(高速)拉高,從硬件的角度通知PC有新設備接入。

從以上問答可以看出來USB總線驅動程序的作用可以總結為:(后面會再詳細說明)

1、識別設備
2、找到并安裝對應的USB設備驅動
3、提供USB讀寫函數(不了解數據含義)

 

 2、接著再提出一些USB的概念

1、USB是主從結構的
所有的USB傳輸都是從USB主機這方發起,USB設備沒有主動通知USB主機的能力
例子:USB鼠標滑動一下,立刻產生數據,但是它沒有能力通知PC讀數據,只能被動的等待PC機被讀

2、USB的傳輸類型:
a、控制傳輸:可靠,時間有保證,比如USB設備的識別過程
b、批量傳輸:可靠,時間沒有保證,比如:U盤
c、中斷傳輸(還是查詢方式):可靠,實時,比如:USB鼠標
d、實時傳輸:數據不可靠,實時,比如:USB攝像頭

3、USB傳輸的對象:端點(endpoint)
我們說“讀U盤”、“寫U盤”可以細化為:把數據寫到U盤的端點1,把數據從U盤的端點2里讀出數據
除了端點0之外,每一個端點只支持一個方向的數據傳輸
端點0用于控制傳輸,既能輸出也能輸入

4、每一個端點都只有一個傳輸類型,傳輸方向

5、術語里、程序里說的輸入(IN)、輸出(OUT)“都是”基于USB主機的立場說的。
比如鼠標的數據是從鼠標傳入PC機的,對應的端點稱為“輸入端點”

 

3、通過前面的描述對于USB已經有了大致的了解了,接著通過程序分析來更深入的了解USB設備的識別過程:

把一個USB鼠標接到開發板上會彈出如下信息:

usb 1-1: new full speed USB device using s3c2410-ohci and address 3

usb 1-1: configuration #1 chosen from 1 choice

scsi1 : SCSI emulation for USB Mass Storage devices

拔掉

usb 1-1: USB disconnect, address 3

再接上

usb 1-1: USB disconnect, address 3usb 1-1: new full speed USB device using s3c2410-ohci and address 4

usb 1-1: configuration #1 chosen from 1 choice

scsi2 : SCSI emulation for USB Mass Storage devices


其中address3,address4就是USB核心程序給USB設備分配的地址。查找“USB device using ”關鍵字,在drivers/usb/core/hub.c的2186行找到了這句話:'%s %s speed %sUSB device using %s and address %dn'。它位于hub_port_init函數下,層層查找可以發現最終是hub_irq函數導致了hub_port_init被調用。hub_irq不是一個真正的中斷處理程序,它只是集線器USB設備的數據接收完成后的回調函數,其實drivers/usb/core/hub.c也不過是一個USB設備驅動程序而已。


drivers/usb/core/hub.c程序先放到一邊,待會再來分析它。先嘗試找一下USB控制器的驅動程序,在driversusbhostOhci-s3c2410.c找到了這個驅動程序, 它以平臺設備驅動程序為框架,driversusbhostOhci-s3c2410.c屬于driver層


static struct platform_driver ohci_hcd_s3c2410_driver = {

    .probe        = ohci_hcd_s3c2410_drv_probe,//一旦匹配devices則被調用

    .remove        = ohci_hcd_s3c2410_drv_remove,

    .shutdown    = usb_hcd_platform_shutdown,

    /*.suspend    = ohci_hcd_s3c2410_drv_suspend, */

    /*.resume    = ohci_hcd_s3c2410_drv_resume, */

    .driver        = {

        .owner    = THIS_MODULE,

        .name    = 's3c2410-ohci',

    },

};


接著搜索“s3c2410-ohci”,找到了devices層,位于archarmplat-s3c24xxDevs.c


struct platform_device s3c_device_usb = {

    .name          = 's3c2410-ohci',

    .id          = -1,

    .num_resources      = ARRAY_SIZE(s3c_usb_resource),

    .resource      = s3c_usb_resource,

    .dev              = {

        .dma_mask = &s3c_device_usb_dmamask,

        .coherent_dma_mask = 0xffffffffUL

    }

};


到這里我們還沒有找到插上USB設備后第一個運行的函數,我們猜測這個函數必定是一個中斷,USB控制器接收到數據后將會產生一個中斷給MCU,然后MCU再進行處理。現在我們就是要找到這一個中斷函數,在drivers/usb/core/hub.c中找到了usb_add_hcd函數,它位于usb_hcd_s3c2410_probe函數下,這個函數一旦有USB控制器設備匹配就會被調用。


static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,

                  struct platform_device *dev)

{

    ...

    ...


    retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);//注冊OHCI控制器中斷

    if (retval != 0)

        goto err_ioremap;


    ...

    ...

}


繼續往下看usb_add_hcd函數,它位于driversusbcorehcd.c下


int usb_add_hcd(struct usb_hcd *hcd,

        unsigned int irqnum, unsigned long irqflags)

{

    ...

    ...

        if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,

                hcd->irq_descr, hcd)) != 0) {//中斷USB中斷

            dev_err(hcd->self.controller,

                    'request interrupt %d failedn', irqnum);

            goto err_request_irq;

        }

        hcd->irq = irqnum;

    ...

    ...


在這里看到了調用注冊中斷函數,并且它的中斷處理回調函數為usb_hcd_irq,它同樣位于driversusbcorehcd.c下


irqreturn_t usb_hcd_irq (int irq, void *__hcd)

{

    struct usb_hcd        *hcd = __hcd;

    int            start = hcd->state;


    if (unlikely(start == HC_STATE_HALT ||

        !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))

        return IRQ_NONE;

    if (hcd->driver->irq (hcd) == IRQ_NONE)

        return IRQ_NONE;


    set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);//設置中斷標志


    if (unlikely(hcd->state == HC_STATE_HALT))

        usb_hc_died (hcd);

    return IRQ_HANDLED;

}


這樣,通過usb_hcd_irq 函數的作用,最終將會調用到drivers/usb/core/hub.c下的hub_irq函數。之前說過drivers/usb/core/hub.c其實也是一個USB設備驅動程序,它其實是一個根集線器驅動程序。這里直接列出匹配USB設備驅動程序的過程。


hub_irq

    kick_khubd

        hub_thread

            hub_events

                hub_port_connect_change

                    usb_alloc_dev(hdev, hdev->bus, port1);

                        dev->dev.type = &usb_device_type;

                        

                    choose_address(udev);  //給新設備分配編號(地址)

                    

                    hub_port_init      //usb 1-1: new full speed USB device using s3c2410-ohci and address 3

                        hub_set_address  //把編號(地址)告訴USB設備

                        usb_get_device_descriptor(udev, 8);//獲取設備描述符

                        usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

                        

                    usb_new_device(udev);

                        usb_get_configuration(udev);//把所有的描述符都讀出來并解析

                            usb_parse_configuration

                            

                        device_add//把device放入usb_bus_type的dev鏈表,

                             //從usb_bus_type的driver鏈表中取出usb_driver

                             //把usb_interface和usb_driver的id_table比較

                             //如果能匹配,調用usb_driver的probe函數


大致總結一下:


1、當接上USB鼠標后,USB主機控制器檢查到D-或D+接口變高知道了有設備接入。


2、USB主機控制器把新分配的編號告訴USB設備,這時候還是以0地址通訊的。


3、USB主機控制器以0地址從USB設備獲得設備描述符的前8個字節,從這8個字節可以知道后面所有設備描述符總共的大小


4、知道了剩下設備描述符的大小,就可以將剩余的設備描述符都讀出來


5、接著把device放入usb_bus_type的dev鏈表


6、從usb_bus_type的driver鏈表中取出usb_driver


7、把usb_interface和usb_driver的id_table比較(對于USB鼠標最終比較的是接口描述符下的bInterfaceClass;bInterfaceSubClass;bInterfaceProtocol;三個信息,中文翻譯為設備類型,設備子類型,設備協議)


8、如果能匹配,調用usb_driver的probe函數


從上面總結可以看出,要寫USB設備的驅動程序就需要對usb_driver結構體進行初始。


USB各個描述符的關系如下,具體描述符結構將在下一節講解

 

 以上就是USB總線驅動程序的框架,USB設備是一個非常復雜的東西,這里只是簡單的描述,并未深入理解。目的是為了編寫USB設備驅動程序。


關鍵字:Linux驅動  USB總線 引用地址:Linux驅動之USB總線驅動程序框架簡析

上一篇:Linux驅動之LCD驅動編寫
下一篇:利用Crosstool-ng制作交叉編譯工具鏈

推薦閱讀最新更新時間:2025-03-25 01:09

通過USB總線為電池充電
??? 無處不在的USB總線能夠為所有類型的低功耗電子設備提供電源。總線電源與電網隔離,并且具有很好的穩定性。 但是,可用電流是受限的,同時負載和主機或電源之間存在潛在的互操作問題。? ??? USB端口由90Ω雙向差分屏蔽雙絞線、VBUS?(+5V電源)?和地組成。這4條線由鋁箔內屏蔽層和編織網外屏蔽層進行屏蔽。最新的USB規范標準是2.0版,可以從USB組織免費獲得。要做到完全符合該規范標準,需要通過一個功能控制器來實現設備和主機間的雙向通信。規范定義了1個單位負載為100mA?(最大)。任何設備允許吸取的最大電流為5個單位負載。USB端口可分為低功率端口和大功率端口兩類,低功率端口可提供1個單位負載的電
[嵌入式]
Samsung_tiny4412(驅動筆記01)----linux 3.5,U-Boot,Busybox,SD卡啟動環境搭建
/*********************************************************************************** * * linux 3.5,U-Boot,Busybox,SD卡啟動環境搭建 * * 聲明: * 1. 本系列文檔是在vim下編輯,請盡量是用vim來閱讀,在其它編輯器下可能會 * 不對齊,從而影響閱讀. * 2. 以下所有的shell命令都是在root權限下運行的; * 3. minicom(U-Boot)指的是用minicom連接開發板做為U-Boot的終端; * 4. 文中在需
[單片機]
linux2.6.32.2 mini2440平臺移植-- LCD 顯示驅動 ( W35屏 )
1.4.1 LCD 驅動基礎知識 Linux-2.6.32.2 內核已經支持 S3C2440 的 LCD 控制器驅動,但在此我們先介紹一下關于 2440 LCD 控制器以及驅動相關的 LCD 的一些基礎知識。 注意:在此我們只討論 TFT LCD,也就是真彩屏。 LCD 驅動中最關鍵的就是時鐘頻率(Clock frequency)的設置,時鐘頻率設置不對,LCD 的顯示就會閃,或者根本沒有顯示。一般 LCD 的 Datasheet 上會寫有一個推薦的頻率,比如 mini2440 所用的統寶 3.5 LCD,在它的數據手冊第 13 頁,有這樣一個表格:可以看到,這里推薦的時鐘頻率是 6.39MHz,近似于 6.4MHz,
[單片機]
迅為4412開發板Linux驅動教程之GPIO的初始化
視頻下載地址: http://pan.baidu.com/s/1c06oiti GPIO的初始化 ? 在內核源碼目錄下使用命令“ls drivers/gpio/*.o”,可以看到“gpio-exynos4”被編譯進了內核 – 生成.o文件代表最終被編譯進了內核 – 除了menuconfig配置文件,還可以通過.o文件來判定該文件是否編譯進了 內核 ? 在“gpio-exynos4.c”文件最下面一行 – core_initcall(exynos4_gpiolib_init); – core_initcall代表在linux初始化過程中會調用 – 初始化函數是在源碼目錄下“include/linux/init.h”文件中定義
[單片機]
迅為4412開發板<font color='red'>Linux</font><font color='red'>驅動</font>教程之GPIO的初始化
Linux-2.6.32.2內核在mini2440上的移植(六)---添加LCD背光驅動
移植環境 1,主機環境:VMare下CentOS 5.5 ,1G內存。 2,集成開發環境:Elipse IDE 3,編譯編譯環境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,開發板:mini2440,2M nor flash,128M nand flash。 5,u-boot版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,參考文章: 嵌入式linux應用開發完全手冊,韋東山,編著。 Mini2440 之Linux 移植開發實戰指南 到目前為止,我們一直都在命令行下移植,查看結果,LCD 屏幕上似乎總是如伸手不見五指
[單片機]
<font color='red'>Linux</font>-2.6.32.2內核在mini2440上的移植(六)---添加LCD背光<font color='red'>驅動</font>
基于Linux的USB從設備驅動研究
引言   USB是英文Universal Serial Bus的縮寫,意為通用串行總線。USB是一種快速、雙向、同步、低成本、動態可連接的串行接口。USB現在已經廣泛應用到各種設備上,尤其是手持設備,幾乎都采用了USB接口。現在,USB即可用來與其他設備連接后高速地傳遞數據,又可用來充電,使手持設備可以發揮U盤、MODEM、無線網卡等作用。   事實上,USB只是主機和外圍設備之間的連接。如何來促使這種連接發揮作用,就需要驅動程序。驅動程序主要解決硬件“需要提供什么功能”以及“如何使用這些功能”。在linux系統中,USB設備可以作為主機使用,也可作為從設備使用。對應的USB驅動程序有兩種主要的類型:宿主系統上的驅動程序和設
[單片機]
基于<font color='red'>Linux</font>的USB從設備<font color='red'>驅動</font>研究
嵌入式Linux系統中I2C總線設備的驅動設計
引言 I2C總線是PHILIPS公司推出的兩線式串行總線,用于連接微控制器及其外圍設備,具有簡單、高效等特點。由于其接口直接在組件之上,因此I2C總線占用的空間非常小,減少了電路板的空間和芯片引腳的數量,降低了互聯成本,特別適用于嵌入式產品。 而Linux系統具有開源、免費、網上資源豐富等優點,目前已成為嵌入式系統的主流選擇。因此如何在嵌入式Linux系統中實現I2C功能成為實際開發中的問題。 I2C總線 I2C 總線通過串行數據SDA 和串行時鐘SCL線在連接到總線的器件間傳遞信息,每個器件都有一個唯一的地址識別。根據數據傳輸時的功能不同,把器件分為主機和從機。主機是初始化總線的數據傳輸并產生允許傳輸的時鐘信
[單片機]
嵌入式<font color='red'>Linux</font>系統中I2C總線設備的<font color='red'>驅動</font>設計
嵌入式Linux下的AU 1200 MAE驅動程序設計
隨著移動多媒體終端的口益普及,功能的日益強大,人們已經不滿足于自己的手持終端僅僅能夠聽MP3音樂,而是希望終端在播放音樂的同時能夠播放高質量視頻,并支持多種視頻格式。AU 1200作為一款基于MIPS架構的處理器,由于其片上集成了視頻硬件設備(Media Accel-eration Engine,MAE),使得該處理器無需配合其他視頻解碼芯片即可完成多種格式的視頻解碼功能,所以AU 1200非常適合應用于像PMP這樣的移動多媒體終端,而MAE也成為AU 1200的特色。 1 MAE概述 MAE是AU 1200的片上硬件設備,除了可以實現視頻解碼功能外,還可以完成色彩空間轉換、濾波等工作。MAE在硬件結構上可以分為前端和后端
[嵌入式]
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 揭西县| 班玛县| 成武县| 柳河县| 石阡县| 永安市| 任丘市| 桐柏县| 布尔津县| 鹤岗市| 宁河县| 淳安县| 江永县| 同仁县| 乾安县| 台南县| 布尔津县| 白朗县| 临清市| 金堂县| 景宁| 湘乡市| 玉门市| 阜南县| 蒙自县| 杭州市| 永康市| 尤溪县| 安徽省| 开封县| 黄石市| 高密市| 古浪县| 马关县| 防城港市| 广州市| 万宁市| 祥云县| 通化县| 湾仔区| 洛川县|