天天看点

【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

【twitter】 @sky2030_

【facebook】 张昺华 zhangbinghua

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

继续阅读