博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
驱动04.平台总线驱动模型——点亮LED灯
阅读量:6332 次
发布时间:2019-06-22

本文共 7257 字,大约阅读时间需要 24 分钟。

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 
2 #include
3 4 #include
5 6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 15 static struct resource myled_dev_resource[] = {16 [0] = {17 .start = 0x56000050,18 .end = 0x56000050 + 8 - 1,19 .flags = IORESOURCE_MEM,20 },21 [1] = {22 .start = 6,23 .end = 6,24 .flags = IORESOURCE_IRQ,25 }26 };27 28 29 static void myled_dev_release(struct device * dev)30 {31 }32 33 34 static struct platform_device myled_dev = {35 .name = "myled",36 .id = -1,37 .num_resources = ARRAY_SIZE(myled_dev_resource),38 .resource = myled_dev_resource,39 .dev = {40 .release = myled_dev_release,41 }42 };43 44 static int myled_dev_init(void)45 {46 platform_device_register(&myled_dev);47 return 0;48 }49 50 static void myled_dev_exit(void)51 {52 platform_device_unregister(&myled_dev);53 }54 55 module_init(myled_dev_init);56 module_exit(myled_dev_exit);57 58 MODULE_LICENSE("GPL");
myled_dev.c
1 #include 
2 #include
3 4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 19 20 21 static struct class *g_ptMyledCls; 22 static struct class_device *g_ptMyledClsDev; 23 static int g_iPin; 24 25 volatile unsigned long *gpiocon = NULL; 26 volatile unsigned long *gpiodat = NULL; 27 28 29 static int myled_open(struct inode *inode, struct file *file) 30 { 31 //printk("first_drv_open\n"); 32 /* 配置GPF4,5,6为输出 */ 33 *gpiocon &= ~(0x3<<(g_iPin*2)) ; 34 *gpiodat |= (0x1<<(g_iPin*2)) ; 35 return 0; 36 } 37 38 static ssize_t myled_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) 39 { 40 int val; 41 42 //printk("first_drv_write\n"); 43 44 copy_from_user(&val, buf, count); // copy_to_user(); 45 46 if (val == 1) 47 { 48 // 点灯 49 *gpiodat &= ~(1<
start, tRes->end - tRes->start +1); 75 gpiodat = gpiocon + 1; 76 77 tRes = platform_get_resource(dev, IORESOURCE_IRQ, 0); 78 g_iPin = tRes->start; 79 80 printk("myled_probe, found led\n"); 81 82 g_iMajor = register_chrdev(0, "myled", &myled_fops); // 注册, 告诉内核 83 g_ptMyledCls = class_create(THIS_MODULE, "myled"); 84 85 g_ptMyledClsDev = class_device_create(g_ptMyledCls, NULL, MKDEV(g_iMajor, 0), NULL, "myled"); /* /dev/xyz */ 86 return 0; 87 } 88 89 static int myled_remove(struct platform_device *dev) 90 { 91 printk("led_remove, remove led\n"); 92 93 class_device_destroy(g_ptMyledCls, MKDEV(g_iMajor, 0)); 94 class_destroy(g_ptMyledCls); 95 unregister_chrdev(g_iMajor, "myled"); 96 iounmap(gpiocon); 97 98 return 0; 99 }100 101 static struct platform_driver myled_driver = {102 .probe = myled_probe,103 .remove = myled_remove,104 .driver = {105 .name = "myled",106 },107 };108 109 static int myled_drv_init(void)110 {111 platform_driver_register(&myled_driver);112 return 0;113 }114 115 static void myled_drv_exit(void)116 {117 platform_driver_unregister(&myled_driver);118 }119 120 121 module_init(myled_drv_init);122 module_exit(myled_drv_exit);123 124 MODULE_LICENSE("GPL");
myled_drv.c
1 #include 
2 #include
3 #include
4 #include
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
\n", argv[0]);22 return 0;23 }24 25 if (strcmp(argv[1], "on") == 0)26 {27 val = 1;28 }29 else30 {31 val = 0;32 }33 34 write(fd, &val, 4);35 return 0;36 }
测试程序

编辑于2017-01-09 16:36:01

 

转载于:https://www.cnblogs.com/Lwd-linux/p/6265746.html

你可能感兴趣的文章
linux磁盘配额
查看>>
NFS文件共享服务器的搭建
查看>>
%r 和 %s 该用哪个?
查看>>
小公司职场不是“切糕”
查看>>
play工程部署到云服务器
查看>>
ListView 取消点击效果
查看>>
降级论
查看>>
wampServer连接oracle
查看>>
CentOS 6.5下编译安装新版LNMP
查看>>
Android Picasso
查看>>
top命令
查看>>
javascript的作用域
查看>>
新形势下初创B2B行业网站如何经营
查看>>
初心大陆-----python宝典 第五章之列表
查看>>
java基础学习2
查看>>
sysbench使用笔记
查看>>
有关电子商务信息的介绍
查看>>
NFC·(近距离无线通讯技术)
查看>>
多线程基础(三)NSThread基础
查看>>
PHP的学习--Traits新特性
查看>>