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

          新聞中心

          platform總線

          作者: 時(shí)間:2016-12-14 來(lái)源:網(wǎng)絡(luò) 收藏
          platform總線實(shí)際上并不對(duì)應(yīng)任何硬件上的總線,有時(shí)又稱為偽總線。由于設(shè)備模型中的驅(qū)動(dòng)和設(shè)備關(guān)聯(lián)機(jī)制必須要有一條總線才能發(fā)揮作用,對(duì)于那些沒(méi)有連接在實(shí)際總線上的設(shè)備,如果想使用這種機(jī)制,就需要將它連接在一條假想的總線上。platform總線就可以起到這個(gè)作用,通常,platform總線上的設(shè)備都是直接與CPU相連的底層設(shè)備。
          使用platform總線的好處是可以將驅(qū)動(dòng)與設(shè)備分離,驅(qū)動(dòng)所需的平臺(tái)相關(guān)數(shù)據(jù)則在定義設(shè)備時(shí)提供,使驅(qū)動(dòng)具有更大的跨平臺(tái)通用性。
          platform總線的相關(guān)定義和聲明在頭文件中。
          1.platform總線基本特征
          struct bus_type platform_bus_type = {
          .name = "platform",
          .match = platform_match,
          .uevent = platform_uevent,
          ......
          }
          匹配操作是platform_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);
          if(pdrv->id_table)
          return platform_match_id(pdrv->id_table,pdev)!=NULL;
          return (strcmp(pdev->name,drv->name)==0);
          }
          其中調(diào)用的platform_match_id函數(shù)定義如下:
          static const struct platform_device_id *platform_match_id(
          struct platform_device_id *id, struct platform_device *pdev)
          {
          while(id->name[0]){
          if(strcmp(pdev->name, id->name) == 0){ pdev->id_entry=id; return id; }
          id++;
          }
          return NULL;
          }
          顯然在匹配時(shí),先將設(shè)備的名稱與驅(qū)動(dòng)的id_table成員數(shù)組中列舉的名稱逐一比較,若相同則匹配成功,否則再將設(shè)備的名字與驅(qū)動(dòng)的名字比較,若相同則匹配成功。
          platform總線的用戶態(tài)事件鉤子函數(shù)是platform_uevent,定義如下:
          static int platform_uevent(struct device *dev, struct kobj_uevent_env *env){
          struct platform_device *pdev = to_platform_device(dev);
          add_uevent_var(env,"MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
          return 0;
          }
          也就是說(shuō),platform總線上的設(shè)備發(fā)送用戶態(tài)事件時(shí),會(huì)增加一個(gè)MODALIAS環(huán)境變量。
          2.platform設(shè)備
          struct platform_device{
          const char *name;//設(shè)備名稱
          int id;//設(shè)備編號(hào),-1表示只有一個(gè)
          struct device dev;//內(nèi)嵌的設(shè)備對(duì)象
          u32 num_resources;//資源數(shù)組中的元素的個(gè)數(shù)
          struct resource *resource;//指向描述資源的數(shù)組
          struct platform_device_id *id_entry;//保存與驅(qū)動(dòng)匹配后的ID
          }
          設(shè)備的名稱最終會(huì)被設(shè)為name.id,其中id是設(shè)備的編號(hào)。如果id的賦值為-1,表示設(shè)備的個(gè)數(shù)只可能是1個(gè),這時(shí)設(shè)備的名字為name.
          num_resources和resource用于描述設(shè)備需要的全部資源,即端口號(hào),IO內(nèi)存、中斷號(hào)等,內(nèi)存將它們統(tǒng)稱為資源。
          struct resource{
          resource_size_t start;//資源區(qū)域的起始值
          resource_size_t end;//資源區(qū)域的結(jié)束值
          const char *name;//申請(qǐng)資源的設(shè)備名稱
          unsigned long flags;//資源的標(biāo)志
          struct resource *parent,*sibling,*child;//樹(shù)指針
          }
          每個(gè)struct resource類型的數(shù)據(jù)描述資源的一段區(qū)域,同一類型的所有資源以樹(shù)的形式組織在一起。資源的標(biāo)志包含了資源類型的說(shuō)明,常用類型如下:
          * IORESOURCE_IO :端口號(hào)資源
          * IORESOURCE_MEM :IO內(nèi)存資源
          * IORESOURCE_IRQ :中斷號(hào)資源
          * IORESOURCE_DMA :DMA資源
          平臺(tái)相關(guān)的其他數(shù)據(jù)則放在platform設(shè)備的dev成員的platform_data指針?biāo)赶虻膬?nèi)存中,。
          下面是platform設(shè)備的注冊(cè)和注銷函數(shù)的原型:
          int platform_device_register(struct platform_device *pdev);//注冊(cè)
          void platform_device_unregister(struct platform_device *pdev);//注銷
          注冊(cè)platform設(shè)備時(shí),首先向platform總線注冊(cè)相應(yīng)的設(shè)備,然后將設(shè)備的端口號(hào)和IO內(nèi)存資源添加到系統(tǒng)的資源樹(shù)種,注銷platform設(shè)備則是相反的操作。
          通常一個(gè)系統(tǒng)中的platform設(shè)備的個(gè)數(shù)和類型總是固定的,因此可以把它們的地址放在一個(gè)數(shù)組中,然后用下面的接口函數(shù)同時(shí)注冊(cè):
          int platform_add_devices(struct platform_device **devs, int num);
          3.platform驅(qū)動(dòng)
          struct platform_driver{
          int (*probe)(struct platform_device *pdev)
          int (*remove)(struct platform_device *pdev);
          struct device_driver driver;//內(nèi)嵌的驅(qū)動(dòng)對(duì)象
          struct platform_device_id *id_table;//用于匹配的ID數(shù)組
          .......
          }
          在platform驅(qū)動(dòng)的成員driver的各種操作函數(shù)中,實(shí)際上直接回調(diào)了platform驅(qū)動(dòng)的各種操作,只是將參數(shù)的類型轉(zhuǎn)換了下。因?yàn)閜latform總線本身沒(méi)有probe和remove操作,所以當(dāng)platform驅(qū)動(dòng)注冊(cè)時(shí),若platform總線上已經(jīng)注冊(cè)了匹配的設(shè)備,就會(huì)調(diào)用驅(qū)動(dòng)的probe方法。
          platform設(shè)備通常先于platform驅(qū)動(dòng)而加載,這樣探測(cè)操作就會(huì)只發(fā)生在模塊的加載過(guò)程中,從而可以安全的放入初始化數(shù)據(jù)段,以節(jié)約內(nèi)存。
          注冊(cè)和注銷platform驅(qū)動(dòng)的接口函數(shù)如下:
          int platform_driver_register(struct platform_driver *drv);
          void platform_driver_unregister(struct platform_driver *drv);
          在platform驅(qū)動(dòng)的probe函數(shù)中,可以用下面這個(gè)函數(shù)獲取設(shè)備的各種資源:
          struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned num);
          *dev指向要獲取資源的platform設(shè)備。
          *type資源的類型
          *num:資源的索引,表示要獲得設(shè)備的資源數(shù)組中第幾個(gè)此類型的資源,索引從0開(kāi)始編號(hào)。
          獲取中斷號(hào)的接口函數(shù):
          int platform_get_irq(struct platform_device *dev, unsigned int num);


          關(guān)鍵詞: platform總線偽總

          評(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); })();