linux驱动(九)platform驱动模型详解,以及基于platform驱动模型的led驱动

参考:

http://blog.csdn.net/qq_28992301/article/details/52385518

http://blog.csdn.net/zoe6553/article/details/6372445

http://blog.chinaunix.net/uid-25014876-id-111745.html

1:什么是platform总线?
platform总线是区别于实体总线USB、 I2C、SPI 、PIC总线的虚拟总线,一些usb设备选址的话需要通过USB总线来进行寻址,

而有些类似于SoC内部外设如led 看门狗 定时器是直接通过内存的寻址空间来进行寻址的,cpu与这些设备通信是不需要总线的,2.6内核以后要

对所有设备进行统一管理,通过kset、kobject来建立层次关系,对这些直接通过内存寻址的设备虚拟了一种总线即platform总线,在硬件上

实际是没有这个总线;platform内核纯软件的总线,所有的直接通过内存寻址的设备都映射到这条总线上;

2:platform总线的优点

  a:可以通过platform总线,可以遍历所有的platform总线设备;platform本质其实也是kset、kobject,具有kobject的特性

  b:实现设备与驱动的分离,通过platform总线,设备与驱动是分开注册的,通过platform总线的probe来随时检测与设备匹配的驱动,如匹配上即进行这个设备的驱动注册;

  c:由于上面这个优势,一个驱动可以供同类的几个设备使用;

3:platform总线以及platform总线设备驱动的实现流程

  a:platform总线注册

  b:platform_device注册

  c:platform_driver注册

  d:设备与驱动的匹配

  e:驱动的注册

platform总线的工作流程如下图:

------------------------------------------------------------------------------------------------------------------------------------------------------------------

1:根据上面的流程我们来分析一下具体代码:
  platform总线的注册:platform的注册是linux内核工程师已经设注册好的;重点看一下.match = platform_match函数;platform_driver和platform_device就是通过这个函数

来匹配的

1 struct bus_type platform_bus_type = {
2     .name        = "platform",
3     .dev_attrs    = platform_dev_attrs,
4     .match        = platform_match,
5     .uevent        = platform_uevent,
6     .pm        = &platform_dev_pm_ops,
7 };
 1 int __init platform_bus_init(void)
 2 {
 3     int error;
 4
 5     early_platform_cleanup();
 6
 7     error = device_register(&platform_bus);
 8     if (error)
 9         return error;
10     error =  bus_register(&platform_bus_type);
11     if (error)
12         device_unregister(&platform_bus);
13     return error;
14 }
 1 static int platform_match(struct device *dev, struct device_driver *drv)
 2 {
 3     struct platform_device *pdev = to_platform_device(dev);
 4     struct platform_driver *pdrv = to_platform_driver(drv);
 5
 6     /* match against the id table first */
 7     if (pdrv->id_table)
 8         return platform_match_id(pdrv->id_table, pdev) != NULL;
 9
10     /* fall-back to driver name match */
11     return (strcmp(pdev->name, drv->name) == 0);
12 }

由platform_match_id函数来进行匹配的,如果id_table不为空,则通过id_table来pdev_name匹配,如果为空,则drv->name与pdev->name来进行匹配,

匹配上以后再执行probe函数,这个函数即注册这个设备的驱动;

---------------------------------------------------------------------------------------------------------------------------------------------------------------

2:platform_device的注册

在arch/arm/mach-s3c2440/mach-mini2440.c文件中

这里注意.name、.dev.platform_data 这两个变量

platform_driver和platform_device就是通过name来匹配的。name一致则匹配上;

.dev.platform_data这个元素是中的内容是name、gpio flag def_trigger四个元素

 1 static struct platform_device mini2440_led1 = {
 2     .name        = "s3c24xx_led",      
 3     .id        = 1,
 4     .dev        = {
 5         .platform_data    = &mini2440_led1_pdata,
 6     },
 7 };
 8
 9 static struct platform_device mini2440_led2 = {
10     .name        = "s3c24xx_led",
11     .id        = 2,
12     .dev        = {
13         .platform_data    = &mini2440_led2_pdata,
14     },
15 };

