以下是设备树(Device Tree)中 compatible 属性的具体引用举例,涵盖不同硬件场景和驱动匹配逻辑:
1. 基础示例:PWM 控制器
设备树节点(.dts 文件):
pwm@020c0000 {
compatible = "fsl,imx6q-pwm", "brcm,bcm2835-pwm";
reg = <0x020c0000 0x4000>;
#pwm-cells = <2>;
};
驱动代码匹配逻辑:
// drivers/pwm/pwm-imx.c
static const struct of_device_id pwm_of_match[] = {
{ .compatible = "fsl,imx6q-pwm" }, // 优先匹配此驱动
{ .compatible = "brcm,bcm2835-pwm" }, // 备选兼容驱动
{ /* sentinel */ }
};
// 若设备树中 compatible 顺序为 "brcm,bcm2835-pwm", "fsl,imx6q-pwm"
// 则内核会优先尝试加载 bcm2835-pwm 驱动
2. 多兼容字符串:I2C 设备
设备树节点:
i2c@7e204000 {
compatible = "brcm,bcm2835-i2c", "simple-bus";
reg = <0x7e204000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
};
驱动匹配逻辑:
- 内核优先尝试
brcm,bcm2835-i2c驱动(如 Raspberry Pi 的 I2C 控制器)。 - 若未找到专用驱动,则回退到通用
simple-bus驱动(用于总线设备枚举)。
3. SoC 级别兼容性
设备树根节点:
/ {
compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
model = "Raspberry Pi 3 Model B Rev 1.2";
// ...
};
作用:
raspberrypi,3-model-b:特定开发板的兼容标识,用于加载板级驱动(如 GPIO 引脚复用)。brcm,bcm2837:SoC 级别标识,用于加载芯片通用驱动(如时钟、中断控制器)。
4. 驱动代码中的匹配表
驱动示例(of_match_table):
// drivers/leds/leds-gpio.c
static const struct of_device_id gpio_leds_of_match[] = {
{ .compatible = "gpio-leds" }, // 通用 GPIO LED 驱动
{ .compatible = "raspberrypi,gpio-leds" }, // 树莓派定制驱动
{ /* sentinel */ }
};
// 若设备树中 compatible 为 "raspberrypi,gpio-leds",则加载定制驱动
// 否则回退到通用 "gpio-leds" 驱动
5. 兼容性扩展:屏幕控制器
设备树节点:
lcdc@021c0000 {
compatible = "fsl,imx6q-lcdif", "simple-panel";
reg = <0x021c0000 0x4000>;
// ...
};
驱动逻辑:
- 优先尝试
fsl,imx6q-lcdif(NXP i.MX6Q 的 LCD 控制器驱动)。 - 若未找到,则尝试
simple-panel(通用面板驱动,仅支持基础功能)。
6. 验证兼容性匹配
步骤 1:编译设备树
dtc -I dts -O dtb -o myboard.dtb myboard.dts
步骤 2:查看内核解析结果
cat /proc/device-tree/pwm@020c0000/compatible
# 输出应为:fsl,imx6q-pwm\0brcm,bcm2835-pwm\0
步骤 3:检查驱动加载日志
[ 1.234567] pwm-imx: probe of pwm@020c0000 failed with error -22
# 错误示例:若驱动未匹配,检查 compatible 字符串是否与驱动中的 of_match_table 一致
关键规则总结
- 优先级顺序:设备树中的
compatible字符串按从左到右顺序匹配,驱动代码中的of_match_table同理。 - 唯一性:厂商缩写(如
fsl,brcm)需唯一,设备型号需明确(如imx6q-pwm)。 - 回退机制:通过追加通用字符串(如
simple-bus)实现驱动兼容性降级。
通过合理设计 compatible 属性,可确保硬件与驱动的精准匹配,同时提高代码复用性。
1.内核在匹配驱动和设备的过程中,compatible 属性发生的作用举例,最好有具体的代码
在 Linux 内核中,compatible 属性是驱动与设备匹配的核心纽带。以下通过具体代码示例和内核源码分析,完整展示其作用机制:
1. 设备树节点定义(.dts 文件)
// arch/arm/boot/dts/imx6q-sabresd.dts
pwm@020c0000 {
compatible = "fsl,imx6q-pwm"; // 唯一匹配标识
reg = <0x020c0000 0x4000>;
#pwm-cells = <2>; // 定义 PWM 通道参数格式
};
2. 驱动代码中的 of_device_id 匹配表
// drivers/pwm/pwm-imx.c
#include <linux/of.h>
static const struct of_device_id pwm_of_match[] = {
{ .compatible = "fsl,imx6q-pwm" }, // 精确匹配此字符串
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pwm_of_match);
// PWM 驱动结构体
static struct platform_driver imx_pwm_driver = {
.driver = {
.name = "imx-pwm",
.of_match_table = pwm_of_match, // 绑定匹配表
},
.probe = imx_pwm_probe,
.remove = imx_pwm_remove,
};
3. 内核匹配流程详解
步骤 1:设备树解析
- 内核启动时,
dtc编译器将.dts转换为二进制设备树(.dtb)。 - 解析到
pwm@020c0000节点时,提取compatible = "fsl,imx6q-pwm"。
步骤 2:驱动注册
- 驱动通过
platform_driver_register(&imx_pwm_driver)注册自身。 - 内核将驱动的
of_match_table存入全局链表。
步骤 3:设备-驱动匹配
- 内核遍历所有注册的驱动,调用
of_match_device()函数:// lib/of_platform.c const struct of_device_id *of_match_device(const struct of_device_id *matches, const struct device *dev) { // 从设备树节点获取 compatible 字符串 const char *compat = of_get_property(dev->of_node, "compatible", NULL); if (!compat) return NULL; // 遍历驱动的 of_match_table while (matches->compatible[0]) { if (of_device_is_compatible(dev->of_node, matches->compatible)) return matches; matches++; } return NULL; }of_device_is_compatible()会逐字符比较设备树的compatible字符串与驱动匹配表中的条目。- 若完全匹配(如
fsl,imx6q-pwm),则返回对应的of_device_id条目。
步骤 4:驱动绑定
- 匹配成功后,内核调用驱动的
probe函数(如imx_pwm_probe),完成硬件初始化。
4. 关键代码路径追踪
- 设备树解析:
dtb加载:arch/arm/kernel/devtree.c::unflatten_device_tree()- 提取
compatible:lib/of.c::of_get_property()
- 驱动匹配:
- 入口函数:
drivers/base/platform.c::platform_match() - 匹配逻辑:
lib/of_platform.c::of_match_device()
- 入口函数:
- 驱动绑定:
probe调用:drivers/base/dd.c::driver_probe_device()
5. 调试技巧
- 查看驱动匹配日志:
[ 1.234567] pwm-imx: probe of pwm@020c0000 failed with error -22-22表示EINVAL,通常因compatible字符串不匹配或硬件地址错误。
- 手动验证匹配:
# 查看内核解析后的设备树 cat /proc/device-tree/pwm@020c0000/compatible # 输出应为:fsl,imx6q-pwm # 检查驱动是否注册 lsmod | grep pwm_imx
6. 扩展场景:多兼容字符串
若设备树节点定义多个 compatible 字符串:
compatible = "fsl,imx6q-pwm", "brcm,bcm2835-pwm";
- 内核会按顺序尝试匹配驱动中的
of_match_table。 - 若驱动 A 匹配
fsl,imx6q-pwm,驱动 B 匹配brcm,bcm2835-pwm,则优先加载驱动 A。
通过上述代码和流程分析可见,compatible 属性是驱动与设备通信的“密码”,内核通过严格的字符串匹配确保硬件被正确初始化。理解此机制对嵌入式开发、驱动调试至关重要。
7.关系分析

2.设备树的 compatible 属性
在 Linux 设备树(Device Tree)中,compatible 属性是驱动与硬件匹配的核心标识,用于将硬件描述与内核驱动绑定。以下是详细解释:
1. 语法与结构
- 格式:
compatible = "厂商缩写,设备型号", "通用兼容字符串";- 示例:
compatible = "fsl,imx6q-pwm", "brcm,bcm2835-pwm";
- 示例:
- 规则:
- 厂商缩写:通常为大写(如
fsl代表 Freescale/NXP,brcm代表 Broadcom)。 - 设备型号:唯一标识硬件(如
imx6q-pwm表示 i.MX6Q 的 PWM 控制器)。 - 兼容字符串:可包含多个值,按优先级排序(内核会尝试从左到右匹配驱动)。
- 厂商缩写:通常为大写(如
2. 核心作用
-
驱动匹配:
内核通过compatible字符串匹配设备树节点与驱动。驱动代码中通过of_match_table定义支持的字符串列表:static const struct of_device_id pwm_of_match[] = { { .compatible = "fsl,imx6q-pwm" }, { .compatible = "brcm,bcm2835-pwm" }, { /* sentinel */ } };兼容性扩展:
如果硬件与现有驱动兼容但型号不同,可通过追加通用字符串(如"simple-pwm")实现复用。
3. 实际应用场景
-
新增硬件支持:
当开发新硬件时,需为设备树节点定义唯一的compatible字符串,并确保驱动代码中包含该字符串的匹配项。 -
驱动调试:
若驱动未加载,可通过内核日志(dmesg)检查匹配过程:[ 1.234567] pwm-imx: probe of pwm@020c0000 failed with error -22此处
-22表示EINVAL(无效参数),可能因compatible字符串不匹配或硬件地址错误。
4. 最佳实践
-
唯一性:
避免重复使用其他厂商的compatible字符串,防止驱动冲突。 -
版本控制:
若硬件有修订版本,可在字符串中追加版本号(如"fsl,imx6q-pwm-v2")。 -
文档参考:
查阅芯片厂商的文档(如 NXP 的 i.MX 参考手册)获取官方推荐的compatible名称。
5. 工具验证
-
编译检查:
使用设备树编译器(dtc)编译.dts文件,检查语法错误:dtc -I dts -O dtb -o myboard.dtb myboard.dts -
运行时验证:
通过/proc/device-tree/查看内核解析后的设备树:cat /proc/device-tree/pwm@020c0000/compatible输出应为:
fsl,imx6q-pwm\0brcm,bcm2835-pwm\0
6. 常见问题
-
驱动未匹配:
检查compatible字符串是否与驱动中的of_match_table完全一致(包括大小写)。 -
字符串顺序:
内核按顺序匹配,优先使用第一个匹配的驱动。若需覆盖默认行为,可调整字符串顺序。
通过合理设计 compatible 属性,可以确保硬件与驱动的精准匹配,是嵌入式系统开发中的关键步骤。
5465

被折叠的 条评论
为什么被折叠?



