本文是《从零到一:把一块 RK3568 开发板移植到 OpenHarmony 6.1 全记录》系列的第 6 篇。讲一次真实的"设备树翻译"全过程:两块系统、两个内核版本、同一块硬件,说明书怎么搬。
上一篇文章认识了设备树。这篇讲实战:同一块板子,Android(内核 4.19)已经有一份能用的说明书,怎么把它变成 OpenHarmony 6.6 内核能读的版本。
我的方法是标准的工程三件套:diff 找差异 → 逐项翻译 → dtc 快速验证。
一、先打破一个信息差:OH 6.1 的内核是 6.6
刚开始移植时,我照着网上的旧资料,把板级补丁全放在了 linux-5.10 目录下。等真正编译时才发现:
OpenHarmony 6.1 的默认内核是 Linux 6.6,不是 5.10。
(build/ohos/kernel/kernel.gni 里 linux_kernel_version = "linux-6.6",网上的 5.10 资料全是旧版本遗留。)
这是整个移植中信息成本最高的一课:方向错了,之前写的设备树全部返工。写这篇文章,就是希望你别再踩。
二、翻译的三个步骤
第 1 步:diff 找差异
原厂 Android 源码里,这块板的说明书在 rk3568-evb1-ddr4-v10.dtsi 等文件里(4.19 语法);OH 6.6 内核自带的是官方参考板(toybrick)的说明书。两者一 diff,差异就出来了:
# 以太网部分的差异(节选)
< phy-mode = "rgmii"; # 官方参考板:RGMII
> phy-mode = "rmii"; # 这块板:RMII
< snps,reset-gpio = <&gpio2 RK_PD3 ...>; # 官方板:复位接 gpio2_D3
> snps,reset-gpio = <&gpio0 RK_PD5 ...>; # 这块板:复位接 gpio0_D5
差异就是"这块板与官方参考板不同的地方"——移植的本质就是把这些差异用新语法重新表达。
第 2 步:逐项翻译
我把差异归纳成一张对照表,然后逐项写进新说明书:
| 硬件 | 官方参考板(6.6) | CHESHIT10 这块板 | 翻译动作 |
|---|---|---|---|
| 以太网 | gmac0/gmac1 双 RGMII | gmac0 单路 RMII(RTL8201F) | 覆盖 gmac0;gmac1 禁用 |
| 屏幕 | 主屏接 DSI0 | 主屏 7 寸接 DSI1 | 关 DSI0 通路,开 DSI1+VP1 |
| 触摸 | i2c1 上有 gt1x | i2c3 上 4 颗候选芯片 | 删 gt1x,重写 i2c3 |
| 摄像头 | ov13855/gc8034 单通路 | GC2053+GC2093 双通路 | 删旧传感器,写新通路 |
| USB | 5V 接 gpio0_A6 | 5V 接 gpio2_D3,多一个 Hub 复位 | 覆盖引脚 |
| RTC 时钟 | 官方板无 | HYM8563 挂 i2c1 | 新增节点 |
| WiFi 使能 | 无使能引脚 | gpio2_D1 控制 | 补属性 |
每项翻译后的真实代码长这样(节选):
/* 以太网:官方板 RGMII → 这块板 RMII */
&gmac0 {
phy-mode = "rmii";
clock_in_out = "output";
snps,reset-gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_LOW>;
assigned-clock-parents = <&cru SCLK_GMAC0_RMII_SPEED>;
pinctrl-0 = <&gmac0_miim &gmac0_tx_bus2 &gmac0_rx_bus2 &gmac0_clkinout>;
phy-handle = <&rmii_phy0>;
status = "okay";
};
第 3 步:dtc 快速验证
写一段就用 dtc 编译验证一段(方法见第 5 篇),30 秒出结果。别攒到最后让几小时的内核编译来告诉你语法错误。
三、翻译中的"雷区":版本方言差异
4.19 → 6.6,设备树的"方言"变了,踩了三个真实的雷:
雷 1:宏改名了
屏幕 flags 里,4.19 时代用 MIPI_DSI_MODE_EOT_PACKET(发送 EOT 包),6.6 的头文件里这个宏不存在了,改名成了 MIPI_DSI_MODE_NO_EOT_PACKET(语义反转:不带 NO_EOT 即默认发 EOT)。
/* 4.19 写法 */
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
/* 6.6 等价写法(不带 NO_EOT 即默认发 EOT) */
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM)>;
雷 2:基座文件换了
4.19 时代板级说明书基于 rk3568-evb1-ddr4-v10.dtsi;6.6 内核里这个文件不存在了,官方参考板的基座是 rk3568-toybrick.dtsi + rk3568-toybrick-x0.dtsi。板级内容(电源/内存/存储的通用配置)要从新基座复用。
雷 3:删除节点前必须查引用
翻译时经常要"删掉官方板的设备、换成这块板的"。直接删会撞上"悬空引用":
ERROR (phandle_references): /rt5672-sound/dais/dai0:
Reference to non-existent node or label "rt5670"
官方板声卡节点引用了我要删的音频芯片。规则:被引用的节点用 status = "disabled" 禁用,不要 delete;只有无引用(或引用一并删除)的节点才用 delete。
/* 正确做法:禁用而非删除 */
&rt5670 { status = "disabled"; };
/* 无引用的才直接删 */
/delete-node/ &rgmii_phy0;
另外还有个纯语法坑:/delete-node/ 必须放顶层(不能写在 &overlay { } 块内),新版 dtc 会直接报语法错误。
四、最终产物:一份可复用的补丁结构
翻译完成的说明书,我打包成了标准的内核补丁结构:
kernel/linux/patches/linux-6.6/cheshit10_patch/
├── kernel.patch # 板级补丁(构建时自动应用)
├── hdf.patch # HDF 框架接线补丁
└── dts/ # 说明书源文件(维护用)
├── rk3568-cheshit10.dtsi # 板级公共说明书
├── rk3568-cheshit10-7inch.dts # 入口(总目录)
├── panel-cheshit10-7inch-jh071.dtsi # 屏幕章节
└── touch-cheshit10.dtsi # 触摸章节
构建时,这个补丁会在瑞芯微官方补丁之后自动应用,顺序是:
干净内核源码 → 瑞芯微 BSP 补丁(55MB) → CHESHIT10 板级补丁 → 编译出 DTB