第二期驱动篇——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()建立连接。

第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析
对于上述的图,我们可以很清晰的看到,整个输入子系统大致被分为三个部分:中转部分input.c、稳定部分xxx_handler.c、编写部分xxx_device.c

在Linux系统中,有一个名词来描述这种类型的机制:platform(总线)机制

二、platform机制

1、分层思想

  把核心层与设备相关层分开出来,每一层专注于自己的功能的编写,核心层特点:供多数文件使用的共用代码,供设备相关层调用。
如上图input.c为核心层,xxx_device.cxxx_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,用来进行具体硬件驱动的编写,一般只需要编写这个文件。
通过分析,得到下图:
第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析

  • 构建一个platform_device结构体xxx_dev
    原型:
    第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析
  • 需要通过platform_device_register()来注册一个平台devicexxx_dev
  • 调用device_add()来添加xxx_dev
  • 进行插入链表且匹配工作

3.2 driver部分

  platform机制中,这个文件一般命名为xxx_drv.c,用来存放相对“稳定”的代码(稳定——基本不需要修改、兼容性强)。
通过分析,得到下图:
第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析

  • 构建一个platform_driver结构体xxx_drv
    原型:
    第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析
  • 需要通过platform_driver_register()来注册一个平台driverxxx_drv
  • 调用bus_add_driver来添加xxx_drv
  • 进行插入链表工作(这里并没有进行匹配)

3.3 bus部分

在上面介绍了device部分driver部分,那么二者是怎么来进行匹配的呢?下面分两种情况来介绍:

  1. 先加载xxx_drv.ko,后加载xxx_dev.ko
    在加载xxx_dev.ko时会进行如下:
    ①、将xxx_dev结构体放入到bus的device链表
    ②、从bus的drv链表中每取出一个drv,就调用bus->match()函数判断drv是否支持这个dev
    ③、若支持则调用drv->probe()函数

  2. 先加载xxx_dev.ko,后加载xxx_drv.ko
    在加载xxx_drv.ko时会进行如下:
    ①、将xxx_drv结构体放入到bus的driver链表
    ②、从bus的device链表中每取出一个dev,就调用bus->match()函数判断dev是否支持这个drv
    ③、若支持则调用drv->probe()函数

那么他们是如何进行判断是否互相支持的呢?
这里只是一种匹配方式,还有其他几种,可以查看这片博文https://blog.csdn.net/shenlong1356/article/details/104461673
drivers/base/bus.c中找到如下代码
第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析

3.3 总体大致框架图

第二期驱动篇——3.1 驱动的分层分离思想——platform机制剖析