1. 程式人生 > >linux驅動開發:匯流排,裝置,驅動三要素

linux驅動開發:匯流排,裝置,驅動三要素

平臺匯流排和IIC,SPI,IIS都是匯流排型別,一般的,匯流排下,掛載對應的裝置。但實際上,裝置要正常運轉,是需要驅動程式來未知提供驅動的。所以linux核心也把驅動掛載在對應的匯流排下。匯流排,驅動,裝置三者缺一不可.
相應的,核心衍生出來的平臺匯流排,那麼便衍生出來了平臺裝置和憑條驅動。他們均有自己的專屬函式來註冊,登出。這個是成一套體系結構的.在以後的驅動開發中,很是常見與重要.

一)核心中的匯流排,裝置,驅動
1)匯流排

struct bus_type {
    const char      *name;
    const char      *dev_name;
    struct
device *dev_root; struct bus_attribute *bus_attrs;//匯流排屬性 struct device_attribute *dev_attrs;//裝置屬性 struct driver_attribute *drv_attrs;//驅動屬性 int (*match)(struct device *dev, struct device_driver *drv);//匹配匯流排下的裝置和驅動 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);//用於匯流排環境變數的新增
int (*probe)(struct device *dev);//回撥函式 int (*remove)(struct device *dev); void (*shutdown)(struct device *dev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); const struct dev_pm_ops *pm;//電源管理 struct iommu_ops *iommu_ops; struct
subsys_private *p;//將bus device sysfs聯絡起來 struct lock_class_key lock_key; }; 註冊:bus_register(struct bus_type *bus); 登出:bus_unregister(struct bus_type *bus);

2)裝置

struct device {
    struct device       *parent;

    struct device_private   *p;

    struct kobject kobj;
    const char      *init_name; /* initial name of the device */
    const struct device_type *type;

    struct mutex        mutex;  /* mutex to synchronize calls to
                     * its driver.
                     */

    struct bus_type *bus;       /* type of bus device is on  裝置所屬的匯流排*/
    struct device_driver *driver;   /* which driver has allocated this
                       device */
    void        *platform_data; /* Platform specific data, device
                       core doesn't touch it */
    struct dev_pm_info  power;
    struct dev_pm_domain    *pm_domain;

#ifdef CONFIG_PINCTRL
    struct dev_pin_info *pins;
#endif

#ifdef CONFIG_NUMA
    int     numa_node;  /* NUMA node this device is close to */
#endif
    u64     *dma_mask;  /* dma mask (if dma'able device) */
    u64     coherent_dma_mask;/* Like dma_mask, but for
                         alloc_coherent mappings as
                         not all hardware supports
                         64 bit addresses for consistent
                         allocations such descriptors. */

    struct device_dma_parameters *dma_parms;

    struct list_head    dma_pools;  /* dma pools (if dma'ble) */

    struct dma_coherent_mem *dma_mem; /* internal for coherent mem
                         override */
#ifdef CONFIG_CMA
    struct cma *cma_area;       /* contiguous memory area for dma
                       allocations */
#endif
    /* arch specific additions */
    struct dev_archdata archdata;

    struct device_node  *of_node; /* associated device tree node */
    struct acpi_dev_node    acpi_node; /* associated ACPI device node */

    dev_t           devt;   /* dev_t, creates the sysfs "dev" */
    u32         id; /* device instance */

    spinlock_t      devres_lock;
    struct list_head    devres_head;

    struct klist_node   knode_class;
    struct class        *class;
    const struct attribute_group **groups;  /* optional groups */

    void    (*release)(struct device *dev);
    struct iommu_group  *iommu_group;
};

設備註冊:int device_register(struct device *dev)
設備註銷:void device_unregister(struct device *dev)

3)裝置驅動

struct device_driver {
    const char      *name;
    struct bus_type     *bus;//掛載的匯流排,所屬的匯流排

