首页 > 其他分享 >platform_driver驱动及设备驱动匹配标识符

platform_driver驱动及设备驱动匹配标识符

时间:2024-03-25 23:44:39浏览次数:44  
标签:struct driver platform device 驱动 id 设备

一、设备树platform_driver示例

设备树中需要定义一个设备节点,包含设备的相关信息和属性。例如,假设有一个名为 "my_device" 的设备,其设备树节点可能如下所示:
/dts-v1/;
/ {
    compatible = "example,my_device";
    my_device {
        compatible = "example,my_device";
        reg = <0x12345678 0x1000>;
        interrupt-parent = <&gpio0>;
        interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
    };
};
在上述示例中,该设备节点具有 compatible 属性来标识设备的兼容性,reg 属性用于指定设备的地址范围,interrupt-parent 属性指定中断控制器的父节点,interrupts 属性指定设备的中断号和触发类型。 在驱动程序中定义 platform_driver 结构体,并使用 of_match_ptr() 宏将设备的兼容性标识与驱动程序关联起来。例如:
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>

static int my_driver_probe(struct platform_device *pdev)
{
    // 在这里执行设备的初始化和操作
    return 0;
}

static int my_driver_remove(struct platform_device *pdev)
{
    // 在这里执行设备的清理和操作
    return 0;
}

static const struct of_device_id my_driver_of_match[] = {
    { .compatible = "example,my_device" },
    {},
};
MODULE_DEVICE_TABLE(of, my_driver_of_match);

static struct platform_driver my_driver = {
    .driver = {
        .name = "my_device",
        .of_match_table = of_match_ptr(my_driver_of_match),
    },
    .probe = my_driver_probe,
    .remove = my_driver_remove,
};

module_platform_driver(my_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lethe1203");
 

二、platform驱动总线的匹配方式

首先看下platform_driver、device_driver和device_driver结构体的定义:   struct platform_driver 是Linux内核中用于表示平台驱动程序的结构体。它包含了与平台设备驱动相关的属性和操作,用于管理和控制平台设备。 下面是 struct platform_driver 结构体的定义:
struct platform_driver {
    int (*probe)(struct platform_device *pdev);
    int (*remove)(struct platform_device *pdev);
    void (*shutdown)(struct platform_device *pdev);
    int (*suspend)(struct platform_device *pdev, pm_message_t state);
    int (*resume)(struct platform_device *pdev);
    struct device_driver driver;                  // device_driver结构体**
    const struct platform_device_id *id_table;    // 匹配规则三
    bool prevent_deferred_probe;
};
struct platform_driver 结构体的主要字段如下:
  • probe: 当匹配到某个平台设备时,调用该函数进行设备的初始化。
  • remove: 在设备被移除时,调用该函数进行设备的清理和释放资源操作。
  • shutdown: 可选字段,在系统关机时调用该函数进行设备的关机处理。
  • suspend: 可选字段,在设备进入挂起状态时调用该函数进行设备的挂起操作。
  • resume: 可选字段,在设备从挂起状态恢复时调用该函数进行设备的恢复操作。
  • driver: 包含了和设备驱动相关的属性,如名称、owner等。
  • id_table: 可选字段,用于指定平台设备的标识表,用于驱动程序的设备匹配。
  • prevent_deferred_probe: 可选字段,用于控制是否延迟设备的探测。
  struct device_driver 是 Linux 内核中用于表示设备驱动程序的结构体。它包含了与设备驱动相关的属性和操作,用于管理和控制特定类型的设备。 下面是 struct 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;    // 匹配规则二
    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;
};
struct device_driver 结构体的主要字段如下:
  • name: 设备驱动程序的名称。
  • bus: 指向设备所属的总线类型的指针。
  • owner: 指向拥有该设备驱动程序的模块的指针。
  • mod_name: 拥有该设备驱动程序的模块的名称。
  • suppress_bind_attrs: 一个布尔值,用于控制是否在 sysfs 中暴露 bind/unbind 相关的属性。
  • of_match_table: 指向设备树匹配表的指针,用于匹配设备树节点。
  • probe: 当匹配到设备时,调用该函数来初始化设备。
  • remove: 在设备被移除时,调用该函数来清理和释放资源。
  • shutdown: 可选字段,在系统关机时调用该函数进行设备的关机处理。
  • suspend: 可选字段,在设备进入挂起状态时调用该函数进行设备的挂起操作。
  • resume: 可选字段,在设备从挂起状态恢复时调用该函数进行设备的恢复操作。
  • groups: 指向设备驱动程序所属的属性组数组的指针。
  • pm: 指向设备的电源管理操作的指针。
  struct platform_device 是 Linux 内核中用于表示平台设备的结构体。它用于描述与特定平台相关的设备,例如 SoC 上的外设或其他与硬件集成的设备。 下面是 struct platform_device 结构体的定义:
