iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >如何解析Linux驱动中的platform总线
  • 641
分享到

如何解析Linux驱动中的platform总线

2023-06-22 02:06:23 641人浏览 薄情痞子
摘要

如何解析linux驱动中的platfORM总线,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1、platform 总线简介1.1、Linux 驱动的分离和分层思

如何解析linux驱动中的platfORM总线,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

    1、platform 总线简介

    1.1、Linux 驱动的分离和分层思想

    1.1.1、Linux 驱动的分离

            先讲 Linux 驱动的分离,Linux 操作系统支持在各类 CPU 上运行,因为每一种 CPU 对设备的驱动不一样,这样就造成了 Linux 内核中积累了大量代码,并且这些代码关于同一设备的描述大致相同,这就使得内核代码很冗余。以 CPU 通过 I2C 控制 MPU6050 为例:

    如何解析Linux驱动中的platform总线

            从图可以看出每一种平台下都有一套主机驱动和一套设备驱动,因为每个平台的 I2C 控制器不同,所以这个主机驱动得每个平台配一个自己的,但大家所用的 MPU6050 是一样的,所以完全可以就共用一套设备驱动代码。完善后框架如下:

    如何解析Linux驱动中的platform总线

            当然,这只是对于 I2C 下的 MPU6050 这个设备,实际情况下,I2C 下肯定会挂载很多设备,根据这个思路,我们可以得到框架为:

    如何解析Linux驱动中的platform总线

             而在实际开发中,I2C 主机驱动半导体厂家会编写好,设备驱动也由设备厂家编写好,我们只需要提供设备信息即可,如设备接到那个 I2C 接口上,I2C 速度为多少。这样就相当于把设备信息从设备驱动中剥离出来,而设备驱动也会用标准方法去获取设备信息(如从设备树中获取设备信息)。这样就相当于驱动只负责驱动,设备(信息)只负责设备,想办法将两者进行匹配即可,来做这个匹配工作的就是总线,这就构成了 Linux 中的 总线-驱动-设备 模型。结构图如下:

    如何解析Linux驱动中的platform总线

    1.2、platform 平台驱动模型

            上面我们讲做设备驱动的分离,得到 总线-驱动-设备 模型,这个总线就是我平常所说的 I2C、SPI、USB 等总线。但问题是有些设备是不需要通过某一跟总线的,这是就引入了 platform 总线。

            这里需要注意的是,platform 总线是区别于 USB、SPI、I2C 这些总线的虚拟总线。说它虚拟是因为 SoC 与一些外设如 LED、定时器、蜂鸣器是通过内存的寻址空间来进行寻址的,所以 CPU 与这些设备通信压根就不需要总线,那么硬件上也就没有这样一个总线。但内核有对这些设备做统一管理的需求,所以就对这些直接通过内存寻址的设备虚拟了一条 platform 总线,所有直接通过内存寻址的设备都映射到这条虚拟总线上。

            platform 总线的优点:

            1、通过 platform 总线,可以遍历所有挂载在 platform 总线上的设备;

            2、实现设备和驱动的分离,通过 platform 总线,设备和驱动是分开注册的,因为有 probe 函数,可以随时检测与设备匹配的驱动,匹配成功就会把这个驱动向内核注册;

            3、一个驱动可供同类的几个设备使用,这个功能的实现是因为驱动注册过程中有一个遍历设备的操作。      

    2、platform 框架

    2.1、platform 总线

            Linux 内核用 bus_type 结构体来表示总线,我们所用的 I2C、SPI、USB 都是用这个结构体来定义的。该结构体如下:

     struct bus_type {    const char *name;                                      const char *dev_name;     struct device *dev_root;    struct device_attribute *dev_attrs;    const struct attribute_group **bus_groups;             const struct attribute_group **dev_groups;             const struct attribute_group **drv_groups;              int (*match)(struct device *dev, struct device_driver *drv);          int (*uevent)(struct device *dev, struct kobj_uevent_env *env);    int (*probe)(struct device *dev);    int (*remove)(struct device *dev);    void (*shutdown)(struct device *dev);     int (*online)(struct device *dev);    int (*offline)(struct device *dev);    int (*suspend)(struct device *dev, pm_message_t state);    int (*resume)(struct device *dev);    const struct dev_pm_ops *pm;    const struct iommu_ops *iommu_ops;    struct subsys_private *p;    struct lock_class_key lock_key;};

             platform 总线是 bus_type 类型的常量,之所以说它是常量是因为这个变量已经被 Linux 内核赋值好了,其结构体成员对应的函数也已经在内核里面写好。

    定义如下:

     struct bus_type platform_bus_type = {    .name = "platform",    .dev_groups = platform_dev_groups,    .match = platform_match,           .uevent = platform_uevent,    .pm = &platform_dev_pm_ops,};

            platform_bus_type 中的 platform_match 就是我们前面所说的做驱动和设备匹配的函数,该函数定义如下:

     static int platform_match(struct device *dev, struct device_driver *drv){    struct platform_device *pdev = to_platform_device(dev);    struct platform_driver *pdrv = to_platform_driver(drv);         if (pdev->driver_override)        return !strcmp(pdev->driver_override, drv->name);         if (of_driver_match_device(dev, drv))        return 1;         if (acpi_driver_match_device(dev, drv))        return 1;         if (pdrv->id_table)        return platform_match_id(pdrv->id_table, pdev) != NULL;         return (strcmp(pdev->name, drv->name) == 0);}

            这个匹配函数什么时候用,在哪里用,我们不妨先留一个悬念。

    2.2、platform 驱动

    2.2.1、platform 驱动定义

            platform 驱动用结构体 platform_driver 来表示,该结构体内容为:

     struct platform_driver {    int (*probe)(struct platform_device *);        int (*remove)(struct platform_device *);    void (*shutdown)(struct platform_device *);    int (*suspend)(struct platform_device *, pm_message_t state);    int (*resume)(struct platform_device *);    struct device_driver driver;                    const struct platform_device_id *id_table;      bool prevent_deferred_probe;};

             platform_driver 中 const struct platform_device_id *id_table 是 id_table 表,在 platform 总线匹配驱动和设备时 id_table 表匹配法时使用的,这个 id_table 表其实是一个数组,里面的每个元素类型都为 platform_device_id,platform_device_id 是一个结构体,内容如下:

    struct platform_device_id {    char name[PLATFORM_NAME_SIZE];    kernel_ulong_t driver_data;};

            platform_driver 中 driver 是一个驱动基类,相当于驱动具有的最基础的属性,在不同总线下具有的属性则存放在 platform_driver 结构体下。

            驱动基类结构体 device_driver 内容为:

     struct device_driver {    const char *name;                                   struct bus_type *bus;    struct module *owner;    const char *mod_name;     bool suppress_bind_attrs;     const struct of_device_id *of_match_table;          const struct acpi_device_id *acpi_match_table;    int (*probe) (struct device *dev);    int (*remove) (struct device *dev);    void (*shutdown) (struct device *dev);    int (*suspend) (struct device *dev, pm_message_t state);    int (*resume) (struct device *dev);    const struct attribute_group **groups;    const struct dev_pm_ops *pm;    struct driver_private *p;};

             driver 中 of_match_table 也是一个匹配表,这个匹配表是 platform 总线给驱动和设备做匹配时使用设备树匹配时用的,也是一个数组,数组元素都为 of_device_id 类型,该类型结构体如下:

     struct of_device_id {    char name[32];    char type[32];    char compatible[128];       const void *data;};
    2.2.2、platform 驱动注册

            用 platform_driver 结构体定义好 platform 驱动后,用 platform_driver_reGISter 函数向 Linux 内核注册 platform 驱动,函数大致流程如下:

    platform_driver_register (drv)    -> __platform_driver_register        -> drv->driver.probe = platform_drv_probe;               -> driver_registe (&drv->driver)                             -> ......                 -> drv->driver->probe                                        -> platform_drv_probe                        -> drv->probe                    

            上面的分析中从 driver_register (&drv->driver) 到 drv->driver->probe 这一步我们用省略号代替了,现在来做一下分析:

    driver_register(&drv->driver)    -> bus_add_driver                                     -> driver_attach             -> bus_for_each_dev                                    -> __driver_attach                                    -> driver_match_device                                -> 调用bus下的match匹配函数                    -> driver_probe_device                                -> really_probe                             -> drv->probe         

            根据 driver_register 函数流程,我们就知道了总线的 match 匹配函数会在这里遍历使用,这就回答了我们之前留下的一个问题:总线 match 函数在哪里用,一旦匹配成功就会进入到驱动的 probe 函数。 

            根据 platform_driver_register 函数流程,我们可以得出一个结论:向 Linux 内核注册 platform driver 过程里面会有一个遍历驱动和设备匹配的过程,匹配成功后最终会执行 platform driver 的 probe 函数,过程中 的驱动基类 driver 的 probe 函数和 platform_drv_probe 函数都是达到这个目的的中转函数而已。

            值得注意的是,最终会执行的 platform driver 的 probe 函数是由我们来写的,所以主动权又回到我们手里。

    2.3、platform 设备

    2.3.1、platform 设备定义

            如果我们用的 Linux 版本支持设备树,那就在设备树中去描述设备,如果不支持设备树,就要定义好 platform 设备。这里我们需要考虑的一个点是,总线下的匹配函数 match 在做匹配时是先设备树匹配,然后 id_table 表匹配,然后才是 name 字段匹配。支持设备树时,直接在设备树节点里面改设备信息,内核启动时会自动遍历设备树节点,匹配成功就会自动生成一个 platform_device,给下一步来使用。不是设备树的话,这个 platform_device 就是由开发者来写。

            这里我们先不用设备树,自己来定义 platform 设备。platform 设备用 platform_device 结构体来表示,该结构体定义如下:

     struct platform_device {    const char *name;                       int id;     bool id_auto;    struct device dev;    u32 num_resources;     struct resource *resource;    const struct platform_device_id *id_entry;    char *driver_override;         struct mfd_cell *mfd_cell;        struct pdev_archdata archdata;};

    2.4、platform 匹配过程

            platform 总线对驱动和设备的匹配过程其实上面零零碎碎也已经讲的差不多了,现在我们汇总起来在过一遍。

            前面也说过,总线下的驱动和设备的匹配是通过总线下的 match 函数来实现的,不同的总线对应的 match 函数肯定不一样,这个我们不用管,内核都会写好。我们所用的 platform 总线对应的 match 函数是 platform_match 函数,分析一下这个函数:

    platform_match    -> of_driver_match_device              -> acpi_driver_match_device            -> platform_match_id                   -> strcmp(pdev->name, drv->name)   

             通过对上面匹配函数的一个简单分析,我们知道匹配函数做匹配的顺序是先匹配设备树,然后匹配 id_table 表,然后才是暴力匹配 name 字段。对于支持设备树的 Linux 版本,我们一上来做设备树匹配就完事。不支持设备树时,我们就得定义 platform 设备,再用 id_tabale 表或 name 匹配,一般情况下都是选用 name 匹配。

            现在我们来具体看一下设备树条件下的匹配过程:

    of_driver_match_device         -> of_match_device (drv->of_match_table, dev)            -> of_match_node              -> __of_match_node                -> __of_device_is_compatible                    -> __of_find_property(device, "compatible", NULL)   

            看上面的分析我们就知道了这个匹配过程最终是驱动基类的 of_match_table 里的 compatible 去设备树节点里面的 compatible 属性作比较。这个就是把设备树与 platform 总线串起来的一个机理,从而实现了在设备树对应节点里面写设备信息,驱动另外单独写的目的,也就是我们前面讲的驱动分离。

     3、总结

            在具体的开发过程中我们并不需要真的去写一个 platform 总线模型,内核中都已经给我们定义好了。我们对 platform 总线模型的分析主要是搞清楚如何将驱动和设备匹配的,即当我们插入设备是如何找到对应驱动或插入驱动如何找到对应设备的,并最终调用 probe 函数。其实不管是先有驱动后有设备、还是先有设备后有驱动,最终匹配成功后第一件事都是执行驱动的 probe 函数,所以我们尽可放心的忽略中间曲折的情感纠葛,直接把注意力放在最终的 probe 函数。

    看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网操作系统频道,感谢您对编程网的支持。

    --结束END--

    本文标题: 如何解析Linux驱动中的platform总线

    本文链接: https://www.lsjlt.com/news/301903.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • 如何解析Linux驱动中的platform总线
      如何解析Linux驱动中的platform总线,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1、platform 总线简介1.1、Linux 驱动的分离和分层思...
      99+
      2023-06-22
    • windows驱动总裁如何离线安装驱动
      这篇文章主要介绍“windows驱动总裁如何离线安装驱动”,在日常操作中,相信很多人在windows驱动总裁如何离线安装驱动问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”windows驱动总裁如何离线安装驱动...
      99+
      2023-06-30
    • 如何解析Linux 驱动架构
      今天就跟大家聊聊有关如何解析Linux 驱动架构,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。首先,需要熟悉操作系统的设计与实现,推荐大家看 MINIX作者的那部书,同时把MINIX...
      99+
      2023-06-28
    • windows驱动总裁安装的驱动如何卸载
      本篇内容介绍了“windows驱动总裁安装的驱动如何卸载”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!驱动总裁安装的驱动卸载教程方法一:1、...
      99+
      2023-07-01
    • windows驱动总裁安装完驱动没反应如何解决
      这篇文章主要介绍了windows驱动总裁安装完驱动没反应如何解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇windows驱动总裁安装完驱动没反应如何解决文章都会有所收获,下面我们一起来看看吧。驱动总裁安装完...
      99+
      2023-07-01
    • windows驱动总裁安装驱动卡住鼠标不能动如何解决
      这篇文章主要介绍“windows驱动总裁安装驱动卡住鼠标不能动如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“windows驱动总裁安装驱动卡住鼠标不能动如何解决”文章能帮助大家解决问题。驱动...
      99+
      2023-07-01
    • Linux系统如何安装无线网卡驱动
      这篇文章给大家分享的是有关Linux系统如何安装无线网卡驱动的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一 查看自己网卡的版本键入命令 # 如果你的linux版本这个命令不能用,百度其他命令...
      99+
      2023-06-28
    • 如何理解Linux驱动中内核互斥锁
      如何理解Linux驱动中内核互斥锁,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 互斥体概述信号量是在并行处理环境中对多个处理器访问某个公共资源进行保护的机制,mut...
      99+
      2023-06-15
    • windows驱动总裁无法卸载如何解决
      本篇内容介绍了“windows驱动总裁无法卸载如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!驱动总裁无法卸载解决方法首先右键点击下方...
      99+
      2023-07-01
    • vue中的总线机制(EventBus)解析
      目录一、EventBus的简介二、使用方法第一步:2种方式初始化第二步:发送事件第三步:接受事件第四步:移除事件三、全局EventBus1、注册,在main.js中2、在组件中使用&...
      99+
      2022-11-13
      vue总线机制 vue中EventBus vue总线机制EventBus
    • Linux系统如何安装Intel无线网卡驱动
      这篇文章将为大家详细讲解有关Linux系统如何安装Intel无线网卡驱动,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。操作确定无线网卡的型号博主根据实物标识,确实是intel 7260确定系统的内核版本&...
      99+
      2023-06-28
    • 电脑光驱总是自动弹出如何解决
      这篇文章主要介绍“电脑光驱总是自动弹出如何解决”,在日常操作中,相信很多人在电脑光驱总是自动弹出如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”电脑光驱总是自动弹出如何解决”的疑惑有所帮助!接下来,请跟...
      99+
      2023-06-27
    • 电脑中的无线网卡驱动如何安装
      小编给大家分享一下电脑中的无线网卡驱动如何安装,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!点击桌面左下方“主菜单”,点击“控制面板”。进入控制面板后点击“管理工具”。点击“计算机管理”。点击“设备管理”,点击“网络适配器...
      99+
      2023-06-28
    • 怎么解析Linux设备和驱动的相遇
      本篇文章为大家展示了怎么解析Linux设备和驱动的相遇,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一个开发板这一节结合设备信息集合的详细讲解来认识一下设备和驱动是如何绑定的。所谓设备信息集合,就是...
      99+
      2023-06-15
    • 如何理解Linux内核驱动的编码风格
      本篇文章给大家分享的是有关如何理解Linux内核驱动的编码风格,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。最近在向Linux内核提交一些驱动程序,在提交的过程中,发现自己的代...
      99+
      2023-06-16
    • linux驱动中并发与竟态的示例分析
      小编给大家分享一下linux驱动中并发与竟态的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先什么是并发与竟态呢?并发(concurrency)指的是多...
      99+
      2023-06-19
    • 重装win10没有无线网卡驱动如何解决
      这篇文章主要介绍“重装win10没有无线网卡驱动如何解决”,在日常操作中,相信很多人在重装win10没有无线网卡驱动如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”重装win10没有无线网卡驱动如何解决...
      99+
      2023-07-01
    • 在Linux中如何编译并安装ixgbe驱动
      本篇内容介绍了“在Linux中如何编译并安装ixgbe驱动”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!i...
      99+
      2024-04-02
    • Linux设备驱动指的定时与延时如何理解
      本篇文章为大家展示了Linux设备驱动指的定时与延时如何理解,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Linux通过系统硬件定时器以规律的间隔(由HZ度量)产生定时器中断,每次中断使得一个内核计...
      99+
      2023-06-16
    • Win10如何卸载无线网卡的驱动程序
      要卸载无线网卡的驱动程序,可以按照以下步骤进行操作:1. 打开“设备管理器”:可以通过在开始菜单中搜索“设备管理器”来打开它,或者按...
      99+
      2023-09-17
      win10
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作