设置好platform_device 结构体以后就可以注册platform_device设备了,把我们设置好的platform_device结构体放到mini2440这个结构体数组指针中;

 1 static struct platform_device *mini2440_devices[] __initdata = {
 2     &s3c_device_ohci,
 3     &s3c_device_wdt,
 4     &s3c_device_i2c0,
 5     &s3c_device_rtc,
 6     &s3c_device_usbgadget,
 7     &mini2440_device_eth,
 8     &mini2440_led1,
 9     &mini2440_led2,
10     &mini2440_led3,
11     &mini2440_led4,
12     &mini2440_button_device,
13     &s3c_device_nand,
14     &s3c_device_sdi,
15     &s3c_device_iis,
16     &mini2440_audio,
17 };

在arch/arm/mach-s3c2440/mach-mini2440.c

mini2440_init 函数下

  platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

使用的platform_add_devices这个函数把mini2440的所有设备注册到内核中;内核会自动查找platform_device链表以及platform_driver链表,当match以后字自动执行platform_driver的probe函数;

在整理一下platform_device的注册过程:

1:设置好platform_device结构体(对于led驱动来说关键是name、dev->platform_data两个元素)

2:初始化好dev->platform_data结构体,这里主要涉及到led驱动所要用到的gpio,

这里我们可以看到linux内核platform驱动框架的设计思想:首先设备和驱动是分开的,同类设备有共性的部分,不同的部分,不同的部分在初始化的即被设置好;共性的部分内核工程师以及设置好;然后在通过一个匹配函数如果内核链表的设备与驱动链表的驱动匹配,则会自动安装驱动,否则不会安装驱动;

3:把设置好的platform_device设备加入到mini2440_devices中

4:在mini2440_device初始化的时候通过platform_add_devices函数把platform设备注册上去;注册以后再/sys/bus/platform/devices目录下会看到dev.name的文件夹

---------------------------------------------------------------------------------------------------------------------------------------------------------

3: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 (*resume)(struct platform_device *);
7     struct device_driver driver;
8     const struct platform_device_id *id_table;
9 };
 1 static struct platform_driver s3c24xx_led_driver = {
 2     .probe        = s3c24xx_led_probe,
 3     .remove        = s3c24xx_led_remove,
 4     .driver        = {
 5         .name        = "s3c24xx_led",
 6         .owner        = THIS_MODULE,
 7     },
 8 };
 9
10 static int __init s3c24xx_led_init(void)
11 {
12     return platform_driver_register(&s3c24xx_led_driver);
13 }

设置好platform_driver  结构体,使用platform_driver_register注册即可,这里关键的是probe、remove、driver.name 三个变量;

platform_driver_register  使用这个函数注册以后再 /sys/bus/platform/drivers目录下会看到 dev.name的文件夹

内核会自动检测匹配以后会自动执行probe函数;

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面分析一下probe函数

probe函数应该做什么?

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

代码实战:

时间: 2024-12-26 12:48:58

linux驱动(九)platform驱动模型详解,以及基于platform驱动模型的led驱动的相关文章

日志模型详解

日志模型详解 NET Core的日志模型主要由三个核心对象构成,它们分别是Logger.LoggerProvider和LoggerFactory.总的来说,LoggerProvider提供一个具体的Logger对象将格式化的日志消息写入相应的目的地,但是我们在编程过程中使用的Logger对象则由LoggerFactory创建,这个Logger利用注册到LoggerFactory的LoggerProvider来提供真正具有日志写入功能的Logger,并委托后者来记录日志. 目录一.Logger  

《Linux设备驱动开发详解:基于最新的Linux 4.0内核》china-pub预售

<Linux设备驱动开发详解:基于最新的Linux 4.0内核>china-pub今日上线进入预售阶段: http://product.china-pub.com/4733972 推荐序一 技术日新月异,产业斗转星移,滚滚红尘,消逝的事物太多,新事物的诞生也更迅猛.众多新生事物如灿烂烟花,转瞬即逝.当我们仰望星空时,在浩如烟海的专业名词中寻找,赫然发现,Linux的生命力之旺盛顽强,斗志之昂扬雄壮,令人称奇.它正以摧枯拉朽之势迅速占领包括服务器.云计算.消费电子.工业控制.仪器仪表.导航娱乐等

