Chinaunix首页 | 论坛 | 博客
  • 博客访问: 470488
  • 博文数量: 65
  • 博客积分: 573
  • 博客等级: 中士
  • 技术积分: 693
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 17:16
文章分类

全部博文(65)

文章存档

2015年(12)

2014年(9)

2013年(22)

2012年(7)

2011年(15)

分类: LINUX

2014-09-17 17:23:28

示例程序运行kernel版本为3.0.36,示例程序是国嵌的,修改使之在3.0.36内核版本可运行,并消除编译时的警告信息
platform设备的介绍,在ldd3中已经介绍的很详细了,没有了解过的,可以去看看第十四章设备模型这一章,,这里只简单提供一个可以运行的平台设备和平台驱动的示例程序,用做备忘!
Platform总线是kernel中的一种虚拟总线,2.6版本很多驱动都用它来实现

系统启动时已经注册好了平台总线,所以我们可以直接在平台总线上面注册平台设备和驱动。下面直接给出一个注册平台设备和平台驱动的简单示例。

平台设备:

platform_device.c

  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/string.h>
  6. #include <linux/platform_device.h>

  7. MODULE_LICENSE("Dual BSD/GPL");

  8. //定义一个平台设备
  9. static struct platform_device my_device = {
  10.     .name    = "my_dev",
  11. };

  12. //模块初始化函数
  13. static int __init my_device_init(void)
  14. {
  15.     int ret = 0;
  16.     //注册设备
  17.     ret = platform_device_register(&my_device);
  18.     if (ret)
  19.      platform_device_put(&my_device);
  20.     printk("register platfrom device success!!!\n");
  21.     return ret;    
  22. }

  23. //模块卸载函数
  24. static void my_device_exit(void)
  25. {
  26.     platform_device_unregister(&my_device);
  27.     printk("unregister platfrom device success!!!\n");
  28. }

  29. module_init(my_device_init);
  30. module_exit(my_device_exit);

平台驱动:

platform_driver.c

  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/string.h>
  6. #include <linux/platform_device.h>

  7. MODULE_LICENSE("Dual BSD/GPL");

  8. static int my_probe(struct platform_device *dev)
  9. {
  10.     printk("Driver found device which my driver can handle!\n");
  11.     return 0;
  12. }

  13. static int my_remove(struct platform_device *dev)
  14. {
  15.     printk("Driver found device unpluged!\n");
  16.     return 0;
  17. }
  18. //定义一个平台驱动
  19. static struct platform_driver my_driver = {
  20.     .probe        = my_probe, //探测函数,当匹配到设备时调用
  21.     .remove        = my_remove, //移除函数
  22.     .driver        = {
  23.         .owner    = THIS_MODULE,
  24.         .name    = "my_dev", //驱动名
  25.     },
  26. };
  27. //模块初始化函数
  28. static int __init my_driver_init(void)
  29. {
  30.     int ret;
  31.     //注册平台驱动
  32.     ret=platform_driver_register(&my_driver);
  33.     if(ret){
  34.         printk("register platfrom driver error!!!\n");
  35.         return -1;
  36.     }
  37.     printk("register platfrom driver success!!!\n");
  38.     return 0;
  39. }
  40. //模块卸载函数
  41. static void my_driver_exit(void)
  42. {
  43.     platform_driver_unregister(&my_driver);
  44.     printk("unregister platfrom driver success!!!\n");
  45. }

  46. module_init(my_driver_init);
  47. 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;
}



阅读(1485) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~