首页 > 系统相关 >linux module_platform_driver宏的使用

linux module_platform_driver宏的使用

时间:2023-06-01 21:33:33浏览次数:49  
标签:__ driver module platform device 设备

module_platform_drivers使用方式

module_platform_driver 是一个宏,用于简化在 Linux 内核模块编程中注册平台设备驱动的过程。

具体使用方法如下:

  1. 包含相关头文件:
    在代码文件的顶部,包含所需的头文件,如:
#include <linux/module.h>
#include <linux/platform_device.h>
  1. 定义平台设备驱动结构体:
    创建一个结构体来描述平台设备驱动,包含驱动的名称、设备探测函数、设备注销函数等。例如:
static int my_probe(struct platform_device *pdev)
{
    // 设备探测逻辑
    return 0; // 返回0表示成功
}

static int my_remove(struct platform_device *pdev)
{
    // 设备注销逻辑
    return 0; // 返回0表示成功
}

static struct platform_driver my_platform_driver = {
    .driver = {
        .name = "my_device",
        .owner = THIS_MODULE,
    },
    .probe = my_probe,
    .remove = my_remove,
};
  1. 使用 module_platform_driver 宏注册平台设备驱动模块:
    使用 module_platform_driver 宏来注册平台设备驱动模块,将上述定义的结构体作为参数传递给宏。例如:

module_platform_driver(my_platform_driver);

通过使用 module_platform_driver 宏,内核会在模块加载时自动注册平台设备驱动,并根据驱动的名称与设备树中的设备节点进行匹配。当匹配成功时,内核将调用驱动结构体中指定的设备探测函数进行设备的初始化。当模块卸载时,内核会自动调用驱动结构体中指定的设备注销函数进行设备的注销。

请注意,上述示例中的函数和结构体名称仅供参考,实际使用时需要根据具体情况进行适配和命名。另外,还需确保内核配置中已启用平台设备支持(CONFIG_OF 和 CONFIG_PLATFORM_DRIVERS)以及相关的依赖项。

先说结论,再看细节

  1. module_platform_driver对module_init/module_exit进行了封装,简化了模板代码
  2. module_platform_driver注册的driver在匹配到设备树节点、或者匹配到对应的平台设备时才会执行probe函数
    问题:
    怎么匹配设备树节点或者设备?

再来看看细节

module_platform_driver的宏定义在include/linux/platform_device.h文件

#define module_platform_driver(__platform_driver) \
	module_driver(__platform_driver, platform_driver_register, \
			platform_driver_unregister)

module_driver定义在include/linux/device/driver.h文件

/**
 * module_driver() - Helper macro for drivers that don't do anything
 * special in module init/exit. This eliminates a lot of boilerplate.
 * Each module may only use this macro once, and calling it replaces
 * module_init() and module_exit().
 *
 * @__driver: driver name
 * @__register: register function for this driver type
 * @__unregister: unregister function for this driver type
 * @...: Additional arguments to be passed to __register and __unregister.
 *
 * Use this macro to construct bus specific macros for registering
 * drivers, and do not use it on its own.
 */
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

追根溯源,从代码中看到,module_platform_driver最终还是调用了module_init,但是,又不仅仅是调用了module_init,还调用了platform_driver_registerplatform_driver_unregister,这两个函数的作用就是注册和卸载平台驱动。

再来看看platform_driver_register

/*  include/linux/platform_device.h */
#define platform_driver_register(drv) \
	__platform_driver_register(drv, THIS_MODULE)

https://www.cnblogs.com/hueyxu/p/13659262.html

查看platform设备device和驱动driver

// 里面包含了设备树节点和platform_device_register_data两种方式注册的设备
# /sys/bus/platform/devices

// 包含了module_platform_driver注册的驱动
# /sys/bus/platform/drivers

设备驱动模型

