4. DTS设备树配置:RK3588/RK356x平台实战
设备树(Device Tree Source,DTS)是嵌入式Linux驱动开发的基石。说白了,它就是一份硬件描述清单,告诉内核:你有哪些外设、它们挂在哪里、用什么时钟和GPIO。
我在RK3588和RK356x上调试Sensor驱动时,遇到过好几次DTS写错导致系统起不来的情况。嗯,这章我们就来把DTS的配置逻辑彻底理清楚。
4.1 DTS基础结构
一个完整的Sensor DTS节点,通常包含以下几部分:
- compatible:驱动匹配的关键字符串
- reg:I2C地址或寄存器基址
- clocks:时钟资源绑定
- pinctrl:引脚复用配置
- power-domains:电源域控制
- avdd/dovdd/dvdd:电源 regulator 绑定
核心原则:DTS只描述硬件,不描述行为。行为是驱动的事。
4.2 时钟资源绑定实战
Sensor通常需要两个时钟:MCLK(主时钟)和PCLK(外设时钟)。RK3588的时钟树比较复杂,我建议直接使用clk-provider方式绑定。
// RK3588 Sensor时钟节点示例
sensor_mclk: sensor-mclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>; // 24MHz
clock-output-names = "sensor_mclk";
};
// Sensor节点中引用
i2c2: i2c@fdd40000 {
status = "okay";
sensor0: sensor@30 {
compatible = "ov5648";
reg = <0x30>;
clocks = <&cru CLK_MIPI_CAMERA0>,
<&sensor_mclk>;
clock-names = "xvclk", "mclk";
// 时钟频率配置
assigned-clocks = <&cru CLK_MIPI_CAMERA0>;
assigned-clock-rates = <24000000>;
};
};
我的经验:RK3588的CLK_MIPI_CAMERA0默认是24MHz,但有些Sensor需要27MHz。记得检查Sensor datasheet,别想当然。
4.3 GPIO与pinctrl配置
GPIO配置是DTS里最容易出错的地方。RK平台使用pinctrl子系统管理引脚复用,每个引脚可以配置为GPIO、I2C、SPI等功能。
4.3.1 pinctrl节点定义
// pinctrl配置
&pinctrl {
sensor_pins: sensor-pins {
rockchip,pins =
// 复位引脚:GPIO4_B5,默认输出高
<4 RK_PB5 RK_FUNC_GPIO &pcfg_output_high>,
// 电源使能:GPIO4_B6,默认输出低
<4 RK_PB6 RK_FUNC_GPIO &pcfg_output_low>,
// 中断引脚:GPIO4_B7,上拉输入
<4 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
4.3.2 Sensor节点引用pinctrl
sensor0: sensor@30 {
compatible = "ov5648";
reg = <0x30>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sensor_pins>;
pinctrl-1 = <&sensor_pins_sleep>;
// GPIO资源
reset-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
power-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
irq-gpios = <&gpio4 RK_PB7 GPIO_ACTIVE_HIGH>;
};
我曾经踩过的坑:RK3588的GPIO bank编号从0开始,但有些文档写的是1开始。我因为搞混了bank号,浪费了整整一天。建议直接看TRM的GPIO章节,别信二手资料。
4.4 电源管理配置
Sensor通常需要三路电源:AVDD(模拟)、DOVDD(数字IO)、DVDD(数字核心)。RK平台推荐使用regulator框架管理。
| 电源名称 | 典型电压 | regulator绑定 | 备注 |
|---|---|---|---|
| AVDD | 2.8V | avdd-supply | 模拟电源,噪声敏感 |
| DOVDD | 1.8V | dovdd-supply | IO电源,与SoC电平匹配 |
| DVDD | 1.2V | dvdd-supply | 核心电源,电流较大 |
// regulator节点
vcc_avdd: regulator-avdd {
compatible = "regulator-fixed";
regulator-name = "vcc_avdd";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
regulator-boot-on;
gpio = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
// Sensor节点引用
sensor0: sensor@30 {
avdd-supply = <&vcc_avdd>;
dovdd-supply = <&vcc_dovdd>;
dvdd-supply = <&vcc_dvdd>;
};
4.5 完整DTS示例:RK3588 + OV5648
下面是一个完整的实战配置,我把它整理成了可复用的模板:
// RK3588 OV5648 DTS配置
#include "rk3588.dtsi"
&i2c2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c2m0_xfer>;
ov5648: camera@36 {
compatible = "ovti,ov5648";
reg = <0x36>;
// 时钟配置
clocks = <&cru CLK_MIPI_CAMERA0>;
clock-names = "xvclk";
assigned-clocks = <&cru CLK_MIPI_CAMERA0>;
assigned-clock-rates = <24000000>;
// pinctrl
pinctrl-names = "default";
pinctrl-0 = <&camera_pins>;
// GPIO
reset-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
pwdn-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
// 电源
avdd-supply = <&vcc_avdd>;
dovdd-supply = <&vcc_dovdd>;
dvdd-supply = <&vcc_dvdd>;
// MIPI CSI配置
port {
ov5648_out: endpoint {
remote-endpoint = <&mipi_csi2_input>;
data-lanes = <1 2>;
};
};
};
};
&pinctrl {
camera_pins: camera-pins {
rockchip,pins =
<4 RK_PB5 RK_FUNC_GPIO &pcfg_output_high>,
<4 RK_PB6 RK_FUNC_GPIO &pcfg_output_low>;
};
};
关键检查点:编译DTS时,用make dtbs检查语法错误。我习惯在arch/arm64/boot/dts/rockchip/目录下直接编译,方便快速迭代。
4.6 DTS调试技巧
DTS写对了,但系统不认?别急,我总结了几条实用技巧:
- 查看设备树是否加载:
ls /proc/device-tree/检查节点是否存在 - 检查GPIO状态:
cat /sys/kernel/debug/gpio查看引脚复用 - 时钟调试:
cat /sys/kernel/debug/clk/clk_summary确认时钟频率 - I2C探测:
i2cdetect -y 2确认Sensor地址是否正确
我的习惯:每次修改DTS后,先diff对比一下改动,避免手误。我曾经因为多打了一个分号,导致整个I2C总线挂掉,查了半小时才发现。
4.7 知识体系图
下面这张图总结了DTS配置的核心流程和资源绑定关系:
4.8 常见错误与避坑
| 错误类型 | 现象 | 解决方案 |
|---|---|---|
| GPIO bank号错误 | Sensor无法复位 | 核对TRM,GPIO0-4对应bank0-4 |
| 时钟频率不匹配 | MIPI无信号 | 检查assigned-clock-rates与实际需求 |
| regulator缺失 | Sensor上电失败 | 确保所有supply都绑定到有效regulator |
| pinctrl冲突 | 引脚被其他外设占用 | 检查pinctrl状态,避免复用冲突 |
我曾经犯过的错:在RK3568上,我把Sensor的复位引脚配置成了GPIO_ACTIVE_HIGH,但Sensor手册要求低电平复位。结果Sensor一直处于复位状态,I2C都探测不到。嗯,从那以后我每次都会仔细检查GPIO的极性。
DTS配置是Sensor驱动开发的第一步,也是最重要的一步。写对了,后面调试就顺风顺水;写错了,可能连系统都起不来。我个人建议:每次修改DTS后,先编译检查,再烧录验证,别偷懒。