天天看點

【Linux進階驅動】linux裝置驅動模型之平台裝置驅動機制【轉】

1.實作子產品加載函數

  a.申請主裝置号

    register_chrdev(major,name,file_operations);

  b.建立字元裝置cdev,注冊字元裝置

    cdev_alloc cdev_init cdev_add 

  c.建立裝置檔案

    class_create device_create

  d.注冊中斷

    ret =request_irq(中斷号,...,...,...,...);

  e.映射

    虛拟位址=ioremap(實體位址,大小)

  f.初始化(初始化等待隊列頭,初始化tasklet,初始化工作隊列)

  ...

2.實作子產品解除安裝函數

3.建構file_operations結構體變量

4.實作操作硬體的方法

  xxx_open xxx_write xxx_read

    為了提高驅動的可移植性,減少驅動開發周期,最好将跟硬體/平台相關的東西分離出來,以便增強驅動的可移植性

    中斷号,實體位址----->歸為裝置資源

    最好将裝置資源與裝置驅動分離開來

                       平台裝置驅動機制

platform_device                             platform_driver

裝置資源(裝置)           <------>            裝置驅動

    裝置總線驅動模型:以對象的思想來實作的

    每一個裝置對應唯一的一個驅動

    每個驅動則可能服務多個裝置

    系統中有很多總線:1)實際的實體總線(如:i2c總線,usb總線,SDIO總線,SPI總線...)

                     2)虛拟總線(隻有一條:平台總線)

/*1.在系統用來表示一個裝置*/

struct device {

 struct device_driver *driver;  //裝置驅動

 struct bus_type *bus;     //所屬總線

 struct device  *parent;   //父裝置

 dev_t   devt;     //裝置号

 void  *platform_data;    //私有資料

 ....

}

/*2.在系統中用來表示裝置驅動*/

struct device_driver {

 const char  *name;   //驅動名字

 struct bus_type  *bus;  //所屬總線

 struct module  *owner;  //擁有者

 int (*probe) (struct device *dev); //probe函數

/*3.在系統中用來表示總線*/

struct bus_type {

 const char  *name;   //總線名字

 /*mach函數,比對函數,每條總線裡面都會有自己的

  *mach,但不同總線的mach的比對方法可能會不同

  */

 int (*match)(struct device *dev, struct device_driver *drv);  

 /*當裝置與驅動比對成功的時候,便會調用probe函數

  *不過,一般總線中不會實作probe函數,在比對成功

  *的時候,會直接調用裝置驅動中的probe函數

 int (*probe)(struct device *dev);

 int (*remove)(struct device *dev);

/*1.總線注冊*/

int bus_register(struct bus_type *bus)

void bus_unregister(struct bus_type *bus)

/*2.裝置注冊*/

int device_register(struct device *dev)

void device_unregister(struct device *dev)

/*3.裝置驅動注冊*/

int driver_register(struct device_driver *drv)

void driver_unregister(struct device_driver *drv)

借助于裝置總線驅動模型,虛拟出一條總線,用來實作裝置資源與裝置驅動的比對

===============================================

平台裝置驅動機制采用了:分離的思想,對象的思想

                       分離的思想:裝置資源與裝置驅動分離開

/*1.平台裝置結構體*/

struct platform_device {

 const char * name;     //名字

 int  id;

 struct device dev;    //裝置結構體

 u32  num_resources;    //資源數量

 struct resource * resource;      //裝置資源

 const struct platform_device_id *id_entry;

 /* arch specific additions */

 struct pdev_archdata archdata;

};

/*2.平台驅動結構體*/

struct platform_driver {

 int (*probe)(struct platform_device *);  //probe函數

 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;

/*3.虛拟總線:平台總線結構體*/

struct bus_type platform_bus_type = {

 .name  = "platform",   //總線名字

 .dev_attrs = platform_dev_attrs,

 .match  = platform_match,  //比對函數

 .uevent  = platform_uevent,

 .pm   = &platform_dev_pm_ops,

/*4.資源結構體*/

struct resource {

 resource_size_t start;   //起始

 resource_size_t end;   //結束

 const char *name;    //名字

 unsigned long flags;   //标号

 struct resource *parent, *sibling, *child;

//平台裝置驅動機制中如何來實作裝置與驅動的比對

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);

 /* match against the id table first :可能支援多個裝置*/

 if (pdrv->id_table)

  return platform_match_id(pdrv->id_table, pdev) != NULL;

 /*平台裝置裡面的名字,與裝置驅動裡面的名字比對*/

 return (strcmp(pdev->name, drv->name) == 0);

/*核心啟動時的第一個C語言入口函數*/

start_kernel     //init/main.c

     rest_init

     /*建立一個核心線程*/

     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);  

     kernel_init

          do_basic_setup   //init/main.c

           driver_init

            platform_bus_init

         /*1.注冊平台總線*/

         bus_register(&platform_bus_type);

/*1.注冊平台裝置*/

int platform_device_register(struct platform_device *pdev)

void platform_device_unregister(struct platform_device *pdev)

/*2.注冊平台驅動*/

int platform_driver_register(struct platform_driver *drv)

void platform_driver_unregister(struct platform_driver *drv)

/*3.擷取平台資源*/

platform_get_resource(struct platform_device * dev, unsigned int type, unsigned int num)

【Linux進階驅動】linux裝置驅動模型之平台裝置驅動機制【轉】
【Linux進階驅動】linux裝置驅動模型之平台裝置驅動機制【轉】

@成鵬緻遠([email protected]

本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/5066557.html,如需轉載請自行聯系原作者

繼續閱讀