ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RK3568设备树实战:从DTS修改到外设驱动全链路解析

RK3568设备树实战:从DTS修改到外设驱动全链路解析 1. 为什么RK3568的DTS修改不是“改个文件就完事”——设备树的本质是硬件与内核的契约你手上那块RK3568开发板从上电那一刻起Linux内核根本不知道它连着什么外设是OV5695摄像头还是YT8521千兆PHY抑或是正点原子扩展板上的EtherCAT从站芯片内核不会主动去“猜”它只相信一份白纸黑字的协议——设备树Device Tree。这份协议不是代码注释不是配置文档而是内核启动时唯一认可的硬件描述语言。DTS文件就是这份协议的源码而DTC编译器生成的DTB二进制文件才是内核真正读取的“合同正文”。很多人卡在第一步改完DTS烧录后设备没反应、驱动不加载、甚至内核panic。问题往往不在驱动代码里而在你写的DTS节点里——一个compatible字符串拼错整个节点就被内核忽略一个reg地址写偏4字节DMA直接访问到内存禁区一个interrupts属性少写一个参数中断永远不来。我第一次调试RK3568触摸屏横竖屏切换时就因为orientation属性没加到正确的touchscreen子节点下折腾了整整两天最后发现是节点层级嵌套错了——这根本不是驱动问题是契约条款写得不规范。所以DTS修改不是文本编辑是在硬件工程师和内核开发者之间当翻译官你要把原理图上的每一个焊点、每一根走线、每一个寄存器映射关系精准地翻译成内核能理解的语法结构。正点原子RK3568开发板配套的DTS文件里i2c2节点默认只启用了EEPROM但如果你要接OV5695就必须手动添加camera子节点并确保phys、phy-names、clocks这些属性与RK3568 SoC的MIPI CSI控制器手册完全对齐。这不是“试试看”而是逐字逐句对照数据手册的工程实践。这也是为什么网络上搜“rk3568 触摸竖屏改为横屏设备树修改”结果一堆人说“改了没用”——他们改的是屏幕旋转参数却没动display-timings里timing参数对应的物理分辨率定义内核初始化时依然按竖屏时序发信号硬件当然不认。真正的设备树实战起点永远是打开RK3568 TRM手册第12章找到你要配的外设控制器章节抄下所有寄存器基地址、中断号、时钟ID再对照内核Documentation/devicetree/bindings/下的对应binding文档一个字段一个字段填。跳过这步后面所有操作都是空中楼阁。2. DTS文件结构解剖从.dts到.dtb的完整编译链与关键节点定位RK3568的DTS生态不是单个文件而是一套分层继承体系。以官方SDK中的rk3568-evb.dts为例它本身只有不到200行但通过#include层层引用最终展开超万行代码。理解这个结构是避免误改、快速定位的关键。整个链条像一棵倒挂的树最顶层是SoC级描述arch/arm64/boot/dts/rockchip/rk3568.dtsi定义CPU、内存控制器、主干总线arm-pmu、gic、pinctrl等所有RK3568芯片共有的硬件中间层是板级基础描述rk3568-evb.dtsi定义核心板上的固定外设如eMMC、USB PHY、PMIC最底层才是具体开发板的定制文件rk3568-evb.dts只写扩展槽、用户IO、特定传感器等差异化部分。这种设计让同一份SoC描述能复用于RK3566/RK3568/RK3588避免重复劳动。但陷阱也在这里你想改I2C2的时钟频率必须去rk3568.dtsi里找i2c2节点而不是在rk3568-evb.dts里自己重写一个——后者会因节点名冲突被编译器报错。我见过太多人在evb.dts里直接写i2c2 { status okay; };结果编译失败因为dtsi里已定义同名节点DTS语法要求同名节点自动合并但status属性必须在原始定义处修改。正确做法是在evb.dts中使用i2c2标签然后只覆盖需要改的属性。比如启用I2C2并添加OV5695i2c2 { status okay; clock-frequency 400000; ov5695: camera36 { compatible ovti,ov5695; reg 0x36; clocks cru CLK_I2C2; clock-names mclk; #address-cells 1; #size-cells 0; port { ov5695_0: endpoint { remote-endpoint mipi_in_cam0; }; }; }; };注意这里i2c2前的符号——它表示引用已有节点而非新建。status okay是使能该I2C控制器clock-frequency设为400kHz是OV5695手册要求的最高I2C速率。ov5695:是该设备的别名用于在其他节点中通过ov5695引用。port子节点定义了视频数据流路径remote-endpoint指向MIPI CSI接收端这是RK3568 MIPI子系统绑定的关键。编译过程同样关键make ARCHarm64 rk3568-evb-dtb命令背后dtc工具先将所有.dtsi和.dts文件预处理合并再语法检查最后生成.dtb。如果dtc报错Label or path i2c2 not found说明你写的i2c2在上游dtsi中根本不存在——可能你用的是RK3566的dtsi而RK3566的I2C控制器编号和RK3568不同。查证方法很简单grep -r i2c2 arch/arm64/boot/dts/rockchip/rk3568.dtsi确认节点是否存在及路径。另外CONFIG_OF_OVERLAYy内核配置必须开启否则动态加载overlay会失败这对调试阶段频繁修改DTS极其重要。我习惯在menuconfig中搜索OF_OVERLAY确保它被编译进内核镜像而不是模块——避免启动时因模块未加载导致overlay失效。最后提醒一个血泪教训修改DTS后务必执行make clean再make dtbs否则旧的.dtb文件可能被缓存烧录的仍是旧版本。曾有同事连续三天改DTS无效最后发现out/目录下残留旧dtbmake dtbs没清掉它。3. 外设节点配置实战从PHY芯片到摄像头手把手拆解5类高频需求网络热词里反复出现的yt8521设备树配置、rk3568调试ov5695、phy设备树配置本质都是同一套逻辑根据芯片手册填写binding文档规定的必填字段。下面以5类最常遇到的外设为例逐个拆解真实配置过程附带避坑要点。3.1 YT8521千兆PHY配置网口不通的90%原因在此YT8521是瑞芯微平台常用PHY但它的设备树配置极易出错。首先确认硬件连接RK3568的GMAC0通常接YT8521走RGMII接口。关键点在于phy-mode必须与硬件设计严格一致。若原理图上GMAC0的TXC/RXC是独立时钟线非共享则phy-mode rgmii-id若共用时钟则为rgmii-rxid。写错会导致PHY初始化失败dmesg | grep gmac看到link down。正确配置如下gmac0 { status okay; phy-mode rgmii-id; phy-handle yt8521; phy-supply vcc_phy; #address-cells 1; #size-cells 0; yt8521: ethernet-phy0 { compatible ethernet-phy-ieee802.3-c22; reg 0; clocks cru CLK_GMAC0_PHY; clock-names ref; /* YT8521特有属性 */ rockchip,grf grf; rockchip,phy-reg 0x10; /* 若需强制1000M全双工 */ // speed 1000; // duplex 1; }; };注意phy-handle yt8521必须指向PHY节点reg 0是PHY地址由硬件跳线决定常见为0或1。rockchip,grf是RK平台特有属性指向通用寄存器框架用于配置PHY复位等。最大坑点phy-supply必须指向正确的LDO电源YT8521需要2.5V和1.0V两路供电vcc_phy在rk3568-evb.dtsi中已定义若你用自定义板必须先在pinctrl节点里声明该LDO。漏掉phy-supplyPHY根本得不到电ethtool eth0显示No data available。3.2 OV5695摄像头调试MIPI CSI链路打通三步法OV5695通过MIPI CSI2连接RK3568配置比I2C复杂得多涉及三个子系统联动I2C配置寄存器、MIPI传输图像、V4L2驱动框架。第一步是I2C节点前文已示第二步是MIPI CSI控制器节点csi0 { status okay; ports { #address-cells 1; #size-cells 0; port0 { reg 0; csi0_in: endpoint { remote-endpoint ov5695_0; >isp0 { status okay; }; rockchip_vir0 { status okay; rockchip,camera-module-name ov5695; rockchip,camera-module-lens-name none; port { rockchip_mipi_in: endpoint { remote-endpoint csi0_out; }; }; };rockchip_vir0是RK的虚拟ISP节点remote-endpoint指向CSI0的输出端。实操心得调试时先用v4l2-ctl --list-devices看是否识别到rkisp1_mainpath设备再用media-ctl -p /dev/media0查看pipeline连接状态。若ov5695节点没出现在graph里一定是I2C或CSI节点的remote-endpoint引用错误——用dtc -I dtb -O dts -o temp.dts /boot/rockchip.dtb反编译当前dtb搜索ov5695确认其endpoint是否被正确解析。3.3 EtherCAT主站配置IGH驱动与设备树的协同正点原子RK3568 EtherCAT方案依赖IGH主站驱动其设备树配置核心是为EtherCAT从站芯片分配正确的SPI或GPIO资源。假设从站芯片通过SPI连接如ET1100配置如下spi1 { status okay; #address-cells 1; #size-cells 0; et11000 { compatible beckhoff,et1100; reg 0; spi-max-frequency 10000000; interrupts GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH; interrupt-parent gic; /* ET1100复位引脚 */ reset-gpios gpio0 12 GPIO_ACTIVE_LOW; /* 同步管理器引脚 */ sm-gpios gpio0 13 GPIO_ACTIVE_HIGH, gpio0 14 GPIO_ACTIVE_HIGH; }; };interrupts必须与RK3568中断控制器手册核对GIC_SPI 42对应SPI1的IRQ线。reset-gpios和sm-gpios是IGH驱动要求的硬性接口。关键提示IGH驱动编译时需开启CONFIG_ETHERCAT_MASTERy且DTS中compatible beckhoff,et1100必须与驱动中of_match_table完全一致字母大小写都不能错。网络上搜适配rk3568的ethercat igh主站驱动很多教程漏掉interrupt-parent导致中断无法注册ec_master进程启动后立即退出。3.4 触摸屏横竖屏切换不只是rotation参数rk3568 触摸竖屏改为横屏设备树修改的需求本质是同步更新显示时序与触摸坐标系。仅改rotation会导致触摸点与显示位置错位。完整步骤修改display-timings节点调整hactive/vactive和hfront-porch等参数匹配横屏物理分辨率在touchscreen节点中添加touchscreen-size-x和touchscreen-size-y值互换更新touchscreen-inverted-x/inverted-y布尔属性根据硬件旋转方向设置。hdmi { status okay; display-timings { native-mode timing0; timing0: timing0 { clock-frequency 148500000; hactive 1920; /* 原1080现1920 */ vactive 1080; /* 原1920现1080 */ hfront-porch 80; hback-porch 48; hsync-len 32; vfront-porch 3; vback-porch 3; vsync-len 6; }; }; }; rk888_ts { touchscreen-size-x 1920; touchscreen-size-y 1080; touchscreen-inverted-x 0; touchscreen-inverted-y 1; };touchscreen-inverted-y 1表示Y轴翻转配合横屏显示使触摸坐标与显示一致。验证方法cat /proc/bus/input/devices确认触摸设备存在evtest /dev/input/eventX观察触摸点坐标是否随手指移动实时变化且范围在0-1919和0-1079内。3.5 开机动画添加UBOOT阶段的设备树干预rk3568 uboot添加开机动画需修改U-Boot的DTS而非Linux内核DTS。U-Boot DTS位于u-boot/arch/arm/dts/关键节点是dispdisp { status okay; rockchip,lcd-screen lcd1; rockchip,boot-logo rockchip,logo; rockchip,boot-logo-path /uboot/logo.bmp; };rockchip,boot-logo-path指定BMP格式logo路径U-Boot编译时会将其打包进u-boot-dtb.img。注意事项BMP必须是24位真彩色尺寸严格匹配LCD分辨率否则显示花屏。我试过用GIMP导出的BMP因包含alpha通道导致U-Boot解析失败改用convert logo.png -depth 8 -type truecolor logo.bmp才成功。4. 编译、烧录与调试全流程从修改到验证的闭环操作DTS修改的价值最终体现在能否让硬件按预期工作。一个完整的闭环流程远不止make dtbs这么简单。以下是我在RK3568项目中沉淀的标准化操作链每一步都有明确目的和验证点。4.1 编译阶段四步验证法确保DTS语法无误预处理检查cpp -nostdinc -I./arch/arm64/boot/dts/rockchip -I./arch/arm64/boot/dts/include -undef -x assembler-with-cpp arch/arm64/boot/dts/rockchip/rk3568-evb.dts /tmp/preprocessed.dts。此命令展开所有#include和宏定义生成纯文本。用vim /tmp/preprocessed.dts搜索你的节点名如ov5695确认它确实被包含且无语法错误如缺少;或}。这是发现#include路径错误的最快方法。DTC语法检查dtc -I dts -O dtb -o /tmp/test.dtb arch/arm64/boot/dts/rockchip/rk3568-evb.dts。若报错ERROR (phandle_references): Reference to non-existent node or label说明xxx引用的节点不存在需回溯到dtsi文件确认。Binding合规性检查make dtbs_check。此目标调用scripts/dtc/dtc的-W选项检查是否符合Documentation/devicetree/bindings/下的规范。例如若忘记给PHY节点加phy-supply会警告Warning (unit_address_vs_reg): Node /soc/ethernetfe2a0000/ethernet-phy0 has a unit name, but no reg property。DTB反编译验证dtc -I dtb -O dts -o /tmp/compiled.dts /tmp/test.dtb。对比/tmp/compiled.dts与原始DTS确认所有修改项如status okay已生效且无意外删除的节点。特别注意#address-cells等属性是否被继承覆盖。4.2 烧录阶段三镜像同步更新策略RK3568启动涉及三个关键镜像U-Bootu-boot-dtb.bin、内核Image、设备树rk3568-evb.dtb。任何单一镜像未更新都会导致DTS修改失效。标准烧录流程make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- u-boot-dtb.bin→ 更新U-Boot DTBmake ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- Image→ 更新内核镜像make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- rk3568-evb-dtb→ 更新Linux DTB使用rkdeveloptool统一烧录rkdeveloptool db loader.bin # 下载Loader rkdeveloptool ul u-boot-dtb.bin # 烧U-Boot rkdeveloptool dl 0x08000000 Image # 烧内核到DDR地址 rkdeveloptool dt rk3568-evb.dtb # 烧DTB到DDR地址提示dl和dt命令的地址必须与U-Boot环境变量kernel_addr_r和fdt_addr_r一致否则内核找不到DTB。用printenv在U-Boot命令行确认这两个变量值。4.3 启动调试dmesg日志的黄金排查法内核启动后dmesg是第一手证据。针对不同问题有固定排查路径设备未识别dmesg | grep -i ov5695\|i2c2\|csi0。若无输出说明DTS节点未被解析检查status okay和compatible字符串。驱动加载失败dmesg | grep -A 10 probe failed。常见原因是reg地址冲突如两个设备用了同一I2C地址或interrupts超出GIC范围。功能异常dmesg | grep -i timeout\|error\|fail。如csi0: timeout waiting for frame start表明MIPI时序不匹配需调整csi0节点的clock-frequency或>/dts-v1/; /plugin/; / { fragment0 { target rk888_ts; __overlay__ { touchscreen-size-x 1920; touchscreen-size-y 1080; }; }; };编译dtc - -I dts -O dtb -o touch-rotate.dtbo touch-rotate.dts加载echo touch-rotate.dtbo /sys/kernel/config/device-tree/overlays/注意需提前挂载configfsmount -t configfs none /sys/kernel/config。Overlay加载后dmesg会显示Applied overlay touch-rotate无需重启即可生效。这是调试阶段的神技但切记Overlay不能替代主DTS仅用于临时验证。5. 常见问题速查表与独家避坑指南在RK3568设备树实战中90%的问题都集中在几个高频雷区。以下是我踩过的坑和总结的速查表按问题现象分类直击根源。问题现象根本原因排查命令解决方案dmesg无任何外设相关日志status disabled或节点未启用grep -r your_node_name /proc/device-tree/确保status okay且节点在正确父节点下I2C设备i2cdetect -y 2显示--I2C控制器未使能或PHY供电失败dmesg | grep i2c2检查i2c2 { status okay; }和phy-supply指向的LDOv4l2-ctl --list-devices无CSI设备MIPI CSI节点remote-endpoint引用错误media-ctl -p /dev/media0确认csi0_in的remote-endpoint指向ov5695_0且ov5695_0存在网口ethtool eth0显示Link downphy-mode与硬件不匹配或PHY地址错误dmesg | grep gmac对照原理图确认RGMII模式rgmii-id/rgmii-rxid检查reg 0触摸屏点击位置与显示错位touchscreen-size-x/y未同步更新或rotation参数缺失evtest /dev/input/eventX同时修改display-timings分辨率和touchscreen尺寸属性独家避坑技巧DTS文件编码必须是UTF-8无BOMWindows记事本保存的DTS常带BOM头dtc编译时报Syntax error。用file -i your.dts检查若显示charsetbom用iconv -f utf-8 -t utf-8 -c your.dts fixed.dts清除BOM。节点名长度限制RK3568内核对节点名长度有限制32字符过长的compatible字符串如rockchip,rk3568-mipi-csi2-ov5695-camera会被截断导致驱动匹配失败。精简为ovti,ov5695即可。时钟ID必须精确匹配clocks cru CLK_I2C2中的CLK_I2C2必须与arch/arm64/boot/dts/rockchip/rk3568.dtsi中cru节点定义的宏名完全一致。grep CLK_I2C2 include/dt-bindings/clock/rockchip-rk3568.h确认宏定义。GPIO引脚号计算陷阱RK3568 GPIO编号为GPIO_BANK * 32 GPIO_PIN如GPIO0_A0是0*3200GPIO2_C7是2*322387。gpio0 12表示GPIO0的第12号引脚即GPIO0_B12务必对照《RK3568 TRM》第8章GPIO章节确认。Overlay加载失败echo xxx.dtbo /sys/kernel/config/device-tree/overlays/返回Permission denied是因为configfs未挂载或权限不足。执行sudo mount -t configfs none /sys/kernel/config并确保当前用户在root组。最后分享一个真实案例某次调试RK3568OV8858组合dmesg一直报ov8858 1-0036: failed to read chip id。查遍I2C地址、电源、reset引脚均无问题。最终发现OV8858的compatible应为ovti,ov8858而我写了ovti,ov8858少了一个8内核驱动匹配失败根本不执行probe函数。设备树的每个字符都是与内核驱动签订的契约错一个字契约即失效。所以动手前请务必打开你所用驱动的源码如drivers/media/i2c/ov5695.c复制compatible字符串粘贴到DTS中——这是最稳妥的做法。
返回列表