news 2026/5/14 16:37:27

struct of_device_id

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
struct of_device_id

struct of_device_idLinux 设备树(Device Tree, DT)机制中,用于驱动与设备树节点进行匹配的核心数据结构,主要在 ARM、ARM64、RISC-V 等现代架构的驱动开发中使用,替代了传统的platform_device_id匹配方式,实现了「硬件信息与驱动代码的解耦」。

核心定位

struct of_device_id的核心作用是:在驱动中定义「需要匹配的设备树节点规则」,让总线(如 Platform 总线)能够根据该规则,找到对应的设备树节点并完成驱动与设备的绑定

简单来说:

  • 设备树中用compatible等属性描述硬件设备;
  • 驱动中用struct of_device_id列出「支持的硬件设备列表」;
  • 总线的match函数会对比两者的compatible属性,匹配成功则调用驱动的probe函数。

它的定义在include/linux/of.h头文件中,是设备树驱动开发的「必备组件」。

完整定义(Linux 5.x 及以上版本)

struct of_device_id { char *compatible; // 核心:匹配设备树节点的 compatible 属性 const void *data; // 驱动私有数据:匹配成功后传递给 probe 函数的附加数据 };

关键字段深度解析

compatible:核心匹配字段(重中之重)

  • 作用:用于与设备树节点中的compatible属性进行字符串比对,是设备与驱动匹配的「核心依据」。

  • 格式要求:采用「厂商名,设备名」的格式,确保全球唯一,避免设备冲突,格式为"<vendor>,<device>",也可支持多个兼容值(设备树中compatible属性可定义多个字符串)。

    • 厂商名:通常是芯片厂商缩写(如fsl飞思卡尔、ti德州仪器、rockchip瑞芯微、intel英特尔)。
    • 设备名:通常是芯片型号或外设名称(如imx6ul-uartam335x-i2crk3399-gpio)。
  • 设备树对应示例:设备树中一个 UART 节点的compatible属性定义如下:

