您的位置:首页 > 其它

驱动04.平台总线驱动模型——点亮LED灯

2017-01-09 16:37 239 查看
1 平台总线的简介

  平台总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver。总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。

  我们可以把一个驱动程序抽出来分为两部分,一部分是硬件相关的dev,另一部分则是稳定的纯软件部分driver。而总线只是一种机制,把dev和driver这两部分建立“联系”的机制。

eg:

①dev部分

  a.把device放入bus的dev链表

  b.从bus的drv链表取出每一个drv,用bus的match函数判断drv是否支持dev

  c.如果支持,将调用drv的probe函数

②drv部分

  a.把driver放入bus的drv链表

  b.从bus的dev链表取出每一个dev,用bus的match函数判断dev是否支持drv

  c.如果支持,将调用drv的probe函数

2 linux平台总线的代码分析

struct bus_type platform_bus_type = {
.name        = "platform",
.dev_attrs    = platform_dev_attrs,
.match        = platform_match,  //dev和drv匹配时调用的函数
.uevent        = platform_uevent,
.suspend    = platform_suspend,
.suspend_late    = platform_suspend_late,
.resume_early    = platform_resume_early,
.resume        = platform_resume,
};


static int platform_match(struct device * dev, struct device_driver * drv)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);

return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);//当dev的设备名与drv的名字相同时,则匹配成功
}


platform_device结构体的定义


struct platform_device {
const char    * name;
u32        id;
struct device    dev;
u32        num_resources;//资源数目
struct resource    * resource;//设备信息,使用platform_get_resource函数来获取资源信息
};


注册平台设备platform_device_register,实际上是加入到bus的dev链表中

1 int platform_device_register(struct platform_device * pdev)
2 {
3     device_initialize(&pdev->dev);//初始化platform_device的device成员
4     return platform_device_add(pdev);//实际上是调用device_add函数
5 }


同样的,也有platform_driver结构体的定义

1 struct platform_driver {
2     int (*probe)(struct platform_device *);
3     int (*remove)(struct platform_device *);
4     void (*shutdown)(struct platform_device *);
5     int (*suspend)(struct platform_device *, pm_message_t state);
6     int (*suspend_late)(struct platform_device *, pm_message_t state);
7     int (*resume_early)(struct platform_device *);
8     int (*resume)(struct platform_device *);
9     struct device_driver driver;
10 }
//device_driver的定义:


1 struct device_driver {
2     const char        * name;
3     struct bus_type        * bus;
4
5     struct kobject        kobj;
6     struct klist        klist_devices;
7     struct klist_node    knode_bus;
8
9     struct module        * owner;
10     const char         * mod_name;    /* used for built-in modules */
11     struct module_kobject    * mkobj;
12
13     int    (*probe)    (struct device * dev);
14     int    (*remove)    (struct device * dev);
15     void    (*shutdown)    (struct device * dev);
16     int    (*suspend)    (struct device * dev, pm_message_t state);
17     int    (*resume)    (struct device * dev);
18 };


注册device_driver结构体:

1 int driver_register(struct device_driver * drv)
2 {
3     if ((drv->bus->probe && drv->probe) ||
4         (drv->bus->remove && drv->remove) ||
5         (drv->bus->shutdown && drv->shutdown)) {
6         printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
7     }
8     klist_init(&drv->klist_devices, NULL, NULL);
9     return bus_add_driver(drv);
10 }


3 写代码

3.1框架

(1)分配、设置、注册一个platform_device/platform_driver结构体

(2)按照led.c的框架来构建

3.2 源代码

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5
6 /* firstdrvtest on
7   * firstdrvtest off
8   */
9 int main(int argc, char **argv)
10 {
11     int fd;
12     int val = 1;
13     fd = open("/dev/myled", O_RDWR);
14     if (fd < 0)
15     {
16         printf("can't open!\n");
17     }
18     if (argc != 2)
19     {
20         printf("Usage :\n");
21         printf("%s <on|off>\n", argv[0]);
22         return 0;
23     }
24
25     if (strcmp(argv[1], "on") == 0)
26     {
27         val  = 1;
28     }
29     else
30     {
31         val = 0;
32     }
33
34     write(fd, &val, 4);
35     return 0;
36 }


测试程序
编辑于2017-01-09 16:36:01
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: