底层软件 | 设备树、设备注册、驱动注册与驱动匹配

前面我们学习了设备如何和驱动匹配,也学习了设备树。

一直觉得,需要有一篇文章系统、项目般的结合讲解一下,加深一下影响,正当我准备动笔之时,发现了一篇很不错的文章!

就分享给大家一起来看看设备树、设备驱动模型是如何相互结合的。

文章以背光调整设备为例,记录设备描述,设备注册,驱动注册,驱动与设备匹配的过程。

1 设备描述

在设备树dts文件中对设备信息进行描述,使用dts将设备与驱动分离,在不同的平台或目标机上,如果硬件设备资源不通,则只需要变更设备树文件即可,驱动可以保持一致。例如背光设备的dts描述为:

{lvds_backlight0: lvds_backlight {                           // 标签:设备名[@设备地址]compatible = "pwm-backlight";                           // 设备与驱动匹配的关键字pwms = <&lvds0_pwm 0 100000 0>;                         // pwm设备描述 <引用PWM设备结点 极性 周期>brightness-levels = < 0  1  2  3  4  5  6  7  8  9      // 背光调整等级10 11 12 13 14 15 16 17 18 1920 21 22 23 24 25 26 27 28 2930 31 32 33 34 35 36 37 38 3940 41 42 43 44 45 46 47 48 4950 51 52 53 54 55 56 57 58 5960 61 62 63 64 65 66 67 68 6970 71 72 73 74 75 76 77 78 7980 81 82 83 84 85 86 87 88 8990 91 92 93 94 95 96 97 98 99100>;default-brightness-level = <80>;                        // 默认背光等级status = "okay";                                        // 设备结点状态,如果是okay则向kernel注册设备,否则为disable,则不向kernel注册设备信息};
}

以上为设备树文件描述lvds_backlight设备节点的节点信息。

  • compatible:字符串属性,用于匹配设备与设备驱动。一般形式为,,前者一般为芯片供应商,后者为模块名。
  • pwms:pwm设备属性,其引用了一个pwm设备节点&lvds0_pwm,节点信息由drivers/pwm/core.c解析成设备。在pwm_bl.c驱动中可以直接get pwm资源及对pwm资源进行操作。
  • brightness-levels:背光调整等级,由pwm_bl.c中的probe进行解析。
  • default-brightness-level:默认背光等级,由pwm_bl.c中的probe进行解析。
  • status:设备状态如果设置成okay,则在解析设备树文件时会将此设备注册到对应的总线上,否则不会自动注册,需要手动注册。

2 设备注册

  • dts文件在编译时,编译成dtb文件,启动kernel时,将dtb的地址传递给kernel,对dtb文件进行解析。开始解析的函数为setup.c文件中的setup_arch()函数中的unflatten_device_tree()对设备树文件进行解析,解析结果放在of_root(of/base.c)的一个链表中。
  • start_kernel()–>rest_init()–>kernel_init()–>kernel_init_freeable()–>driver_init()–>driver_init()–>of_core_init(),将设备树中配置的节点暴露到用户空间的/sys/firmware/devicetree/base目录。其中kset kobj等概念还未完全建立,后续补充
  • 多数设备均注册到platform bus上,如何总线进行注册目前还没有理清楚,在系统目录/sys/bus/platform/devices中列出系统已经注册的设备。

经过kernel的一系列设置arch,初始化操作,kernel将bl_pwm设备注册到platform上,可在文件系统中查看到以下文件:/sys/bus/platform/devices/lvds_backlight,当status属性设置成"disable"时,设备便不会注册,/sys/bus/platform/devices/目录下也不会有相关的设备信息。

3 驱动注册

由于设备注册到platform bus上,因此驱动也注册到platform bus上,platform bus对设备与驱动进行匹配。将驱动注册到platform bus的方法需要使用platform提供的api,具体注册方法如下:

// match table
static const struct of_device_id pwm_backlight_of_match[] = {{ .compatible = "pwm-backlight" },                                  // 匹配设备中的compatible属性{ }
};
MODULE_DEVICE_TABLE(of, pwm_backlight_of_match);...// platform driver 结构定义
static struct platform_driver pwm_backlight_driver = {.driver     = {.name       = "lvds_backlight",                                     // 驱动名称.pm         = &pwm_backlight_pm_ops,.of_match_table = of_match_ptr(pwm_backlight_of_match),             // 匹配设备的配置表,同一个驱动,可以匹配不同的设备},.probe      = pwm_backlight_probe,                                  // 探针函数,当设备与驱动匹配时调用.remove     = pwm_backlight_remove,                                 // 设备离线时调用.shutdown   = pwm_backlight_shutdown,                               // shutdown时调用
};module_platform_driver(pwm_backlight_driver);                           // 宏,展开后调用init 和 exit函数。注册驱动

pwm_backlight_driver和pwm_backlight_of_match均为配置表,设置驱动名,回调函数等,确保能被kernel调用,注册驱动的是platform提供的宏module_platform_driver,具体如下:

// platform_device.h
/* module_platform_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()*/
#define module_platform_driver(__platform_driver) \module_driver(__platform_driver, platform_driver_register, \platform_driver_unregister)// device.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(pwm_backlight_driver);代码,kernel就会适当时候将此驱动注册到platform bus上。注册成功后,可以在/sys/bus/platform/drivers路径下查看已经注册的驱动。

4 驱动与设备匹配

由于设备与驱动均注册到platform bus上,因此设备的匹配由platform bus完成,具体匹配函数为platform.c中的platform_match(struct device *dev, struct device_driver *drv)函数,其参数为设备结构指针和驱动结构指针,函数实现如下:

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))                   // 使用match表匹配compatible属性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;// 匹配ID/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);            // 使用驱动名与设备名进行匹配