    uart1: serial@12340000 { compatible = "fsl,imx6ul-uart", "ns16550a"; // 两个兼容值,优先匹配前者 reg = <0x12340000 0x1000>; };

    驱动中对应的compatible字段可写"fsl,imx6ul-uart"(精确匹配)或"ns16550a"(通用匹配,支持多款兼容 NS16550 协议的 UART)。

  • 匹配规则:总线会遍历设备树节点的compatible字符串数组,只要有一个与驱动的of_device_id.compatible完全一致,即判定为匹配成功(大小写敏感、字符串完全一致)。

data:驱动私有数据

  • 作用:匹配成功后,将该字段的指针传递给驱动的probe函数,用于向probe函数传递额外的硬件配置信息(如寄存器偏移、硬件参数等),避免在probe函数中硬编码。
  • 使用场景:当一个驱动支持多款相似硬件设备,且不同设备的配置存在差异时,可通过data字段传递差异化配置。
  • 示例:定义两款 UART 设备的私有配置,通过data传递:
    // 定义两款 UART 的私有配置结构体 struct uart_config { int baud_rate; // 默认波特率 int reg_offset; // 寄存器偏移量 }; // 具体配置实例 static const struct uart_config imx6ul_uart_cfg = { .baud_rate = 115200, .reg_offset = 0x0, }; static const struct uart_config rk3399_uart_cfg = { .baud_rate = 9600, .reg_offset = 0x10, }; // 定义 of_device_id 表,关联 compatible 和私有配置 static const struct of_device_id uart_of_match[] = { { .compatible = "fsl,imx6ul-uart", .data = &imx6ul_uart_cfg }, { .compatible = "rockchip,rk3399-uart", .data = &rk3399_uart_cfg }, { /* 哨兵节点:标记数组结束,必须存在 */ } };
    probe函数中,可通过of_match_device()函数获取该data指针:
    static int uart_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct uart_config *cfg; // 获取匹配成功的 of_device_id 节点 match = of_match_device(uart_of_match, &pdev->dev); if (!match) return -ENODEV; // 获取私有配置数据 cfg = match->data; printk(KERN_INFO "默认波特率:%d,寄存器偏移:%d\n", cfg->baud_rate, cfg->reg_offset); // 后续硬件初始化逻辑... return 0; }

声明匹配表(向内核导出)

使用MODULE_DEVICE_TABLE(of, 匹配表名)宏,将匹配表导出到内核模块的符号表中,方便内核在加载驱动时识别该驱动支持的设备树节点。

//向内核导出匹配表(必须有,否则内核无法识别) MODULE_DEVICE_TABLE(of, my_dev_of_match);

MODULE_DEVICE_TABLE(of, my_drv_of_match):将匹配表导出到内核模块的符号表中,内核可以通过该宏识别驱动支持的设备树兼容属性,同时也方便模块工具(如modinfo)查看驱动支持的设备。

将匹配表关联到platform_driver结构体

of_match_table并不是一个新的结构体,而是 **struct of_device_id类型的数组(匹配表)**,用于存储一个驱动所支持的所有硬件设备的匹配规则(多个of_device_id项)。

  1. 它是一个以空元素({})结尾的数组(内核要求,用于遍历结束判断)。
  2. 通常在驱动中定义为static const struct of_device_id xxx_of_match[](静态常量,避免内存泄露)。
  3. 驱动需要将该匹配表赋值给对应驱动结构体的of_match_table成员(如platform_driver中的of_match_table),让内核能够找到并使用该匹配表。

关键特性

  • 解耦硬件与驱动:驱动无需硬编码硬件资源(如 IO 地址、中断号),只需通过设备树获取,提升驱动的可移植性。
  • 支持多兼容值:设备树节点的compatible可定义多个字符串,驱动可匹配其中任意一个,提升驱动的通用性(如通用 UART 驱动匹配ns16550a)。
  • 私有数据传递:通过data字段向probe函数传递差异化配置,支持一款驱动适配多款相似硬件。
  • 仅适用于设备树架构:仅在启用了CONFIG_OF内核配置的架构(ARM、ARM64、RISC-V)中有效,x86 架构通常不使用设备树,因此不使用该结构体。

关键要点

  • 必须包含哨兵节点of_device_id匹配表必须以{}结尾(哨兵节点),否则内核遍历匹配表时会发生越界访问,导致系统崩溃。
  • compatible字符串大小写敏感:设备树中的compatible与驱动中的compatible必须完全一致(包括大小写、标点符号),否则匹配失败。
  • 必须导出匹配表MODULE_DEVICE_TABLE(of, ...)宏必须存在,否则内核无法识别驱动支持的设备树节点,导致匹配失败。
  • data字段必须是常量数据data指向的数据必须是静态 / 全局常量(如static const定义),不能是栈上数据,否则驱动加载后可能出现数据丢失。
  • struct of_device_id设备树驱动中驱动与设备节点匹配的核心结构体,核心字段是compatible,用于比对设备树节点的compatible属性。
  • 使用流程固定:定义匹配表(含哨兵节点)→ 导出匹配表 → 关联到platform_driver结构体。
  • 核心优势是实现硬件信息与驱动代码解耦,提升驱动的可移植性和通用性,是现代嵌入式 Linux 驱动开发的必备知识点。
  • 关键注意事项:哨兵节点不可少、compatible字符串大小写敏感、必须通过MODULE_DEVICE_TABLE导出匹配表。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 11:17:49

学术写作新助力:百考通AI如何应对重复率与AIGC双重检测挑战

一、双重检测时代&#xff1a;学术写作面临的新挑战 近年来&#xff0c;随着学术检测技术的不断升级&#xff0c;国内高校和期刊普遍建立了更为严格的论文审核机制。 传统的“查重”已从单纯的文字重复检测&#xff0c;演变为“文字重复率AI生成内容&#xff08;AIGC&#xf…

作者头像 李华
网站建设 2026/5/14 11:17:49

SEW变频器MDX61B0075-5A3-04-00 8279624

孙13665068812SEW MDX61B0075-5A3-04-00 变频器详细介绍 (序列号&#xff1a;8279624) 1. 产品概述与定位 SEW MDX61B0075-5A3-04-00 是 SEW-EURODRIVE 公司生产的 MOVIFIT MDX61B 系列变频器中的一个具体型号。MOVIFIT 系列是 SEW 面向中高端工业应用设计的模块化、多功能变…

作者头像 李华
网站建设 2026/5/11 1:37:30

SEW变频器MDX61B1320-503-04-00 8279748

SEW MDX61B1320-503-04-00 变频器 (8279748) 详细介绍 1. 概述 SEW MDX61B1320-503-04-00 (订货号&#xff1a;8279748) 是德国SEW-EURODRIVE公司生产的 MOVIDRIVE B 系列模块化变频器中的一款特定型号。它代表了该系列中功率等级为 132 kW 的一个配置组合。MOVIDRIVE B 系列…

作者头像 李华
网站建设 2026/5/6 14:20:25

鲜花商城|基于java + vue鲜花商城系统(源码+数据库+文档)

鲜花商城 目录 基于springboot vue鲜花商城系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue鲜花商城系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华
网站建设 2026/5/13 5:31:04

如何选择可编程控制器?可编程控制器分类、性能指标介绍

可编程控制器的作用日渐突出&#xff0c;各大器件中均含有可编程控制器。为增进大家对可编程控制器的了解&#xff0c;本文将对可编程控制器选型技巧、可编程控制器分类以及可编程控制器的技术性能指标进行介绍。如果你对本文内容具有兴趣&#xff0c;不妨继续往下阅读哦。一、…

作者头像 李华
网站建设 2026/5/2 15:11:39

Vue 2.3

一、核心概念 - state 状态 目标&#xff1a;明确如何给仓库提供数据&#xff0c;如何使用仓库的数据 1.提供数据 State提供唯一的公共数据源&#xff0c;所有共享的数据都要统一放到Store中的State中存储。 在state 对象中可以添加我们要共享的数据。 2.使用数据 ①…

作者头像 李华