平台总线模型

原创 2017年03月05日 21:18:48

平台总线模型主要分为3个部分,1.driver 2.device 3.bus


device主要放硬件相关的东西

driver里面主要存放的比较稳定的代码

我们依然可以查看gpio_keys.c这个代码来学习


平台总线是一种虚拟的总线


driver这个结构体会通过调用platform_driver_register这个函数

platform_driver_register这个函数又会调用driver_register这个函数把这个driver放到bus中driver的一个链表里面去


device这个结构体会通过调用platform_device_register这个函数

platform_device_register这个函数会调用platform_device_add这个函数,platform_device_add这个函数又会调用device_add这个函数把device放到Bus中的device的这个链表里面去,这个注册除了把这个结构体放到这个平台里面去,还diver里面取出来跟他比较,用什么函数来跟它比较呢,总线里面有个函数.match函数。用这个函数来比较这个driver能不能支持这个device  能够支持的话就调用driver里面的probe.


device_add做了什么事情

1.把device放入bus中的device链表里面

2.device_add函数会从bus的driver链表取出每个driver,用总线的match函数判断这个driver能否支持device

3.如果能够支持的话调用这个probe函数


driver_add做了什么事情呢

1.把driver放入bus总线的driver链表

2从device链表中拿出每一个device,用总线的match函数来一一比较

3.如果能够支持,调用probe函数


注意:这只不过是这么一种机制,device和driver建立联系的机制,在probe函数里面做什么事情,由你决定,你打印一句话,注册一个字符设备什么的,都是由你决定的


driver里放比较稳定的东西,我们改的话,主要是改device这边的代码

我们来看这个gpio_keys.c这个代码

static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver);这是注册一个driver,来看看这个driver里面有什么东西


static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &gpio_keys_pm_ops,
#endif
}
};


int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type; 我们这里的总线是虚拟总线,来看一看这个结构体
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;


return driver_register(&drv->driver);
}


struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};


平台总线上有一个函数platform_match这个函数,我们来看一下这个匹配函数

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


/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;


/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;


/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
}

由此可以看出,匹配的方法,我们这里用的是下面这种,用名字匹配的方法

}


static void __exit gpio_keys_exit(void)
{
platform_driver_unregister(&gpio_keys_device_driver);
}



范例代码如下


device驱动如下

#include<linux/module.h>

#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/platform_device.h>
#include<linux/interrupt.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/serial_core.h>


static struct resource led_resource[]={
[0]={
.start = 0xe0200280,
.end = 0xe0200284,
.flags = IORESOURCE_MEM,
},


};


static void led_release(struct device * dev)
{
//我们先什么都不放,到时候可以放一些硬件相关的代码
}
/*分配/设置/注册一个platform_device*/
static struct platform_device led_dev={
.name = "myled",//名字要与driver里面的名字一样,因为match函数是根据这个来匹配的
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev=
{
.release = led_release, 
},
};


static int led_dev_init(void)
{
platform_device_register(&led_dev);
return 0;
}


static void led_dev_exit(void)
{
platform_device_unregister(&led_dev);
}


module_init(led_dev_init);
module_exit(led_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT");


driver程序如下

#include<linux/module.h>
#include<linux/init.h>
#include<linux/interrupt.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/slab.h>
#include<linux/uaccess.h>
#include<linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>




struct class *my_class;
struct cdev cdev;
dev_t devno;
static volatile unsigned long *con;
static volatile unsigned long *data;


#define LED_MAGIC 'm'
#define LED_ON _IO(LED_MAGIC,0)
#define LED_OFF _IO(LED_MAGIC,1)


static int led_open(struct inode *inode,struct file *file)
{
writel(0x00001111,con);
return 0;
}
long led_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case LED_ON:
writel(0x00,data);
break;
case LED_OFF:
writel(0x0f,data);
break;
default:
return -EINVAL;
}
return 0;
}




static struct file_operations myled_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.unlocked_ioctl =led_ioctl,
};


