3. I2C设备树绑定:设备树节点语法、compatible属性、reg地址配置
在车载嵌入式Linux系统中,I2C外设的硬件拓扑与驱动匹配完全依赖设备树(Device Tree)描述。设备树节点是驱动与硬件之间的“契约”,其中compatible属性决定驱动匹配,reg属性定义I2C从设备地址。本节将深入解析I2C设备树绑定的核心语法与实战配置。
3.1 I2C设备树节点基本语法
一个标准的I2C从设备节点必须嵌套在I2C控制器节点内部,并遵循以下结构:
&i2c1 {
status = "okay";
clock-frequency = <400000>; /* 400kHz Fast Mode */
/* I2C从设备节点 */
temperature-sensor@48 {
compatible = "ti,tmp102", "ti,tmp101";
reg = <0x48>;
interrupt-parent = <&gpio2>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
};
};
| 节点元素 | 说明 | 示例值 |
|---|---|---|
节点名称@地址 |
设备节点名,@后跟I2C从设备地址(7位) | temperature-sensor@48 |
compatible |
驱动匹配字符串,优先使用第一个 | "ti,tmp102", "ti,tmp101" |
reg |
I2C从设备地址(7位或10位) | <0x48> |
interrupt-parent |
中断控制器phandle | &gpio2 |
interrupts |
中断号与触发类型 | <5 IRQ_TYPE_EDGE_FALLING> |
车载经验提示:I2C节点名称中的
@地址必须与reg属性值一致,否则设备树编译器(DTC)会报地址不匹配警告。在车载多传感器共线场景中,此错误极易导致驱动加载失败。
3.2 compatible属性:驱动匹配的核心
compatible属性是一个字符串列表,内核通过该属性在驱动列表中查找匹配项。匹配规则遵循“最精确优先”原则:
- 第一字符串:精确的芯片型号,如
"ti,tmp102"。 - 后续字符串:兼容的通用型号或系列名,如
"ti,tmp101"。 - 驱动端匹配:使用
of_match_table结构体定义。
/* 驱动端匹配表示例 */
static const struct of_device_id tmp102_of_match[] = {
{ .compatible = "ti,tmp102", .data = &tmp102_config },
{ .compatible = "ti,tmp101", .data = &tmp101_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tmp102_of_match);
| 场景 | compatible写法 | 匹配结果 |
|---|---|---|
| 精确匹配 | "ti,tmp102" |
仅匹配tmp102专用驱动 |
| 兼容匹配 | "ti,tmp102", "ti,tmp101" |
优先匹配tmp102,其次tmp101 |
| 厂商前缀错误 | "nxp,tmp102" |
匹配失败,驱动无法加载 |
常见陷阱:车载项目中常因
compatible字符串大小写或厂商前缀不一致导致驱动不匹配。务必与芯片数据手册和内核驱动源码中的字符串完全一致。
3.3 reg地址配置:7位与10位地址
reg属性定义I2C从设备的从机地址。I2C总线支持7位和10位两种地址模式:
- 7位地址:范围
0x00 ~ 0x7F,常用地址如0x48、0x50。 - 10位地址:范围
0x000 ~ 0x3FF,需在节点中显式声明reg = <0x10 0x00>格式。
/* 7位地址示例 */
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
};
/* 10位地址示例(罕见,需控制器支持) */
sensor@10 {
compatible = "vendor,10bit-sensor";
reg = <0x10 0x00>; /* 高5位 + 低7位 */
reg-names = "i2c-addr";
};
车载调试要点:使用
i2cdetect -y <bus> 扫描总线确认设备地址。若设备树中reg地址与硬件实际地址不符,驱动探测阶段将返回-ENXIO错误。
3.4 I2C设备树绑定完整流程图
下图展示了从设备树节点到驱动匹配、设备注册的完整流程:
3.5 车载I2C设备树绑定实战案例
以车载胎压监测传感器(TPMS)和环境光传感器(ALS)挂载在同一I2C总线为例:
&i2c3 {
status = "okay";
clock-frequency = <100000>; /* 100kHz Standard Mode */
pinctrl-0 = <&i2c3_pins>;
/* TPMS传感器 */
tpms@60 {
compatible = "infineon,sp40", "infineon,sp37";
reg = <0x60>;
interrupt-parent = <&gpio1>;
interrupts = <3 IRQ_TYPE_EDGE_RISING>;
pressure-threshold = <1800>; /* 自定义属性 */
};
/* 环境光传感器 */
ambient-light@44 {
compatible = "rohm,bh1750";
reg = <0x44>;
measurement-mode = <2>; /* 连续高分辨率模式 */
};
};
| 设备 | compatible | reg地址 | 中断配置 |
|---|---|---|---|
| TPMS传感器 | "infineon,sp40" |
0x60 |
GPIO1_3,上升沿触发 |
| 环境光传感器 | "rohm,bh1750" |
0x44 |
无中断(轮询模式) |
车载设计建议:同一I2C总线上的设备地址不能冲突。使用
i2cdetect扫描确认地址唯一性。若地址冲突,需通过硬件地址引脚或I2C多路复用器(如PCA9548)解决。
3.6 设备树绑定常见错误与调试
在车载I2C设备树调试中,以下错误最为常见:
- 地址格式错误:
reg = <0x48>误写为reg = <72>(十进制),导致地址不匹配。 - compatible拼写错误:厂商前缀或型号大小写不一致,如
"TI,tmp102"而非"ti,tmp102"。 - 中断号越界:
interrupts指定的GPIO引脚号超出控制器范围。 - status遗漏:父节点或子节点未设置
status = "okay",设备被禁用。
/* 错误示例:地址冲突 + compatible拼写错误 */
&i2c2 {
status = "okay";
sensor@48 {
compatible = "Ti,Tmp102"; /* 错误:大小写不一致 */
reg = <0x48>;
};
eeprom@48 { /* 错误:地址0x48已被占用 */
compatible = "atmel,24c02";
reg = <0x48>;
};
};
调试命令速查:
dtc -I dtb -O dts -o output.dts input.dtb — 反编译DTB检查节点ls /sys/bus/i2c/devices/ — 查看已注册的I2C设备cat /proc/interrupts | grep i2c — 查看I2C中断分配