由匹配函数可知,当有驱动或设备注册后,依次使用match tbl acpi id tbl dev->name drv->name进行匹配,match tbl优先级最高,驱动名匹配优先级最低。只要有一种方式匹配成功,则返回,驱动与设备匹配成功后,调用驱动中设置的回调函数–probe函数。

5 小结

以上,驱动与设备成功绑定,且调用pwm_bl.c中的probe函数,但是到这里,还不能调整pwm以调整背光,也不能在用户空间通过文件操作来动态的修改背光。现有的驱动是借助backlight class完成属性背光调整及创建用户空间的属性文件。

6 原文链接

  • 设备注册、驱动注册与驱动匹配

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/40309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验2 字符及字符串输入输出与分支程序设计实验

字符及字符串输入输出 从键盘输入两个一位十进制数&#xff0c;计算这两个数之和&#xff0c;并将结果在屏幕上显示出来。 分支程序设计 从键盘输入一字符&#xff0c;判断该字符是小写字母、大写字母、数字或者其他字符。若输入为小写字母&#xff0c;显示“You Input a Lo…

悼念之前的coplit

最近学MySQL七月三号还能正常卡bug使用紫色的coplit 然后今天就不行了 可惜了&#xff0c;蓝色的就是GPT3&#xff0c;紫色是4(可能比不上4但至少比蓝色的聪明点&#xff09; 原来一开始问题框上面有三个模式选择&#xff0c;去年下半年的时候这个三个模式就被隐藏掉了&#x…

备份和清理windows事件日志

echo off Set CurrentDate%date:6,4%-%date:3,2%-%date:~0,2% Set CurrentTime%time:0,2%-%time:3,2%-%time:~6,2% Set CurrentDateTime%CurrentDate% for /f "tokens1-4 delims/ " %%a in (‘date /t’) do ( set month%%a set day%%b set year%%c ) :: 确保月和日始…

成都欣丰洪泰文化传媒有限公司开网店可靠吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业无疑是这场浪潮中的佼佼者。而在这波汹涌的电商大潮中&#xff0c;成都欣丰洪泰文化传媒有限公司凭借其专业的电商服务能力和前瞻的市场洞察力&#xff0c;成为了业界的一匹黑马。今天&#xff0c;就让我们一起揭开这家专注于电…

python绘制领域矩形

问题描述&#xff1a; 使用python书写代码实现以下功能&#xff1a;给定四个点的坐标&#xff0c;调用一个函数&#xff0c;可以使原来的四个点分别向四周上下左右移动15距离&#xff0c;分别记录下移动后的坐标&#xff0c;然后画出内侧矩形和外侧矩形 代码&#xff1a; im…

提升学生岗位管理效率,构建智慧校园学工管理新模式

智慧校园学工管理系统中的“学生岗位”功能&#xff0c;是连接学生与实践机会的桥梁&#xff0c;它集岗位发布、申请、管理、评价于一体&#xff0c;全方位支持学生在校期间的实践锻炼与能力提升。该功能让校园内外的各类组织能轻松在线发布多样化的实践岗位&#xff0c;比如助…

SAP HCM ABAP DEBUG小技巧

导读 INTRODUCTION 调试小技巧&#xff1a;今天分享下我在处理HCM业务中&#xff0c;通过一些DEBUG技巧&#xff0c;减少DEBUG参数输入的问题&#xff0c;经过会遇到调试代码&#xff0c;有时候DEBUG太快&#xff0c;错过自己想看的代码&#xff0c;有时候不想执行某段代码&…

Python基础教程——10个可视化案例实操,一图胜千言!

让数据集改变你的思维 数据可视化是数据科学家传达洞见和讲述数据故事的关键工具。作为 Python 开发者&#xff0c;我们拥有丰富的可视化库和工具&#xff0c;能够创建各种引人入胜的图表。本文将探索一些鲜为人知但实用的可视化类型&#xff0c;如桑基图(Sankey Diagrams)、脊…

