Linux驱动学习——platform平台总线

来源:互联网 发布:seo蜘蛛精 编辑:程序博客网 时间:2024/05/17 23:15

linux内核为了让设备驱动具有更好的可移植性,设备驱动采用设备-总线-驱动模型。

从Linux 2.6起引入了一套新的驱动管理和注册机制,platform_device和platform_driver,Linux中大部分的设备驱动都可以使用这套机制。platform是一条虚拟的总线。设备用platform_device表示,驱动用platform_driver进行注册,Linux platform driver机制和传统的device driver机制(通过driver_register进行注册)相比,一个明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动中使用这些资源时通过platform device提供的标准结构进行申请并使用。这样提高了驱动和资源的独立性,并且具有较好的可移植性和安全性(这些标准接口是安全的)。


设备-总线-驱动模型的实现原理:

1.内核已经帮你定义好了一个虚拟总线“platform_bus_type”,也称为平台总线。

2.在这个总线上维护着两个链表,一个是存放硬件信息的dev链表,一个是存放纯软件信息的drv链表;

3.dev链表中的每一个节点的数据结构是struct platform_device,也称为平台设备,这个结构体就是用来装载硬件相关的信息

4.dev链表中的每一个节点的数据结构是struct platform_driver,也成为平台驱动,这个结构体就是用来状态对硬件操作的纯软件。

5.这两个结构体中都有一个字段name,以后用来进行匹配的!

6.每当向dev链表中添加硬件节点信息时,内核会遍历drv链表,然后取出drv链表中每一个软件节点,取出软件节点的name跟硬件节点的name通过总线提供的match进行匹配,如果一旦匹配成功,说明硬件找到了软件,内核会调用平台驱动的probe函数,然后把硬件节点的首地址传递给probe函数。如果没有匹配成功,没关系,反正以后把硬件节点添加到dev链表中了,就等待软件的到来。

7.每当向drv链表中添加软件信息时,内核会遍历dev链表,然后取出dev链表中每一个硬件节点,根据两个name进行匹配,如果一旦匹配成功,软件找到了硬件。内核会调用平台驱动的probe函数,然后把匹配成功的硬件节点的首地址传递给probe函数。

8.probe函数要完成什么样的工作,完全由驱动开发者来实现。

也就是内核仅仅帮你完成软件和硬件的分离,软件和硬件的匹配。

9.这就是内核的硬件和软件的分离思想。这种思想就是让驱动开发者以后关注的内容就是硬件信息,软件信息一旦写好,以后无需再变。

 

总结:利用内核分离思想实现设备驱动,只需关注两个结构体:

struct platform_device和struct platform_driver

 

相关结构体

struct platform_device :装载硬件相关的信息

struct platform_device {

       char*name; //名称,相当的重要!

       intid; //设备ID,如果只有一个设备,id一般为-1,如果有多个同名的设备,通过id来区分

       intnum_resources; //设备资源的个数

       structresource *res; //装载硬件资源信息,这个硬件信息在描述时,使用structresource.

       structdevice dev;//装载自己定义的硬件信息,只需将自己定义的硬件信息保存在dev.platform_data中即可

};注:platform_data的数据类型是void *

 

struct resource {//内核提供的描述硬件信息的数据结构

       unsignedlong start; //硬件资源的起始信息

       unsignedlong end;   //结束信息

       char*name;   //资源名称

       unsignedint flags; //资源的类型

};

flags:资源类型标志

IORESOURCE_MEM:内存资源

IORESOURCE_IRQ:中断,IO资源

 

具体使用:

1.分配structplatform_device对象

2.根据硬件特性初始化structplatform_device

3.调用platform_device_register(&对象)向内核平台总线的dev链表添加:

  1.将此节点添加到链表dev中

  2.内核会帮你遍历drv链表,然后进行匹配,如果匹配成功,调用platform_driver.probe函数。

4.删除硬件节点:platform_device_unregister(&对象);

 


 

struct platform_driver使用:

struct platform_driver {

 //匹配成功执行,pdev指针指向匹配成功的硬件信息

 int (*probe)(struct platform_device *pdev);

  //卸载软件或者硬件时调用

 int (*remove)(struct platform_device *pdev);

  //关机时调用

  void (*shutdown)(struct platform_device *);

  //电源管理相关,每当进入待机状态,调用次函数

  int (*suspend)(struct platform_device *, pm_mes

                              sage_tstate);

  //电源管理相关,每当系统唤醒以后,调用此函数

  int (*resume)(struct platform_device *);

  struct device_driver driver; //其中的name很重,用于匹配,必须初始化

}

1.分配structplatform_driver

2.初始化platform_driver

  .driver = {

       .name= 必须初始化,要和平台设备的name一样

   },

  .probe = //初始化,整个驱动的起始

  .remove = 相对probe,整个驱动的结束

3.probe函数的执行代表着软件和硬件是否结合!

4.调用platform_driver_register向内核注册

  1.将软件节点添加到drv链表

  2.内核遍历dev链表进行匹配,如果匹配成功,调用probe函数,然后将匹配成功的硬件节点的首地址传递给probe函数

5.probe函数做什么事情,后续由驱动开发者来实现。
0 0