    struct module       *owner;
    const char      *mod_name;  /* used for built-in modules */

    bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */

    const struct of_device_id   *of_match_table;
    const struct acpi_device_id *acpi_match_table;

    int (*probe) (struct device *dev);// 裝置match到驅動,則呼叫對應驅動的probe函式,驅動裝置
    int (*remove) (struct device *dev);//當驅動或者裝置被解除安裝,則呼叫對應驅動的remove函式
    void (*shutdown) (struct device *dev);
    int (*suspend) (struct device *dev, pm_message_t state);
    int (*resume) (struct device *dev);
    const struct attribute_group **groups;

    const struct dev_pm_ops *pm;

    struct driver_private *p;
};

驅動註冊:int driver_register(struct device_driver *drv)
驅動登出:void driver_unregister(struct device_driver *drv)

二)平臺裝置匯流排
匯流排:

struct bus_type platform_bus_type = {
    .name       = "platform",
    .dev_attrs  = platform_dev_attrs,
    .match      = platform_match,
    .uevent     = platform_uevent,
    .pm     = &platform_dev_pm_ops,
};

裝置:

struct platform_device {
    const char  *name;
    int     id;
    bool        id_auto;
    struct device   dev;
    u32     num_resources;
    struct resource *resource;

    const struct platform_device_id *id_entry;

    /* MFD cell pointer */
    struct mfd_cell *mfd_cell;

    /* arch specific additions */
    struct pdev_archdata    archdata;
};
平臺裝置的註冊:platform_device_register(struct platform_device * pdev)
平臺裝置的登出:platform_device_unregister(struct platform_device * pdev)

驅動:

struct platform_driver {
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);
    void (*shutdown)(struct platform_device *);
    int (*suspend)(struct platform_device *, pm_message_t state);
    int (*resume)(struct platform_device *);
    struct device_driver driver;
    const struct platform_device_id *id_table;
};
平臺驅動的註冊:int platform_driver_register(struct platform_driver *drv)
平臺驅動的登出:void platform_driver_unregister(struct platform_driver *drv)

平臺裝置匹配的流程:

先插入一個函式,match

static int platform_match(struct device *dev, struct device_driver *drv)
{
    struct platform_device *pdev = to_platform_device(dev);
    struct platform_driver *pdrv = to_platform_driver(drv);

    /* Attempt an OF style match first */
    if (of_driver_match_device(dev, drv))
        return 1;

    /* Then try ACPI style match */
    if (acpi_driver_match_device(dev, drv))
        return 1;

    /* Then try to match against the id table */
    if (pdrv->id_table)
        return platform_match_id(pdrv->id_table, pdev) != NULL;

    /* fall-back to driver name match */
    return (strcmp(pdev->name, drv->name) == 0);
}
//match 的方式:不同的核心,可能有所不同:我的核心版本:3.10.46

1.OF style match first
2.ACPI style match
3.match against the id table
4.driver name match

大概的匹配流程:
1)平臺設備註冊流程:

platform_device_register()
{
--->platform_device_add()
    {
        --->device_add()
        {
            --->device_add()
            {
                --->bus_probe_device()
                {

                    --->device_attach()
                    {
                        --->bus_for_each_drv(dev->bus, NULL, dev, __device_attach)
                        {
                            --->__device_attach()
                            {
                                --->driver_match_device()//platform_match()
                                //當match到驅動後,繼續下面步驟:
                                --->driver_probe_device()
                                {
                                    --->really_probe()
                                    {
                                        --->drv->probe()//呼叫對應驅動的probe函式
                                    }

                                }

                            }
                        }
                    }


                }
            }
        }
    }

}

2)平臺驅動註冊流程:

