4. 设备树I2C节点:设备树语法、I2C子节点属性与地址属性解析
在RK平台Sensor驱动开发中,设备树(Device Tree)是描述硬件拓扑与资源分配的核心机制。I2C总线上的Sensor设备,必须通过设备树中的I2C子节点向内核传递设备地址、中断号、电源域等关键信息。本章将深入解析设备树I2C节点的语法结构、三大核心属性(compatible、reg、interrupts)以及地址映射的底层逻辑。
of_match_table匹配compatible属性,通过reg属性获取I2C从设备地址,通过interrupts属性注册中断处理函数。
4.1 设备树I2C节点语法结构
设备树采用树形结构描述硬件,I2C控制器作为总线节点,其下挂载的Sensor作为子节点。一个标准的I2C设备树节点包含以下层级:
- 根节点:
/,包含所有硬件信息。 - I2C控制器节点:如
&i2c1,描述I2C总线本身的属性(时钟频率、引脚配置等)。 - Sensor子节点:在I2C控制器节点内部,描述具体的Sensor设备。
以下是一个RK3588平台上I2C1总线挂载加速度传感器(BMI160)的完整设备树片段:
&i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c1m0_xfer>;
clock-frequency = <400000>; /* 400kHz 高速模式 */
bmi160: accelerometer@68 {
compatible = "bosch,bmi160";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <RK_PB2 IRQ_TYPE_EDGE_RISING>;
vdd-supply = <&vcc_3v3>;
vddio-supply = <&vcc_1v8>;
mount-matrix = "0", "1", "0",
"-1", "0", "0",
"0", "0", "1";
};
};
- 子节点名称格式:
设备名@I2C地址(如accelerometer@68),地址必须与reg属性一致。 status = "okay"使能节点;status = "disabled"禁用节点。pinctrl-0引用引脚复用配置,确保I2C总线引脚功能正确。
4.2 三大核心属性详解
4.2.1 compatible 属性:驱动匹配的钥匙
compatible属性是设备与驱动之间的“身份证”。内核通过设备树中的compatible字符串,在驱动注册的of_match_table中查找匹配项,从而将设备绑定到正确的驱动。
| 属性字段 | 格式 | 示例 | 说明 |
|---|---|---|---|
| compatible | "厂商,设备型号" |
"bosch,bmi160" |
厂商前缀+设备型号,内核优先匹配最具体的字符串 |
| 兼容列表 | 多个字符串,用空格分隔 | "bosch,bmi160", "bosch,bmi" |
可提供多个兼容型号,内核按顺序匹配 |
compatible字符串必须与驱动中of_device_id表完全一致,包括大小写和标点符号。- 厂商前缀应遵循内核规范(如
bosch、invensense、st),不要随意自定义。 - 如果设备兼容多个型号,将最具体的型号放在最前面。
4.2.2 reg 属性:I2C从设备地址的载体
reg属性定义了设备在I2C总线上的从设备地址(7位或10位地址)。对于I2C设备,reg的第一个单元格是地址值,第二个单元格(可选)是地址长度。
/* 7位地址示例:0x68 */
reg = <0x68>;
/* 10位地址示例:0x3C0,需要指定地址长度 */
reg = <0x3C0 0x2>; /* 0x2 表示10位地址占用2个字节 */
| 地址类型 | 地址范围 | reg格式 | 常见设备 |
|---|---|---|---|
| 7位地址 | 0x08 ~ 0x77 | reg = <0x68> |
BMI160、MPU6050、LSM6DS3 |
| 10位地址 | 0x00 ~ 0x3FF | reg = <0x3C0 0x2> |
部分数字麦克风、扩展IO芯片 |
- Sensor的I2C地址通常由芯片的ADDR引脚电平决定(高电平或低电平对应不同地址)。
- 在设备树中配置的
reg地址必须与硬件原理图一致,否则驱动无法访问设备。 - RK平台I2C驱动通过
i2c_client结构体的addr字段获取reg值,驱动开发时可通过client->addr读取。
4.2.3 interrupts 属性:中断资源的声明
interrupts属性声明Sensor设备使用的中断资源,包括中断控制器、中断引脚、触发类型。RK平台通常使用GPIO作为中断源,通过interrupt-parent指定GPIO控制器。
/* 完整中断属性示例 */
interrupt-parent = <&gpio1>; /* 中断父控制器:GPIO1 */
interrupts = <RK_PB2 IRQ_TYPE_EDGE_RISING>; /* 引脚PB2,上升沿触发 */
| 中断属性字段 | 说明 | RK平台常用值 |
|---|---|---|
| interrupt-parent | 指定中断控制器(GPIO或GIC) | &gpio0 ~ &gpio4 |
| interrupts | 中断号、触发类型 | RK_PA0 IRQ_TYPE_EDGE_RISING |
| IRQ_TYPE_EDGE_RISING | 上升沿触发 | 适用于数据就绪中断 |
| IRQ_TYPE_LEVEL_LOW | 低电平触发 | 适用于中断引脚低电平有效 |
interrupt-parent指向错误的GPIO控制器,导致中断无法注册。- 中断触发类型与Sensor芯片规格不匹配(如芯片要求下降沿,却配置为上升沿)。
- 多个Sensor共享同一中断引脚时,未配置
IRQ_TYPE_NONE或共享中断处理逻辑。
4.3 地址属性解析与I2C核心交互
当内核启动并解析设备树时,I2C核心框架会遍历每个I2C控制器节点的子节点,提取reg属性中的地址值,并调用i2c_new_device或of_i2c_register_devices创建i2c_client结构体。驱动通过i2c_client的addr字段获取设备地址,进而发起I2C通信。
/* 内核I2C核心解析reg属性的简化流程 */
static struct i2c_client *of_i2c_register_device(struct device_node *node)
{
struct i2c_client *client;
u32 addr;
/* 从设备树节点读取reg属性中的地址值 */
if (of_property_read_u32(node, "reg", &addr)) {
dev_err(dev, "missing reg property\n");
return ERR_PTR(-EINVAL);
}
/* 创建i2c_client,并将地址赋值给client->addr */
client = kzalloc(sizeof(*client), GFP_KERNEL);
client->addr = addr;
/* ... 其他初始化 ... */
return client;
}
probe函数中,通过client->addr获取设备地址,并使用i2c_smbus_read_byte_data或i2c_transfer进行寄存器读写。如果设备树中reg配置错误,驱动将无法找到设备,i2c_smbus_read会返回-ENXIO(无此设备)错误。
4.4 设备树I2C节点实战案例:RK3588 + BMI160
以下是一个完整的RK3588平台设备树I2C节点配置案例,包含所有关键属性,并附有详细注释:
/* RK3588设备树 - I2C1总线挂载BMI160加速度传感器 */
&i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c1m0_xfer>;
clock-frequency = <400000>; /* 400kHz高速模式 */
/* BMI160传感器子节点 */
bmi160: accelerometer@68 {
/* 驱动匹配标识:厂商前缀+设备型号 */
compatible = "bosch,bmi160";
/* I2C从设备地址:7位地址0x68(ADDR引脚接GND) */
reg = <0x68>;
/* 中断配置:GPIO1_B2,上升沿触发 */
interrupt-parent = <&gpio1>;
interrupts = <RK_PB2 IRQ_TYPE_EDGE_RISING>;
/* 电源域:数字核心电压和IO电压 */
vdd-supply = <&vcc_3v3>;
vddio-supply = <&vcc_1v8>;
/* 安装方向矩阵:定义Sensor坐标系与设备坐标系的映射 */
mount-matrix = "0", "1", "0",
"-1", "0", "0",
"0", "0", "1";
};
};
- ✅
compatible是否与驱动of_device_id表完全一致? - ✅
reg地址是否与硬件原理图上的I2C地址一致? - ✅
interrupt-parent是否指向正确的GPIO控制器? - ✅ 中断触发类型是否与Sensor数据手册一致?
- ✅ 电源域
vdd-supply和vddio-supply是否已正确定义?
4.5 本章小结
设备树I2C节点是Sensor驱动与硬件之间的桥梁。通过本章学习,你应掌握:
- 设备树节点层级:根节点 → I2C控制器节点 → Sensor子节点,每个层级承载不同的硬件描述。
- 三大核心属性:
compatible(驱动匹配)、reg(I2C地址)、interrupts(中断资源),是驱动开发中最常配置的字段。 - 地址解析流程:从设备树
reg属性到i2c_client->addr,再到I2C通信的完整链路,任何环节的地址不一致都会导致通信失败。