第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析
驱动的分层分离概念——platform机制剖析
/*
*硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
*软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
*参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》,源码:linux
一、回顾
在上一篇博文【输入子系统——框架分析】中,分析了输入子系统的框架如下图所示:
- 在整个框架中,
input.c
文件起一个中转的作用; -
纯代码相关的文件
xxx_handler.c
,用来存放相对“稳定”的代码(稳定——基本不需要修改、兼容性强); -
硬件有关的文件
xxx_device.c
,用来进行具体硬件驱动的编写,一般只需要编写这个文件。 - 对于整个系统,在已经有
xxx_handler.ko
初次加载xxx_device.ko
时:会调用input_register_device()
将该device
注册进输入子系统(放入链表并进行匹配),匹配成功后之后调用input_attach_handler()
找到对应handler->connect()
建立连接。
对于上述的图,我们可以很清晰的看到,整个输入子系统大致被分为三个部分:中转部分input.c
、稳定部分xxx_handler.c
、编写部分xxx_device.c
。
在Linux系统中,有一个名词来描述这种类型的机制:platform(总线)机制。
二、platform机制
1、分层思想
把核心层与设备相关层分开出来,每一层专注于自己的功能的编写,核心层特点:供多数文件使用的共用代码,供设备相关层调用。
如上图的input.c
为核心层,xxx_device.c
与xxx_driver.c
为设备硬件相关层(platform机制中的handler称为driver)。
2、分离
把硬件相关的代码与驱动相关的分离开来,如上图中编写部分xxx_device.c
为硬件相关的代码,稳定部分xxx_driver.c
为驱动相关。
3、机制剖析
对于上述中的中转部分input.c
、稳定部分xxx_handler.c
、编写部分xxx_device.c
,三者构成的是device-bus-driver
体系。
3.1 device部分
platform机制中,这个文件一般命名为xxx_dev.c
,用来进行具体硬件驱动的编写,一般只需要编写这个文件。
通过分析,得到下图:
- 构建一个
platform_device
结构体xxx_dev
原型: - 需要通过
platform_device_register()
来注册一个平台devicexxx_dev
- 调用
device_add()
来添加xxx_dev
- 进行插入链表且匹配工作
3.2 driver部分
platform机制中,这个文件一般命名为xxx_drv.c
,用来存放相对“稳定”的代码(稳定——基本不需要修改、兼容性强)。
通过分析,得到下图:
- 构建一个
platform_driver
结构体xxx_drv
原型: - 需要通过
platform_driver_register()
来注册一个平台driverxxx_drv
- 调用
bus_add_driver
来添加xxx_drv
- 进行插入链表工作(这里并没有进行匹配)
3.3 bus部分
在上面介绍了device部分
与driver部分
,那么二者是怎么来进行匹配的呢?下面分两种情况来介绍:
-
先加载
xxx_drv.ko
,后加载xxx_dev.ko
。
在加载xxx_dev.ko
时会进行如下:
①、将xxx_dev
结构体放入到bus的device链表中
②、从bus的drv链表中每取出一个drv
,就调用bus->match()
函数判断drv是否支持这个dev
③、若支持则调用drv->probe()
函数 -
先加载
xxx_dev.ko
,后加载xxx_drv.ko
。
在加载xxx_drv.ko
时会进行如下:
①、将xxx_drv
结构体放入到bus的driver链表中
②、从bus的device链表中每取出一个dev
,就调用bus->match()
函数判断dev是否支持这个drv
③、若支持则调用drv->probe()
函数
那么他们是如何进行判断是否互相支持的呢?
这里只是一种匹配方式,还有其他几种,可以查看这片博文https://blog.****.net/shenlong1356/article/details/104461673
在drivers/base/bus.c
中找到如下代码