platform_driver_register()
{
    --->driver_register()
    {
        --->bus_add_driver()
        {
            --->driver_attach()
            {
                --->bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)
                {
                    --->__driver_attach()
                    {
                        --->driver_match_device()//platform_match()
                        //當match到對應的裝置後,繼續
                        --->driver_probe_device()
                        {
                            --->really_probe()
                            {
                                --->drv->probe()//呼叫當前註冊驅動的probe函式
                            }
                        }
                    }
                }
            }
        }
    }
}

這裡寫圖片描述

1.裝置向對應平臺bus註冊裝置,裝置掛載到平臺bus下面的dev list連結串列中.
2.驅動向對應平臺bus註冊驅動,驅動掛載到平臺bus下面的driver list連結串列中.
3.裝置和對應匯流排下的driver list連結串列中每個driver進行匹配(match).匹配成功則呼叫對應driver的probe函式,否則匹配失敗,則裝置無法被驅動,裝置無法工作.

match函式已經在上面列出。它有自己的匹配規則,上一篇的例項是按照match name來進行匹配的.
當裝置或者驅動被解除安裝時,驅動的remove函式都會被呼叫.

平臺裝置匯流排的意義:移植性強。通過我們是不需要寫平臺裝置檔案的,只需要寫對應的驅動檔案。而驅動檔案一般移植時並不需要修改。只需要修改對應的platform_data 平臺數據和resource 平臺資源列表便可.
這樣修改一個驅動或者移植一個驅動到另一個核心便變得很簡單。

相關推薦

linux驅動開發匯流排裝置驅動要素

平臺匯流排和IIC,SPI,IIS都是匯流排型別,一般的,匯流排下,掛載對應的裝置。但實際上,裝置要正常運轉,是需要驅動程式來未知提供驅動的。所以linux核心也把驅動掛載在對應的匯流排下。匯流排,驅動,裝置三者缺一不可. 相應的,核心衍生出來的平臺匯流排,那

linux裝置驅動模型之匯流排裝置驅動三者的關係

