1. 简介:
转自: https://blog.csdn.net/qqliyunpeng/article/details/52700331
1.1 platform 总线是虚拟总线,当使用这个虚拟总线是带来的好处主要有两点:
1.2 对platform中的设备和驱动的理解可以用如下的比喻:
总线是红娘,设备是男方,驱动是女方:
红娘负责男方和女方的撮合
男方或女方找到红娘,来登记,看有没有合适的姑娘 -- 设备或驱动的注册
红娘这个时候看看有没有合适的八字(二者的name字段) -- match 函数进行匹配,看name是不是相同
如果没有,就等着,知道匹配的了,就结婚,结完婚,男方向女方交代,我有多少存款,我的房子在哪,钱放哪等等(struct resource *resource),女方去拿存款买菜啦,买衣服了等等(匹配成功后执行 int (*probe)(struct platform_device *) 匹配成功后执行的第一个函数),当然,如果男的跟小三跑了,女方也不会继续下去的。
1.3 在 linux 系统中,设备可以是:
模块文件
平台文件 (arch/arm/mach-s3c24xx/mach-mini2440.c)
设备树文件 (arch/arm/boot/dts/)
2. 下面就介绍介绍如何使用 platform 总线:
2.1 函数原型
①设备:相关结构体是 struct platform_device
②驱动:相关结构体是 struct platform_driver
过程 | 设备 | 驱动 |
定义 | 成员.dev.release 的函数实现 | .probe .remove 的函数实现 |
初始化 | struct platform_device test_device = {...} | struct platform_driver test_driver = {...} |
注册 | platform_device_register(&test_device); | platform_driver_register(&test_driver); |
释放 | platform_device_unregister(&test_device); | platform_driver_unregister(&test_driver); |
2.2 注册和注销
2.3 为设备添加资源和数据
2.4 对platform的理解可以用如下图:
3. 例子:
3.1 对于一个普通的platform架构的程序很简单:
#include <linux/module.h>#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
static int driver_probe(struct platform_device *dev)
{
printk("platform: match ok!\n");
return 0;
}
static int driver_remove(struct platform_device *dev)
{
printk("platform: driver remove\n");
return 0;
}
static void device_release(struct device *dev)
{
printk("platform: device release\n");
}
struct platform_device test_device = {
.id = -1,
.name = "test_device1",
.dev.release = device_release,
};
struct platform_driver test_driver = {
.probe = driver_probe,
.remove = driver_remove,
.driver = {
.name = "test_device",
},
};
static int __init s5pc100_platform_init(void)
{
platform_device_register(&test_device);
platform_driver_register(&test_driver);
return 0;
}
static void __exit s5pc100_platform_exit(void)
{
platform_device_unregister(&test_device);
platform_driver_unregister(&test_driver);
}
module_init(s5pc100_platform_init);
module_exit(s5pc100_platform_exit);
Makefile 参照前边的内容,是一样的
3.2 而对于设备资源的取得例子如下:
一个设备信息:.
├── dev
│ ├── dev.c
│ └── Makefile
└── dri
├── dri.c
└── Makefile
dev.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
struct resource test_res={
.start = 11,
.end = 22,
.flags = IORESOURCE_MEM,
};
static void device_release(struct device *dev)
{
printk("platform: device release\n");
}
struct platform_device test_device = {
.id = -1,
.name = "test_device",
.dev.release = device_release,
.num_resources =1,
.resource = &test_res,
};
static int __init s5pc100_platform_init(void)
{
printk("dev init\n");
platform_device_register(&test_device);
return 0;
}
static void __exit s5pc100_platform_exit(void)
{
printk("dev exit\n");
platform_device_unregister(&test_device);
}
module_init(s5pc100_platform_init);
module_exit(s5pc100_platform_exit);
dri.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
static int driver_probe(struct platform_device *dev)
{
struct resource * res =NULL;
printk("platform: match ok!\n");
res=platform_get_resource(dev,IORESOURCE_MEM,0);
if(res == NULL)
{
printk("platform_get_resource error\n");
return -EINVAL;
}
printk("res->start:%d\n",res->start); //11
printk("res->end:%d\n",res->end); //22
printk("res->flags:%#x\n",res->flags); //0x200
printk("platform probe end\n");
return 0;
}
static int driver_remove(struct platform_device *dev)
{
printk("platform: driver remove\n");
return 0;
}
struct platform_driver test_driver = {
.probe = driver_probe,
.remove = driver_remove,
.driver = {
.name = "test_device",
},
};
static int __init s5pc100_platform_init(void)
{
printk("dri init\n");
platform_driver_register(&test_driver);
return 0;
}
static void __exit s5pc100_platform_exit(void)
{
printk("dri exit\n");
platform_driver_unregister(&test_driver);
}
module_init(s5pc100_platform_init);
module_exit(s5pc100_platform_exit);
Makefile这里也不写出来,参照前边的写法
运行结果如下:
$sudo insmod dev.ko
$ dmesg
[ 2988.851954] dev init
$ cd ../dri/
$ sudo insmod dri.ko
$ dmesg
[ 2988.851954] dev init
[ 3008.968420] dri init
[ 3008.968466] platform: match ok!
[ 3008.968467] res->start:11
[ 3008.968468] res->end:22
[ 3008.968469] res->flags:0x200
[ 3008.968469] platform probe end
$ sudo rmmod dev
$ dmesg
[ 2988.851954] dev init
[ 3008.968420] dri init
[ 3008.968466] platform: match ok!
[ 3008.968467] res->start:11
[ 3008.968468] res->end:22
[ 3008.968469] res->flags:0x200
[ 3008.968469] platform probe end
[ 3025.176478] dev exit
[ 3025.176508] platform: driver remove
[ 3025.176556] platform: device release
$ sudo rmmod dri
$ sudo rmmod dri
$ dmesg
[ 2988.851954] dev init
[ 3008.968420] dri init
[ 3008.968466] platform: match ok!
[ 3008.968467] res->start:11
[ 3008.968468] res->end:22
[ 3008.968469] res->flags:0x200
[ 3008.968469] platform probe end
[ 3025.176478] dev exit
[ 3025.176508] platform: driver remove
[ 3025.176556] platform: device release
[ 3035.936023] dri exit
3.3 多个设备信息:
结构如上边一个设备信息dev.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
struct resource test_res[]={
[0]={
.start = 11,
.end = 22,
.flags = IORESOURCE_MEM,
},
[1]={
.start = 99,
.end = 99,
.flags = IORESOURCE_IRQ,
},
[2]={
.start = 33,
.end = 44,
.flags = IORESOURCE_MEM,
},
};
static void device_release(struct device *dev)
{
printk("platform: device release\n");
}
struct platform_device test_device = {
.id = -1,
.name = "test_device",
.dev.release = device_release,
.num_resources =ARRAY_SIZE(test_res),
.resource = test_res,
};
static int __init s5pc100_platform_init(void)
{
printk("dev init\n");
platform_device_register(&test_device);
return 0;
}
static void __exit s5pc100_platform_exit(void)
{
printk("dev exit\n");
platform_device_unregister(&test_device);
}
module_init(s5pc100_platform_init);
module_exit(s5pc100_platform_exit);
dri.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
MODULE_LICENSE("Dual BSD/GPL");
static int driver_probe(struct platform_device *dev)
{
struct resource * res =NULL;
printk("platform: match ok!\n");
res=platform_get_resource(dev, IORESOURCE_MEM, 0);
if(res == NULL)
{
printk("platform_get_resource error\n");
return -EINVAL;
}
printk("res->start:%d\n",res->start); //11
printk("res->end:%d\n",res->end); //22
printk("res->flags:%#x\n",res->flags); //0x200
res=platform_get_resource(dev, IORESOURCE_MEM, 1);
if(res == NULL)
{
printk("platform_get_resource error\n");
return -EINVAL;
}
printk("res->start:%d\n",res->start); //33
printk("res->end:%d\n",res->end); //44
printk("res->flags:%#x\n",res->flags); //0x200
res=platform_get_resource(dev,IORESOURCE_IRQ,0);
if(res == NULL)
{
printk("platform_get_resource error\n");
return -EINVAL;
}
printk("res->start:%d\n",res->start); //99
printk("res->end:%d\n",res->end); //99
printk("res->flags:%#x\n",res->flags); //0x400
printk("platform probe end\n");
return 0;
}
static int driver_remove(struct platform_device *dev)
{
printk("platform: driver remove\n");
return 0;
}
struct platform_driver test_driver = {
.probe = driver_probe,
.remove = driver_remove,
.driver = {
.name = "test_device",
},
};
static int __init s5pc100_platform_init(void)
{
printk("dri init\n");
platform_driver_register(&test_driver);
return 0;
}
static void __exit s5pc100_platform_exit(void)
{
printk("dri exit\n");
platform_driver_unregister(&test_driver);
}
module_init(s5pc100_platform_init);
module_exit(s5pc100_platform_exit);
运行结果也不再打印