新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 總線設備驅動模型總結

        總線設備驅動模型總結

        作者: 時間:2016-12-01 來源:網絡 收藏
        我的環境:
        主機開發環境:Fedora14
        開發板: TQ2440
        編譯器: arm-linux-gcc-4.3.2
        型其實現主要是基于Kobject和sysfs等機制,對于驅動模型程序開發主要是理解三個元素:總線、設備、驅動的關系。三者之間因為一定的聯系性實現對設備的控制。
        首先是總線,總線是三者聯系起來的基礎,通過一種總線類型,將設備和驅動聯系起來。總線類型中的match函數用來匹配設備和驅動。當匹配操作晚餐之后就會控制驅動程序中的probe函數。
        型的設計主要包括三個元素的注冊,將三個元素加載到內核中,然后通過內核的內部機制將三者聯系起來。
        首先,總線類型的注冊,包括屬性文件的添加,總線也是一種設備,也需要將總線設備注冊。
        其次,完成設備的注冊和添加以及對設備添加設備屬性文件,同時填充最基本的函數操作。
        最后,完成驅動的注冊和天極以及對設備驅動添加屬性文件,同時填充最基本的函數操作。
        1、總線
        總線類型是通過結構體bus_type表示的。其源碼如下所示:
        struct bus_type {
        /*總線名*/
        const char *name;
        /*總線、設備、驅動屬性*/
        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 (*suspend_late)(struct device *dev, pm_message_t state);
        int (*resume_early)(struct device *dev);
        int (*resume)(struct device *dev);
        struct dev_pm_ops *pm;
        struct bus_type_private *p;
        };
        其中的int (*match)(struct device * dev, struct device_driver * drv)是必須實現的函數,因為這個函數主要是實現設備和驅動之間的匹配管理。其中匹配的具體邏輯關系需要驅動設計著設定。
        int (*uevent)(struct device *dev, char **envp, int num_envp,char *buffer, int buffer_size)則在熱插拔事件之前,允許總線為設備添加環境變量。
        通常創建一種總線類型的過程中只要完成總線類型結構體的填充,然后完成相應的注冊、屬性文件創建即可實現總線類型的添加。并不需要對bus_type類型中的所有變量進行賦值,只要將其中的name,bus_attribute,match實現即可。
        最后不要忘了總線也是設備,需要將總線設備添加到內核中(注冊函數)。
        關于總線類型的屬性設置,實質上就是完成一個結構體的操作。
        如下源碼所示:
        struct bus_attribute {
        /*屬性結構體*/
        struct attribute attr;
        /*屬性讀操作函數,即顯示函數*/
        ssize_t (*show)(struct bus_type *bus, char *buf);
        /*屬性寫操作函數,也就是存儲到結構體中*/
        ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
        };
        /*可以通過宏命令定義一個總線結構體,但是需要自己實現屬性讀寫操作函數,如果沒有,可設置為NULL*/
        /*總線屬性定義宏*/
        #define BUS_ATTR(_name, _mode, _show, _store)
        struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
        /*__ATTR的宏實現如下所示:*/
        #define __ATTR(_name,_mode,_show,_store) {
        .attr = {.name = __stringify(_name), .mode = _mode },
        .show = _show,
        .store = _store,
        }
        由于通常情況下需要查找總線的版本信息,可以將版本信息添加到屬性的讀屬性操作函數中,這樣就能顯示具體的版本信息。
        在宏定義中##是指鏈接符的作用,相當于將兩個部分鏈接起來,比如bus_attr_##name = bus_attr_name。這是在宏定義中比較常用的定義方式之一。
        總線類型的注冊和總線類型屬性文件創建,以及總線設備的注冊主要是依據下面幾個函數來實現:
        /*總線類型注冊函數,由于可能會出錯,因此必須對返回值進行檢查*/
        int __must_check bus_register(struct bus_type *bus);
        /*總線類型釋放函數*/
        void bus_unregister(struct bus_type *bus);
        /*總線文件屬性創建函數,將相關的文件屬性添加給總線類型,同時也必須檢查返回值是否正確*/
        int __must_check bus_create_file(struct bus_type *,struct bus_attribute *);
        /*總線類型文件屬性刪除函數,將兩者之間的關聯性切斷*/
        void bus_remove_file(struct bus_type *, struct bus_attribute *);
        最后需要將總線設備添加到系統中,主要采用設備注冊函數;
        設備注冊函數:
        int __must_check device_register(struct device *dev);
        設備釋放函數:
        void device_unregister(struct device *dev);
        上一頁 1 2 下一頁

        關鍵詞: 總線設備驅動模

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 曲周县| 丹棱县| 鄄城县| 定远县| 滦南县| 城口县| 郁南县| 新竹市| 和林格尔县| 岳阳市| 精河县| 萝北县| 霞浦县| 沈丘县| 夹江县| 蒲城县| 江川县| 格尔木市| 唐山市| 镇沅| 镇宁| 德昌县| 马山县| 绥滨县| 哈巴河县| 湄潭县| 哈尔滨市| 汝南县| 报价| 六枝特区| 林甸县| 孟州市| 洛宁县| 泾阳县| 邳州市| 砀山县| 襄城县| 阳春市| 遂宁市| 玛沁县| 皮山县|