Linux内核在2.6版本中引入设备驱动模型,简化了驱动程序的编写。Linux设备驱动模型包含设备(device)、总线(bus)、类(class)和驱动(driver),它们之间相互关联。其中设备(device)和驱动(driver)通过总线(bus)绑定在一起。

Linux内核中,分别用 bus_type、 device_driver和 device结构来描述总线、驱动和设备,结构体定义详见 linux/device.h。设备和对应的驱动必须依附于同一种总线,因此 device_driver和 device结构中都包含 struct bus_type指针。

对于早期的Linux内核(2.6版本以前)来说,通常在驱动代码中xxx_driver 注册过程中调用 probe() 函数来对设备进行初始化。

引入Linux设备驱动模型下,设备和驱动可以分开注册,依赖总线完成相互绑定。系统每注册一个设备的时候,会寻找与之匹配的驱动;相反,系统每注册一个驱动的时候,会寻找与之匹配的设备。这个过程中,设备和驱动的匹配工作由总线完成。

platform总线的注册

platform总线是一种虚拟的总线,与之相对应的是PCI、I2C、SPI等实体总线。引入虚拟platform总线是为了解决某些设备无法直接依附在现有实体总线上的问题。
可以看到platform_bus_initdo_initcalls前面完成了初始化。

start_kernel
  -> rest_init
    -> kernel_init
      -> do_basic_setup  //这个阶段之前完成了CPU相关初始化,设备还没工作
        ->driver_init
          -> platform_bus_init //注册platform总线
        -> do_initcalls   // 开始pure_initcall、core_initcall、device_initcall等不同阶段的初始化

platform device和platform driver如何绑定

注册driver时绑定device

如下函数依次递进直接到platform_match

函数 解释
__platform_driver_register 该函数会对 struct device_driver 的bus、probe、remove等回调函数进行初始化,紧接着调用 driver_register(&globalfifo_driver->driver)
driver_register 对bus、probe、remove等回调函数初始化进行判断,保证总线和驱动上相应的函数只能存在一个。bus_add_driver(&(globalfifo_driver.driver)) ,将驱动注册到总线上
bus_add_driver 如果总线使能 drivers_autoprobe ,将调用 driver_attach() 尝试匹配设备
driver_attach driver_attach() 函数找到驱动依附的总线信息,遍历总线上链表 klist_devices 得到当前总线上存在的设备,然后调用 __driver_attach(dev, drv) 函数,尝试将驱动和设备绑定。
driver_match_device driver_match_device(drv, dev) 回调 drv->bus->match() 函数,对于platform_bus为 platform_match() 。

注册device时绑定driver

函数 解释
platform_device_register 主要对 struct device 中基本成员进行初始化,包括 kobject 、 struct device_private 、 struct mutex 等
platform_device_add device_add 添加设备
device_add bus_add_device注册到总线系统中。并建立sysfs的相关目录:总线系统中建立到设备的链接,同时也在设备目录下建立到总线的subsystem链接
bus_probe_device 尝试在总线上寻找可以绑定的驱动。经过层层调用,最终又调用到 driver_match_device() 和 driver_probe_device() 函数,查找总线上能和当前设备匹配的驱动,并将驱动和设备绑定在了一起。
device_initial_probe
__device_attach 后面流程和上面一样了

platform_match

driver_override 有效时,尝试将驱动名字和 driver_override 匹配

  • 基于设备树风格的匹配
  • 基于 ACPI 风格的匹配
  • 匹配 ID 表
  • 匹配 platform_device 设备名和驱动的名字
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);

	/* When driver_override is set, only bind to the matching driver */
	if (pdev->driver_override)
		return !strcmp(pdev->driver_override, drv->name);

	/* Attempt an OF style match first */
	if (of_driver_match_device(dev, drv))
		return 1;

	/* Then try ACPI style match */
	if (acpi_driver_match_device(dev, drv))
		return 1;

	/* Then try to match against the id table */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}

Ref

https://blog.csdn.net/m0_37765662/article/details/106490792

