<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 總線設(shè)備驅(qū)動(dòng)模型總結(jié)

          總線設(shè)備驅(qū)動(dòng)模型總結(jié)

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

          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();