【MySQL】数据类型{tinyint/bit/float/decimal/char/varchar/date/enum/set}

文章目录 1.数据类型分类2.数值类型2.1tinyint 1字节2.2bit 0-64位2.3浮点类型float 4个字节decimal 3.字符串类型char开多少空间为多大varchar开多少是上限 存多少占多大空间日期和时间类型enum和setenum&#xff1a;枚举&#xff0c;“单选”类型&#xff1b;set&#xff1a;…

9.计算机视觉—目标检测

目录 1.物体检测边缘框目标检测数据集总结边缘框代码实现2.锚框:目标检测的一种方法IoU—交并比赋予锚框标号使用非极大值抑制(NMS)输出总结代码实现1.物体检测 边缘框 一个边缘框可以通过四个数字定义 (左上x,左上y),(右下x,右下y)(左上x,左上y,宽,高)(中间x,中间y…

docker-compose: 未找到命令

这个错误表明您在执行docker-compose up -d命令时&#xff0c;系统无法找到docker-compose命令。这通常是因为在当前的环境中&#xff0c;docker-compose命令没有被正确安装或者没有被正确配置到系统的可执行路径中。 要解决这个问题&#xff0c;您可以按照以下步骤检查和修复…

文心一言指令是什么?快速上手教程来了!

在数字化时代&#xff0c;人工智能的发展日新月异&#xff0c;其中自然语言处理技术尤为引人瞩目。文心一言作为其中的佼佼者&#xff0c;凭借其强大的语言理解和生成能力&#xff0c;为用户提供了高效、便捷的信息处理服务。本文将详细介绍如何快速上手文心一言指令&#xff0…

用网上抓取的天气的接口做了一个系统

这个接口数据太全了了&#xff0c;空气质量、雷达预报、小时预报、15天预报、实况、aqi排名&#xff0c;云量、预警、生活指数包圆了&#xff0c;数据接口如下图所示&#xff1a; 万年历 万年历接口 行政区划边界GEOJSON 国家统计局区划编码 全国城市区划编码经纬度 天气实况 …

10计算机视觉—物体检测算法

目录 1.R-CNN(区域卷积神经网络)2014兴趣区域(RoI)池化层Fast RCNN 2015Faster R-CNN 2015Mask R-CNN 2017总结2. SSD(单发多框检测)2016SSD模型总结3.YOLO(你只看一次)快!很重要4.目标检测算法性能对比5.SSD代码实现 使用很少,比不上yolo多尺度锚框实现SSD代码实现训练…

浅谈渗透测试实战

很多时候&#xff0c;在看白帽子们的漏洞的时候总有一种感觉就是把web渗透简单地理解成了发现web系统漏洞进而获取webshell。其实&#xff0c;个人感觉一个完整的渗透&#xff08;从黑客的角度去思考问题&#xff09;应该是以尽一切可能获取目标的系统或者服务器的最高权限&…

Go语言工程管理

本文内容为Go工程创建和配置开发及简单程序示例。 目录 工程管理 GOPATH 配置GOPATH GOROOT 新建系统变量 配置go工程 添加go path 简单的程序实现 程序代码 开始运行 运行结果 内容解析 总结 工程管理 GOPATH go语言的项目&#xff0c;需要有特定的目录结构进行…

【人工智能】GPT-5的即将到来:从高中生进化到,,,博士生?

GPT-5的即将到来&#xff1a;从高中生进化到,博士生&#xff1f; 随着近月GPT-4o的出世&#xff0c;OpenAI也在进行一系列的采访和介绍接下来的展望和目标。 在6月22日的采访中&#xff0c;美国达特茅斯工程学院公布了OpenAI首席技术官米拉穆拉蒂的访谈内容。穆拉蒂确认&#…

urfread刷算法|构建一棵树

大意 示例标签串&#xff1a; 处理结果&#xff1a; 题目1 根据标签串创建树 需求 需求&#xff1a;给出一个字符串&#xff0c;将这个字符串转换为一棵树。 字符串可以在代码里见到&#xff0c;是以#开头&#xff0c;按照\分割的字符串。 你需要将这个字符串&#xff0…

ChatGPT 论文助手:如何用 AI 技术加速学术写作过程

ChatGPT在论文写作中的应用 ChatGPT作为一个先进的语言模型&#xff0c;在学术论文创作领域提供显著帮助。它不仅提升学生与研究者的写作效率&#xff0c;还优化论文质量并引入创新观点。以下是ChatGPT在论文写作中的几种具体应用&#xff1a; 提升写作效率 生成写作构思&…

数据结构——树的基础概念

目录 1.树的概念 2.树的相关概念 3.树的表示 &#xff08;1&#xff09;直接表示法 &#xff08;2&#xff09;双亲表示法 (3)左孩子右兄弟表示法 4.树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 1.树的概念 树是一种非线性的数据结构&#xff0…