《Linux设备驱动开发详解:基于最新的Linux 4.0内核》china-pub 预售

<Linux设备驱动开发详解:基于最新的Linux 4.0内核>china-pub今日上线进入预售阶段: http://product.china-pub.com/4733972 推荐序一 技术日新月异,产业斗转星移,滚滚红尘,消逝的事物太多,新事物的诞生也更迅猛.众多新生事物如灿烂烟花,转瞬即逝.当我们仰望星空时,在浩如烟海的专业名词中寻找,赫然发现,Linux的生命力之旺盛顽强,斗志之昂扬雄壮,令人称奇.它正以摧枯拉朽之势迅速占领包括服务器.云计算.消费电子.工业控制.仪器仪表.导航娱乐等

《Linux设备驱动开发详解(基于最新4.0内核)》前言

Linux从未停歇脚步.Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核.做技术,从来没有终南捷径,拼的就是坐冷板凳的傻劲. 这是一个连阅读都被碎片化的时代,在这样一个时代,人们趋向于激进.浮躁.内心的不安宁使我们极难静下心来研究什么.我见过许许多多的Linux工程师,他们的简历书写着"精通"Linux内核,有多年的工作经验,而他们的"精通"却只是把某个寄存器从0改成1,从1改成0的不

Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与移植实战详解>分为18章,依次讲解了Android系统的基本知识, Linux内核的基本知识,分析了Android系统的源码,深入分析HAL层的基本知识,GoldFish下的驱动.MSM内核和驱动.OMAP内核和驱动.显示系统驱动.输入系统驱动.振动器系统驱动.音频系统驱动和视频输出系统驱动,多媒体框架

vSocket模型详解及select应用详解

1.I/O复用:selec函数 在介绍socket编程之前,首先要熟悉下I/O多路转接技术,尽管SOCKET通信编程有很多模型,但是,在UNIX环境下,使用I/O多路转接模型无疑是一种更好的选择,UNIX下有5种I/0模型,分别是阻塞式I/O.非阻塞式I/O.I/O复用(select和poll).信号驱动式I/O,异步I/O.这5种方式都可用SOCKET编程,这里只介绍阻塞式I/O和I/O复用,如果向详细了解I/O模型的,可以参考<UNIX网络编程卷一:套接字联网API>,或着查看 Socke

WSAEventSelect模型详解

WSAEventSelect 是 WinSock 提供的一种异步事件通知I/O模型,与 WSAAsyncSelect模型有些类似.       该模型同样是接收 FD_XXX 之类的网络事件,但是是通过事件对象句柄通知,而非像 WSAAsyncSelect一样依靠Windows的消息驱动机制. 与WSAAsyncSelect模型相同,WSAEventSelect将所有的SOCKET事件分为如下类型:(共十种)                FD_READ , FD_WRITE , FD_OOB

I/O复用模型详解

一.httpd工作模型 prefork:进程模型,两级结构,主进程master负责生成子进程,每个子进程负责响应一个请求 worker:线程模型,三级结构,主进程master负责生成子进程,每个子进程负责生成多个线程,每个线程相应一个请求 event:线程模型,三级结构,主进程master负责生成子进程,每个子进程响应多个请求 二.I/O模型名词概念 同步/异步:关注的是消息通信机制 同步:synchronous,调用者等待被调用者返回信息,才能继续执行异步:asynchronous,被调用者通

OSI七层模型详解 TCP/IP协议

总结 OSI中的层 功能 TCP/IP协议族 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 表示层 数据格式化,代码转换,数据加密 没有协议 会话层 解除或建立与别的接点的联系 没有协议 传输层 提供端对端的接口 TCP,UDP 网络层 为数据包选择路由 IP,ICMP,OSPF,EIGRP,IGMP 数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,MTU 物理层 以二进制数据形式在物理媒体上

Linux进程间通信与线程间同步详解(全面详细)

引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496linux下进程间通信的几种主要手段简介: 1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:   2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身