标签:__,driver,module,platform,device,设备
From: https://www.cnblogs.com/lvzh/p/17447274.html

相关文章

  • 使用kalibr做相机内参标定时,报错:“ImportError: No module named igraph”
    这是因为电脑没有安装python的igraph库,所以需要安装igraph库。1.sudoapt-getinstall-ylibigraph0-dev 2.pipinstallpython-igraph==0.7.1.post6(python2只支持0.8X以前的版本)安装完毕,执行kalibr相机内参标定命令即可。 ......
  • 如何正确在多线程环境下更新UI_使用Platform的runLater方法
    如何正确在多线程环境下更新UI_使用Platform的runLater方法许多UI控件都提供了各种修改方法,比如我们可以修改Label上面的文本,进度条ProgressBar的进度。但我们必须保证修改UI的线程是JavaFX的UI线程,如果不是则会出现异常。那么我们如何在另一个线程中修改JavaFX的UI呢?......
  • bitsandbytes通过源码安装后调用报错AttributeError: module 'bitsandbytes.nn' has n
    通过github下载的源码使用pipinstall-e.方式安装的时候会出现题目中的问题。这个时候先卸载掉bitsandbytes,然后重新使用pipinstallbitsandbytes安装,这种方式直接从仓库中安装,问题就解决了。目前尚不清楚问题出现原因,虽然两种方式的安装版本都是0.38.1......
  • cassandra cpp driver中bind list——用cass_statement_bind_collection函数
     CassErrorinsert_into_collections(CassSession*session,constchar*key,constchar*items[]){CassErrorrc=CASS_OK;CassStatement*statement=NULL;CassFuture*future=NULL;CassCollection*collection=NULL;constchar**item=NULL;c......
  • mongodb c++ driver安装踩坑记
     安装教程:https://mongodb.github.io/mongo-cxx-driver/mongocxx-v3/installation/(1)“initializer_list”filenotfoundhttp://stackoverflow.com/questions/19493671/initializer-list-no-such-file-or-directorySinceyouareusing GCC-4.8 andyourproblemisthatyoud......
  • 【HarmonyOS】hap包在多台设备中安装和HarmonyOS应用含多个module安装问题
     在HarmonyOS应用开发过程中,大家会遇到一些hap安装问题,如多模块hap包存在调用如何在模拟器上统一运行、或者同一hap包如何在多台设备运行问题等,这里汇总一些hap安装问题解答,供大家参考。 【问题1】我的HarmonyOS工程创建了多个module,构建出的.app包,如何在模拟器上安装?   ......
  • 使用Driverquery命令的一些特定参数来进一步精细化您需要的驱动程序信息
    使用Driverquery命令的一些特定参数来进一步精细化您需要的驱动程序信息。以下是一些示例命令:driverquery/v:显示更详细的驱动程序信息,包括每个驱动程序的签名状态、文件路径等。driverquery/si:按照驱动程序的签名状态对结果进行排序,首先列出已签名的驱动程序。driverqu......
  • 错误解决:These dependencies were not found: core-js/modules/es.array.push.js
    错误描述执行npmrundev后报错:Thesedependencieswerenotfound:core-js/modules/es.array.push.jsin./node_modules/@babel/runtime/helpers/objectSpread2.js,./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-pluvue?vue&type=script&la......
  • ModuleNotFoundError: No module named 'requests' 解决方案
    ModuleNotFoundError:Nomodulenamed'requests'一般就是没导入库,可以在脚本当前目录下,运行一下代码:pipinstallrequest#同理,如果别的库缺漏,就把request替换掉我是在vscode里面跑的python,所以就用的powershell的那个命令框......
  • FLEX实践:主应用程序、MODULE、COMPONENT组合
    本次实践主要是记录下如何在FLEX主应用程序中调用一个MODULE,而在MODULE中调用COMPONENT。在开始之前先来简单谈谈MODULE这个概念 --========================================================================模块(Module)开发的优点自不待说。FlexProject中建立多个Application......