支持驱动最好的linux软件,Linux平台设备和驱动
一 platform總線
一個現實的linux設備驅動通常需要掛接在一種總線上,對于本身依附于PCI,USB,IIC,SPI等的設備而言,這自然不是問題,但是在嵌入式系統里面,SOC系統中集成的獨立的外設控制器,掛接在SOC內存空間的外設等確不依附于此類總線。基于這一背景,linux發明了一種虛擬的總線,稱為platform總線,相應的設備稱為platform_device,而驅動成為platform_driver.Platform總線是linux2.6內核加的一種虛擬總線。
Linux platform driver機制和傳統的device driver 機制(通過driver_register函數進行注冊)相比,一個十分明顯的優勢在于platform機制將設備本身的資源注冊進內核,由內核統一管理,在驅動程序中使用這些資源時通過platform device提供的標準接口進行申請并使用。這樣提高了驅動和資源管理的獨立性,并且擁有較好的可移植性和安全性(這些標準接口是安全的)。
二 平臺設備的驅動軟件設計流程
三 平臺設備
3.1 用于描述平臺設備的數據結構是platform_device, 在”linux/platform_device.h”文件中定義,程序清單如下所示:
struct platform_device{
const char? ? ? *name;? ? ? ? ? ?//設備名字
int? ? ? ? ? ? ?id;? ? ? ? ? ? ?//設備ID
struct device? ?dev;? ? ? ? ? ? //設備的device數據結構
u32? ? ? ? ? ? ?num_resources;? //資源的個數
struct resource *resource;? ? ? //設備的資源
const struct platform_device_id? *id_entry;//設備ID入口
struct pdev_archdata archdata;? ?//體系結構相關的數據
};
3.2 分配platform_device結構
注冊一個platform_device之前,必須先定義或者通過platform_device_alloc()函數為設備分配一個platform_device結構。原型如下:
struct platform_device *platform_device_alloc(const char *name,int id);
3.3添加資源
通過platform_device_alloc()申請得到的platform_device結構,必須添加相關資源和私有數據才能注冊。添加資源的函數是platform_device_add_resources:
int platform_device_add_resources(struct platform_device *pdev,const struct resource *res unsigned int num);
添加私有數據的函數是platform_device_add_data:
int platform_device_add_data(struct platform_device *pdev,const void *data,size_t size)
3.4 注冊和注銷platform_device
申請到platform_device結構后,可以通過platform_device_register()往系統進行注冊。原型如下:
int platform_device_register(struct platform_device *pdev);
上述函數只能注冊一個platform_device,如果有多個platform_device,則可以用platform_add_devcies()一次性完成注冊,原型如下:
int platform_add_devices(struct platform_device? *devs,int num);
通過platform_device_unregister()可以注銷系統的plat_device.原型如下:
void platform_unresigner(struct platform_device *pdev);
如果已經定義了設備的資源和私有數據,可以用 platform_device_register_resndata()一次
性完成數據結構申請、資源和私有數據添加以及設備注冊:
struct platform_device *__init_or_module platform_device_register_resndata(
struct device *parent,
const char *name, int id,
const struct resource *res, unsigned int num,
const void *data, size_t size);
platform_device_register_simple()函數是 platform_device_register_resndata()函數的簡化版,
可以一步實現分配和注冊設備操作, platform_device_register_simple()函數原型如下:
static inline struct platform_device *platform_device_register_simple(
const char *name, int id,
const struct resource *res, unsigned int num);
實際上就是: platform_device_register_resndata(NULL, name, id, res, num, NULL, 0)。在\Linux/platform_device.h/文件還提供了更多的 platform_device 相關的操作接口函數,
在有必要的時候可以查看并使用。
3.5向系統添加平臺設備的流程
向系統添加一個平臺設備,可以通過兩種方式完成:
? 方式 1:定義資源,然后定義 platform_device 結構并初始化;最后注冊;
? 方式 2:定義資源,然后動態分配一個 platform_device 結構,接著往結構添加資源
信息,最后注冊。
如下圖所示:
四 平臺驅動
4.1platform_driver
platform_driver 是 device_driver 的封裝,提供了驅動的 probe 和 remove 方法,也提供了
與電源管理相關的 shutdown 和 suspend 等方法
struct platform_driver {
int (*probe)(struct platform_device *);? ? ?/* probe 方法 */
int (*remove)(struct platform_device *);? ? /* remove 方法 */
void (*shutdown)(struct platform_device *); /* shutdown 方法 */
int (*suspend)(struct platform_device *, pm_message_t state); /* suspend 方法 */
int (*resume)(struct platform_device *);? ? /* resume 方法 */
struct device_driver driver;? ? ? ? ? ? ? ? ?/* 設備驅動 */
const struct platform_device_id *id_table;? /* 設備的 ID 表 */
};
Platform_driver 有 5 個方法:
? probe成員指向驅動的探測代碼,在 probe方法中獲取設備的資源信息并進行處理,
如進行物理地址到虛擬地址的 remap,或者申請中斷等操作,與模塊的初始化代碼
不同;
? remove 成員指向驅動的移除代碼,進行一些資源釋放和清理工作,如取消物理地
址與虛擬地址的映射關系,或者釋放中斷號等,與模塊的退出代碼不同;
? shutdown 成員指向設備被關閉時的實現代碼;
? suspend 成員執行設備掛起時候的處理代碼;
? resume 成員執行設備從掛起中恢復的處理代碼
4.2注冊和注銷平臺設備
注冊和注銷 platform_driver 的函數分別是 platform_driver_register()和 platform_driver
_unregister(), 函數原型分別如下:
int platform_driver_register(struct platform_driver *drv);
void platform_driver_unregister(struct platform_driver *drv);
另外, platform_driver_probe()函數也能完成設備注冊, 原型如下:
int platform_driver_probe(struct platform_driver *driver, int (*probe)(struct platform_device *));
如果已經明確知道一個設備不支持熱插拔,可以在__init 斷代碼中調用 platform_driver
_probe()函數,以減少運行時對內存的消耗。如下程序清單所示代碼是
int __init init_module(void)
{
int retval;
ne_add_devices();
retval = platform_driver_probe(&ne_driver, ne_drv_probe);
if (retval) {
if (io[0] == 0)
printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
" value(s) for ISA cards.\n");
ne_loop_rm_unreg(1);
return retval;
}
/* Unregister unused platform_devices. */
ne_loop_rm_unreg(0);
return retval;
}
注意:在設備驅動模型中已經提到,bus 根據驅動和設備的名稱尋找匹配的設備和驅動,
因此注冊驅動必須保證 platform_driver 的 driver.name 字段必須和 platform_device 的 name 相
同, 否則無法將驅動和設備進行綁定而注冊失敗。
閱讀(1871) | 評論(0) | 轉發(0) |
總結
以上是生活随笔為你收集整理的支持驱动最好的linux软件,Linux平台设备和驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux磁盘混乱,Linux磁盘设备文
- 下一篇: linux可以装在硬盘吗,在硬盘上安装L