static int led_probe(struct platform_device *pdev)
{
//根据platform_device的资源来ioremap
struct resource *res_mem;
res_mem=platform_get_resource(pdev,IORESOURCE_MEM,0);
con=ioremap(res_mem->start,res_mem->end-res_mem->start+1);
data=con+1;




//注册字符设备驱动
cdev_init(&cdev,&myled_fops); 
alloc_chrdev_region(&devno, 0 , 1 , "myled");
cdev_add(&cdev, devno, 1);
my_class = class_create(THIS_MODULE, "led_class");
if(IS_ERR(my_class))
{
printk("Err: failed in creating class.\n");
return -1;
}
device_create(my_class, NULL, devno,NULL,"led_driver");
return 0;
}


static int led_remove(struct platform_device *dev)
{
//根据platform_device的资源来进行iounmap
iounmap(con);
iounmap(data);
//卸载字符设备驱动
device_destroy(my_class,devno);
class_destroy(my_class);


cdev_del(&cdev);
unregister_chrdev_region(devno,1);
return 0;


}
struct platform_driver key_driver={
.probe = led_probe,
.remove= led_remove,
.driver={
.name="myled",//要与device里面的名字一样。因为match函数就是根据名字匹配的
},
};


/*分配/设置/注册一个platform_driver结构体*/
static int led_drv_init(void)
{
platform_driver_register(&key_driver);
return 0;
}


static void led_drv_exit(void)
{
platform_driver_unregister(&key_driver);
}


module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT");


测试程序跟前面led的测试程序一样

linux平台总线驱动设备模型之点亮LED

上一节中,我们引入Linux input子系统的分离分层概念,发现这样的架构特别容易移植,因为有一部分是已经相对稳定,它已经把公共的部分抽象出来,不用驱动工程师再去修改,只需要添加符合输入设备的设备驱...

Linux驱动开发-13、平台总线驱动模型

平台总线驱动模型 1.概念 a) 一种虚拟总线,由内核创建 b) 一般在内核代码中已近注册了相应的平台资源,在sys/bus/platform中可以查看平台的设备和驱动   2.平台设备:(...

设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

以下内容转载于微信公众号:嵌入式企鹅圈。如有侵权,请告知删除。     学习Linux设备驱动开发的过程中自然会遇到字符设备驱动、平台设备驱动、设备驱动模型和sysfs等相关概念和技术。     ...

平台总线设备驱动模型——代码分析

节我们分析了平台总线的工作流程,这一节里我们来分析代码: 先来看设备驱动代码: #include #include #include #include #include #...

Linux平台总线驱动设备模型

转自:http://blog.csdn.net/lwj103862095/article/details/17957637 platform总线是一种虚拟的总线,相应的设备则为platform_...

Linux平台总线驱动设备模型

platform总线是一种虚拟的总线,相应的设备成为platform_device,而驱动则为platform_driver。Linux 2.6的设备驱动模型中,把I2C、RTC、LCD等都归纳为pl...

Linux设备驱动模型3——platform平台总线工作原理

以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。 四、platform平台总线工作原理1 1、何为平台总线? (1)相对于usb、pci、i2c等物理总线来说,platfo...

ok6410学习笔记(15.platform平台总线驱动模型之混杂设备驱动led)

本节知识点: 1.这里就一个知识点设备资源: 设备资源前面说过,这里就不多说了 主要说说,在platform模型中,设备资源是定义在device模块中的,而使用是在driver模块中pr...

平台总线设备模型

平台总线是内核实现的一条虚拟总线,Linux设备模型包含三个重要的元素,总线、设备和驱动,那看看平台总线又是怎样去实现的。 首先看平台总线的定义: 946 struct bus_...

Linux平台总线驱动设备模型

platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver。Linux 2.6的设备驱动模型中,把I2C、RTC、LCD等都归纳为pl...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:平台总线模型
举报原因:
原因补充:

(最多只允许输入30个字)