struct platform_device {
    const char *name;        // 匹配方式一
    int id;
    struct device dev;
    u32 num_resources;
    struct resource *resource;
    const struct platform_device_id *id_entry;
};
struct platform_device 结构体的主要字段如下:
  • name: 设备的名称。该名称通常与设备驱动程序关联。
  • id: 设备的 ID。用于标识同一类型的多个设备。
  • dev: 表示该平台设备的通用设备结构体。它可以被设备模型用于管理设备对象。
  • num_resources: 设备资源的数量。
  • resource: 指向设备资源描述符的指针数组。每个资源描述符包含了设备在系统中所需的 I/O 地址、中断等信息。
  • id_entry: 指向平台设备标识表的指针,用于驱动程序的设备匹配。
  在 Linux 内核中,platform 驱动总线使用设备树中的设备节点来与驱动程序进行匹配。介绍 platform 驱动总线的三种常见的匹配方式
  1. 基于driver.name属性的匹配方式:通过driver.namedevice.name来进行对比匹配
  1. 基于 compatible 属性的匹配方式: 设备树中的设备节点通常会包含一个 compatible 属性,用于描述设备的兼容性标识。platform 驱动总线通过比较设备节点的 compatible 属性与驱动程序中定义的 of_device_id 结构体数组中的兼容性标识,来进行匹配。具体示例可以参考前面提到的 of_match_device() 函数的用法。
  2. 基于 platform_device_id 的匹配方式: 驱动程序可以定义一个 platform_device_id 结构体数组,并通过 MODULE_DEVICE_TABLE(platform, ...) 宏将其注册为可供内核使用的设备表。设备节点在与驱动程序匹配时,会通过比较设备节点的 name 属性与驱动程序中定义的 platform_device_id 结构体数组中的设备名称,来进行匹配。具体示例可以参考前面提到的 platform_device_id 的用法。
需要注意的是,platform 驱动总线的匹配方式是基于设备树的,因此要求设备树中正确地描述了设备的配置信息,包括设备节点的兼容性标识和其他属性。 具体的驱动可参考: 驱动——platform驱动总线三种匹配方式_platform匹配过程_犩未的博客-CSDN博客  

三、of_match_ptr、of_match_device、platform_get_device_id

of_match_ptr

of_match_ptr() 是一个用于将 of_device_id 结构体数组传递给 of_match_table 字段的宏。它将 of_device_id 结构体数组的指针转换为 const struct of_device_id * 类型,以便在注册 platform_driver 时使用。 of_match_tableplatform_driver 结构体中的一个字段,用于指定设备树匹配表。通过传递 of_match_ptr() 宏转换后的指针,可以将设备树匹配表与驱动程序关联起来,实现设备树节点和驱动程序的匹配。 示例代码中的这行代码:
.driver = {
    .name = "my_device",
    .of_match_table = of_match_ptr(my_driver_of_match),
},
使用了 of_match_ptr() 宏将 my_driver_of_match 数组的指针传递给了 of_match_table 字段。这样,当 platform_driver 注册到内核时,内核就能根据设备树节点的兼容性标识进行匹配,并调用相应的回调函数。  

of_match_device

of_match_device() 函数用于在设备树中查找与给定设备匹配的设备兼容性标识(compatible)。 以下是 of_match_device() 函数的原型:
const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev);
函数接受两个参数:
  1. matches:一个指向 of_device_id 结构体数组的指针,包含了设备驱动程序所支持的设备兼容性标识。
  2. dev:一个指向 struct device 的指针,表示当前需要匹配的设备。
函数返回一个指向匹配的 of_device_id 结构体的指针。如果找不到匹配项,则返回 NULL。 以下是一个示例用法:
static const struct of_device_id my_driver_dt_ids[] = {
    { .compatible = "device1" },
    { .compatible = "device2" },
    // 其他设备兼容性标识
};

static int my_driver_probe(struct platform_device *pdev)
{
    const struct of_device_id *id;

    id = of_match_device(my_driver_dt_ids, &pdev->dev);
    if (!id)
        return -ENODEV;

    if (strcmp(id->compatible, "device1") == 0) {
        // 匹配到 device1 的处理逻辑
    } else if (strcmp(id->compatible, "device2") == 0) {
        // 匹配到 device2 的处理逻辑
    }

    return 0;
}
在上述示例中,my_driver_dt_ids 是一个包含设备兼容性标识的数组。在驱动程序的 probe 函数中,使用 of_match_device() 函数来获取与平台设备匹配的设备兼容性标识,并通过相应的操作来处理匹配到的设备。  

platform_get_device_id

