1. 为什么搞 OpenHarmony 移植,先得跟设备树死磕
先说个很多刚入坑 OpenHarmony 的人都会撞上的场景:你手里有一块 RK3568 的开发板,教程也下了,源码也拉了,结果打开 kernel 目录一看, arch/arm64/boot/dts/rockchip/ 底下躺着几十个以 rk3568 开头的 dts 文件。什么 rk3568-evb1-ddr4-v10.dts 、 rk3568-evb2-lpddr4-v10.dts 、 rk3568-evb2-lpddr3-v10.dts ,还有各种 -demo 、 -dt 后缀的变体。你脑子里的第一个问题绝对是:我到底该选哪个?第二个问题可能是:这些看着差不多的 dts,改起来到底在改什么?
这就是设备树 DTS(Device Tree Source)在 OpenHarmony 实战开发里最真实的痛点,尤其是当你用的还不是官方推荐的那几块板子,而是自己画的板、自己选的 DDR 颗粒、自己调的引脚,那设备树就不再是"编译内核时顺便勾选的一个选项",而是决定你能不能点亮屏幕、能不能跑起 WiFi、能不能让系统稳定不重启的核心关卡。这篇文章就把我在 OpenHarmony + RK3568 上跟设备树死磕的整套经验写出来,从 DTS 语法基础、文件结构,到多板型选择策略、常用改动点,再到编译、烧录和排错流程,争取让看完的人从"不知道选哪个 dts"进阶到"拿到一块板子能自己把设备树改明白"。
先说明白,这篇文章对标的是 OpenHarmony 标准系统(也就是带 kernel 的 full 版本),不是轻量系统那个跑在 MCU 上的场景。标准系统里,内核用的还是 Linux 内核那套机制,所以 DTS 的语法和编译方式跟传统嵌入式 Linux 高度一致,但 OpenHarmony 的构建系统、烧录方式、以及 device 目录下的 hdf 驱动配置会和纯 Linux 有些差异,这也是很多人卡住的地方。适合谁看?正在做 OpenHarmony 板级移植的开发、打算在非官方板子上跑 OpenHarmony 的玩家、以及想把内核设备树这块"知其然不知其所以然"补全的入门者。
2. 别急着改 dts,先搞懂 DTS/DTB/DTC 到底在干什么
2.1 一套三板斧:dts、dtb、dtc 的关系
设备树这套东西,核心目的就一句话:把"硬件长什么样"和"驱动怎么工作"解耦。在设备树出现之前,内核里描述硬件的方式是写一堆 board 文件,代码里到处都是平台设备注册、资源填充,每换一块板子就要动一遍 C 代码。设备树的做法是,把硬件信息用树状的节点描述出来,内核启动时通过解析这棵树来自动匹配驱动、填充资源。
具体到 OpenHarmony 里,source 文件是 .dts ,这个是人类可读的文本格式。编译工具是 dtc ,全称 Device Tree Compiler,它把 .dts 编译成二进制的 .dtb 文件。内核启动早期阶段会去加载 dtb,然后解析树上的节点,逐个匹配驱动。这套流程和 Linux 内核完全一致,只不过在 OpenHarmony 的构建脚本里,dtc 的调用被打包进了内核编译流程,你在 kernel/linux/build 的日志里能看到类似 DTC arch/arm64/boot/dts/rockchip/rk3568-evb2-lpddr4.dtb 的输出。
这里有个非常容易踩的认知坑:很多人觉得设备树改了只要重新编译 kernel 就行,实际不是。dtb 文件编译出来以后,最终要不要被加载,还得看 bootloader(OpenHarmony 标准系统里通常是 U-Boot 或者 fastboot 方式)传不传它、传的是哪个。也就是说,你改了 dts 并编译出新的 dtb,还得确保烧录时这个 dtb 真的被放到了 boot 分区里并被引导加载。
2.2 节点、属性、标签:读懂一段 dts 的最小案例
不用把 dts 想得多玄,它本质就是个嵌套的键值对结构。看一段最常见的:
/ {
model = "Rockchip RK3568 EVB2 LPDDR4 Board";
compatible = "rockchip,rk3568-evb2-lpddr4", "rockchip,rk3568";
chosen {
bootargs = "earlycon=uart8250,mmio32,0xfe660000 console=ttyFIQ0 root=PARTUUID=614e0000-0000 rw rootwait";
};
memory@00000000 {
device_type = "memory";
reg = <0x0 0x0 0x0 0x80000000>;
};
};
根节点 / 下面的 model 是板子名称, compatible 是匹配关键字,驱动通过比较这个字符串来找设备。 chosen 节点存放的是启动参数,这里面 console=ttyFIQ0 是 RK 平台特有的 FIQ 串口调试口配置,如果你自己板子的调试串口号改过,串口起不来十有八九就是这里和 U-Boot 传参没对齐。 memory 节点描述内存起始地址和大小, reg 里四个 32 位值拼成了 64 位地址和大小, 0x80000000 就是 2GB。
看到没有,dts 并不复杂,复杂的是你要改哪一个字段、在什么上下文里改。一颗 SoC 有几十个外设控制器,每个控制器都要描述寄存器地址、中断号、时钟、复位、引脚等,一个完整的 RK3568 evb 板级 dts 通常有三四千行。我们不用全看懂,但得知道每一段是干嘛的,改起来才不心虚。
为了加深理解,再说一下"标签"和"引用"的关系。很多 dts 里会出现这种写法:
&uart0 {
status = "okay";
};
这个 &uart0 是引用了在 dtsi(设备树包含文件)里定义好的 uart0: serial@fe660000 节点。这种分层写法是 RK 平台设备树组织的核心:SoC 级别的硬件描述全放在 .dtsi 里,板级文件( .dts )只负责"启用哪些外设、配什么引脚、调什么参数"。这样同一颗芯片做十几个板子,dtsi 基本不动,每个板子只需在 dts 里改外设开关和引脚复用,工作量小很多,也方便维持主线同步。
2.3 为什么说 dtsi + dts 的组织方式救了 Rockchip
RK 的 dts 目录结构特别有自己的风格。你打开 kernel/linux/arch/arm64/boot/dts/rockchip/ 后会发现一堆 .dtsi 文件:
-
rk3568.dtsi:SoC 级描述,包含 CPU、GIC 中断控制器、片上外设、时钟、电源域等 -
rk3568-pinctrl.dtsi:
328




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