匯流排、裝置、驅動,也就是bus、device、driver,在核心裡都有對應的結構體,在include/linux/device.h 裡定義。Device.h (linux-3.4.2\inclu

【迅為iTop4412學習筆記】4. 匯流排裝置驅動註冊流程

宣告 以下都是我剛開始看驅動視訊的個人強行解讀,如果有誤請指出,共同進步。 本節目標 瞭解Linux匯流排、裝置 驅動註冊的流程 基本知識 一般的裝置:接入裝置 -> 註冊裝置 -> 註冊

linux裝置驅動歸納總結(九)1.platform匯流排裝置驅動

linux裝置驅動歸納總結(九):1.platform匯流排的裝置和驅動 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 這一節可

Linux裝置模型(匯流排裝置驅動程式和類)之一bus_type

      匯流排是處理器和一個或多個裝置之間的通道,在裝置模型中,所有的裝置都通過匯流排相連,甚至是內部的虛擬"platform"匯流排。可以通過ls -l /sys/bus看到系統載入的所有匯流排。drwxr-xr-x root     root             

linux驅動開發用戶空間操作LCD顯示簡單的圖片【轉】

res fin blue var chang uil print views statistic 轉自:http://blog.csdn.net/changliang7731/article/details/53074616 上一章我們簡單介紹了LCD的一些基本原

android開發在Macbook環境android studio 配置git環境

第一步:對專案啟用git管理 這步是將專案納入git管理之下,點選android studio選單欄的VCS後,選擇Enable Version Control Integration. 在彈出的框裡選擇Git 然後可以發現在快捷工具圖示裡面多了兩個版本控制的按鈕,並且

linuxlinux報錯安裝nginx時make報錯解決方法

目錄 一、報錯情況 二、解決方法 三、openssl舊版本下載和安裝 一、報錯情況 (1)輸入命令,報錯: make (2)具體報錯: make[1]: *** [objs/src/event/ngx_event_openssl.o] 錯誤

Linux I2C核心、匯流排裝置驅動

I2C匯流排僅僅使用SCL、 SDA這兩根訊號線就實現了裝置之間的資料互動,極大地簡化了對硬體資源和PCB板佈線空間的佔用。因此, I2C匯流排非常廣泛地應用在EEPROM、實時鐘、小型LCD等裝置與C

linux驅動開發-檔案系統與裝置檔案

目錄 1.Linux檔案系統操作 Linux檔案建立,開啟,關閉函式 #檔案許可權最終由mode&umask決定 int creat (const char *filename,mode_t mod

ZYNQ Linux驅動開發——第一個字元裝置驅動

硬體平臺:XCZ7020 CLG484-1 完全適配Zedboard 開發環境:Widows下Vivado 2016.2 、 SDK2016.2 、 Linux機器:debin 目的:操作板載的LED燈LD9,受PS部分的MIO7控制 linux裝置驅

Linux學習總結特殊許可權SUIDSGIDSBIT

目錄 一、SUID 二、SGID 三、SBIT Linux中除了rwx許可權外,另外還有三種特殊許可權:SUID、SGID、SBIT 假如本來在該位上有x, 則這些特別標誌 (SUID, SGID,SBIT)顯示為小寫字母 (s,s,t)。否則顯示為大寫字母 (S,S,T) 。在

Linux匯流排裝置驅動模型

1. 分配一個platform_device結構並呼叫platform_device_register函式進行註冊 int platform_device_register(struct platform_device *pdev) { device_initialize(&pdev->de

裝置驅動歸納總結(八)1.匯流排裝置驅動 —— 匯流排的註冊

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 這幾天一直在看裝置模型,核心的程式碼看得我越來越沮喪,特別是kboject、kset和ktype之間的關係。但是,裝置

deepin15.8 Linux開發Python應用安裝pipvirtualenvwrapper

1,上個帖子用雙十一買的magicbook銳龍版裝了deepin15.8,為的就是把開發工作轉移到deepin下 畢竟Python開發很多包在Linux更好安裝一些包 2 ,由於deepin自帶py2和py3,但是沒有整合pip 進來  自行安裝   sudo apt in

Linux匯流排裝置驅動》自己寫的demo

本demo基於Android2.3模擬器開發,核心程式碼(Linux2.6.29)和Android程式碼可以在網上下載、這裡不在說明。 一、驅動 1.匯流排驅動 功能:匯流排驅動;提供設備註冊和裝置驅動註冊以及裝置與裝置驅動匹配等函式功能。 testbus.c #inc

linux驅動開發觸控式螢幕的認識(FT5x06 IC的分析)

我們板子上的觸控式螢幕是電容屏,當然也有電阻屏。不過目前絕大多數是電容屏。 原理:按下某個位置,得到某個位置的特定電阻/電容值,電阻屏(可能通過好幾個adc去捕獲這些電阻值),因為平面上一個點至少需要a(x,y)表示. 拆開LCD屏的板子,找到觸控式螢幕那塊

嵌入式Linux——應用除錯自制系統呼叫並編寫程序檢視器

簡介:     本文主要講解在ARM Linux中系統呼叫的原理,並根據這些原理在系統中新增自制的系統呼叫函式,最後我們還將通過自制的系統呼叫函式來檢視應用程式指定位置的資訊,用此方法實現應用程式的除錯。  Linux核心:linux-2.6.22.6  所用開發板

Linux Kernel裝置驅動模型之匯流排查詢裝置

裝置驅動模型之匯流排查詢裝置: /**  * bus_find_device - device iterator for locating a particular device.  * @bus: bus type  * @start: Device to begin w

linux驅動開發之自動建立裝置節點

在有2.6系列版本中支援udev管理裝置檔案可以方便的建立裝置節點,不必使用mknod來建立,本文使用最小編碼來說明建立的幾個方法。 //主要用到的四個方法在linux/device.h定義: //建立類和釋放類的函式  建立成後將建立/sys/class/name資料