platform_get_device_id() 是一个函数,用于获取与给定平台设备匹配的平台设备标识。 函数原型如下:
const struct platform_device_id *platform_get_device_id(const struct platform_device *pdev);
参数 pdev 是一个指向 struct platform_device 的指针,表示要查询的平台设备。 函数返回值是一个指向 struct platform_device_id 的指针,表示与给定平台设备匹配的平台设备标识。如果找不到匹配的标识,则返回 NULLstruct platform_device_id 结构体定义如下:
struct platform_device_id {
    char name[PLATFORM_NAME_SIZE]; // 设备名称
    kernel_ulong_t driver_data;     // 驱动程序数据
};
platform_get_device_id() 函数通过遍历平台设备驱动程序注册的平台设备标识表(struct platform_device_id 数组),与给定的平台设备的名称进行匹配。如果找到匹配的标识,则返回该标识的指针;否则返回 NULL。 通常,在编写平台设备驱动程序时,会在驱动程序中定义一个平台设备标识表,并将其注册到内核中。当平台设备被创建时,驱动程序会根据设备的名称和其他属性,匹配对应的标识,并执行相应的初始化操作。 注意:platform_get_device_id() 函数是在 include/linux/platform_device.h 头文件中声明的。              

标签:struct,driver,platform,device,驱动,id,设备
From: https://www.cnblogs.com/lethe1203/p/18095679

相关文章

  • 异步通知和MISC设备驱动
    异步通知:驱动程序中的异步通知是指驱动程序可以向应用程序发送通知,告知应用程序发生了某种事件。这种通知是异步的,即应用程序可以继续执行其他操作,而不需要主动轮询或等待事件的发生。在Linux内核中,实现驱动异步通知的一种常见方式是使用fasync机制。这个机制的核心是利用fasync......
  • wsl2 ubuntu子系统安装显卡驱动与cuda
    wsl2安装参考文档:http://t.csdnimg.cn/ClwJ9演示安装ubuntu22列出可安装的子系统命令:wsl--list--onlinePSC:\Users\linyu>wsl--list--online以下是可安装的有效分发的列表。使用'wsl.exe--install<Distro>'安装。NAMEF......
  • 高抗干扰/抗噪液晶驱动芯片VK2C23A/B 永嘉原厂LCD液晶段码屏驱动芯片适用于导轨电表,早
    VK2C23A/B概述:      VK2C23A/B是一个点阵式存储映射的LCD驱动器,可支持最大224点(56SEGx4COM)或者最大416点(52SEGx8COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,也可通过指令进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点:•......
  • 数智时代“通关攻略”,开天aPaaS驱动千行万业创新提速
    本文分享自华为云社区《数智时代“通关攻略”,开天aPaaS驱动千行万业创新提速》,作者:华为云头条。随着新一代ICT技术的深化演进,尤其是技术之间的相互融合与作用,全球产业正在加速迈入数智时代。借助信息技术,以高效低成本的方式开启新的业务增长点,已然成为企业转型的必由之路。3月1......
  • 在linux中无需修改内核驱动就能操作GPIO口的示例
    一、首先编写一个脚本文件init.sh#!/bin/bashecho2>/sys/class/gpio/exportsleep1echo3>/sys/class/gpio/exportsleep1echoout>/sys/class/gpio/gpio3/directionecho1>/sys/class/gpio/gpio3/value这段代码是在Linux系统中使用shell脚本语言编写的。让......
  • NCV7718CDPR2G半桥驱动器规格书PDF数据手册引脚图图片价格参数概概述
    产品概述:NCV7718是一款六角半桥驱动器,具有专为汽车和工业运动控制应用设计的保护功能。NCV7718具有独立的控制和诊断功能。该器件可在正向、反向、制动和高阻抗状态下运行。驱动器通过16位SPI接口进行控制,并且菊花链兼容规格书参数:引脚图:......
  • Python包的本地安装(.whl)报错:.whl is not a supported wheel on this platform
    以Pandas为例:1.报错:.whlisnotasupportedwheelonthisplatform.2.报错原因:下载的包与Python版本不相配3.解决步骤(共4步):Step1:在cmd输入命令“pipdebug--verbose”,查看可支持的版本。Step2:下载对应版本的安装包(根据......
  • 设备树LED驱动
    参考资料:https://www.bilibili.com/video/BV1fJ411i7PB?p=25&vd_source=432ba293ecfc949a4174ab91ccc526d6 dts节点:dtsled{#address-cells=<1>;#size-cells=<1>;compatible="dts-led";status="okay";......
  • 设备驱动-15.内核kmalloc/vmalloc及CMA内存介绍
    1kmalloc/vmalloc区别函数位置特性大小限制kmalloc物理内存映射区域物理地址虚拟地址均连续不能超过128Kkzalloc物理内存映射区域物理地址虚拟地址均连续不能超过128Kvmalloc虚拟内存映射区域虚拟地址连续,物理地址不一定连续无限制vzalloc虚拟内......
  • 批处理脚本来将 Windows 10 的虚拟内存设置为自动管理所有驱动器的分页文件大小
    批处理脚本来将Windows10的虚拟内存设置为自动管理所有驱动器的分页文件大小:CopyCode@echooffREM将所有驱动器的分页文件大小设置为自动管理REM禁用虚拟内存wmiccomputersystemwherename="%computername%"setAutomaticManagedPagefile=Falsewmicpagefilesetw......