示例程序运行kernel版本为3.0.36,示例程序是国嵌的,修改使之在3.0.36内核版本可运行,并消除编译时的警告信息
platform设备的介绍,在ldd3中已经介绍的很详细了,没有了解过的,可以去看看第十四章设备模型这一章,,这里只简单提供一个可以运行的平台设备和平台驱动的示例程序,用做备忘!
Platform总线是kernel中的一种虚拟总线,2.6版本很多驱动都用它来实现
系统启动时已经注册好了平台总线,所以我们可以直接在平台总线上面注册平台设备和驱动。下面直接给出一个注册平台设备和平台驱动的简单示例。
平台设备:
-
#include <linux/device.h>
-
#include <linux/module.h>
-
#include <linux/kernel.h>
-
#include <linux/init.h>
-
#include <linux/string.h>
-
#include <linux/platform_device.h>
-
-
MODULE_LICENSE("Dual BSD/GPL");
-
-
//定义一个平台设备
-
static struct platform_device my_device = {
-
.name = "my_dev",
-
};
-
-
//模块初始化函数
-
static int __init my_device_init(void)
-
{
-
int ret = 0;
-
//注册设备
-
ret = platform_device_register(&my_device);
-
if (ret)
-
platform_device_put(&my_device);
-
printk("register platfrom device success!!!\n");
-
return ret;
-
}
-
-
//模块卸载函数
-
static void my_device_exit(void)
-
{
-
platform_device_unregister(&my_device);
-
printk("unregister platfrom device success!!!\n");
-
}
-
-
module_init(my_device_init);
-
module_exit(my_device_exit);
平台驱动:
-
#include <linux/device.h>
-
#include <linux/module.h>
-
#include <linux/kernel.h>
-
#include <linux/init.h>
-
#include <linux/string.h>
-
#include <linux/platform_device.h>
-
-
MODULE_LICENSE("Dual BSD/GPL");
-
-
static int my_probe(struct platform_device *dev)
-
{
-
printk("Driver found device which my driver can handle!\n");
-
return 0;
-
}
-
-
static int my_remove(struct platform_device *dev)
-
{
-
printk("Driver found device unpluged!\n");
-
return 0;
-
}
-
//定义一个平台驱动
-
static struct platform_driver my_driver = {
-
.probe = my_probe, //探测函数,当匹配到设备时调用
-
.remove = my_remove, //移除函数
-
.driver = {
-
.owner = THIS_MODULE,
-
.name = "my_dev", //驱动名
-
},
-
};
-
//模块初始化函数
-
static int __init my_driver_init(void)
-
{
-
int ret;
-
//注册平台驱动
-
ret=platform_driver_register(&my_driver);
-
if(ret){
-
printk("register platfrom driver error!!!\n");
-
return -1;
-
}
-
printk("register platfrom driver success!!!\n");
-
return 0;
-
}
-
//模块卸载函数
-
static void my_driver_exit(void)
-
{
-
platform_driver_unregister(&my_driver);
-
printk("unregister platfrom driver success!!!\n");
-
}
-
-
module_init(my_driver_init);
-
module_exit(my_driver_exit);
编译成platform_device.ko,platform_driver.ko两个模块,加载到系统,运行结果如下所示:
平台总线在哪里加载???
系统平台总线在内核初始化时已经加载,具体执行路径:kernel_init()-->do_basic_setup()-->driver_init()-->platform_bus_init();
在platform_bus_init函数里,注册了平台总线platform_bus_type和平台设备platform_bus
int __init platform_bus_init(void)
{
int error;
early_platform_cleanup();
error = device_register(&platform_bus); //注册平台总线设备
if (error)
return error;
error = bus_register(&platform_bus_type); //注册平台总线
if (error)
device_unregister(&platform_bus);
return error;
}
设备驱动如何关联到设备???
设备驱动调用platform_driver_register()注册驱动时,对平台总线上的所有设备进行遍历,调用平台总线的match函数进行匹配,匹配成功之后才调用driver的probe函数进行探测。
具体执行路径:platform_driver_register()-->driver_register()-->bus_add_driver()-->driver_attach()-->bus_for_each_dev();
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);该函数对总线上的每个设备进行遍历,并将相关的device结构和drv数据传递给__driver_attach函数。
__driver_attach函数实现如下,在该函数中对设备和驱动进行了匹配,匹配成功后继续调用驱动的probe函数
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/
if (!driver_match_device(drv, dev)) //这里进行匹配
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev); //这里调用驱动的probe函数
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
阅读(1505) | 评论(0) | 转发(0) |