发布时间:2026/9/5 7:00:18
OpenHarmony源码树全解析:RK3568设备树选择与编译实战 干 OpenHarmony 开发的第一次拉完源码基本都会懵一下目录怎么这么多明明我只想跑一块 rk3568 板子结果拉下来几百个仓库、几十个顶层目录什么 base、foundation、device、vendor、drivers看名字大概知道是干嘛的可真让我说清楚每个目录管什么、哪些是当前产品必需的、改代码该进哪个仓很多人就答不上来了。这个系列是讲开源鸿蒙 OpenHarmony 系统实战开发的第一课我就想把源码树给你解剖明白——因为后面所有编译、裁剪、驱动开发、应用移植全都要在这棵树上动刀。我会从源码树的设计逻辑讲起逐步拆解每个核心目录再用 RK3568 这个最常见的开源鸿蒙主控平台把设备树选择、源码编译流程完整走一遍。内容主要面向刚接触 OpenHarmony 的系统开发者、驱动工程师以及准备做设备适配的团队。看完你至少能回答两个问题源码树里到底有什么我手头的板子该选哪个设备树、怎么编出固件。1. 先搞清楚OpenHarmony 源码树是什么样的一张地图1.1 一个系统几百个仓库OpenHarmony 不像 Linux kernel 那样一个 tar 包就是全部。它采用的是多仓模式每个子系统、甚至子系统里的每个关键组件都是一个独立的 git 仓库发布时由一个 manifest 仓库里的 xml 文件把几百个仓库的版本号统一锁定。你用 repo 工具拉下来的所谓“源码树”本质上是这些仓库在本地按约定路径检出后的集合。为什么要这么干核心原因是 OpenHarmony 覆盖的设备跨度太大了从几百 KB 内存的传感器设备到几个 GB 内存的开发板、电视、平板再到未来的 PC 形态。不同硬件需要的组件完全不一样多仓 按需组装才能做到“同一个系统底座按产品裁剪”。如果像传统系统那样给一个全量源码包光是解压和编译就能劝退一大批人。所以看 OpenHarmony 源码树第一件事是别把它当成一棵“整树”而要当成一张“地图”顶层目录划分的是子系统边界每个目录又是一块可独立替换的积木。用乐高来类比最贴切——每一袋积木是独立分包的按说明书manifest组装成你要的模型用不到的袋子可以先扔一边。1.2 顶层目录的分层逻辑OpenHarmony 顶层目录并不是乱来的它暗合了一套从硬件到应用的分层逻辑层级顶层目录职责典型内容应用层applications/系统自带的标准应用Launcher、Settings框架层foundation/、base/系统服务、分布式能力、UI 框架软总线、分布式调度、ArkUI接口层interface/SDK 接口定义对外 API 声明内核层kernel/内核源码liteos-a / liteos-m / linux驱动层drivers/HDF 驱动框架hdf_core、框架适配层硬件适配层device/、vendor/、soc/芯片、单板、产品适配rk3568 板级配置构建与工具build/、productdefine/、prebuilts/构建系统、产品定义、工具链hb、GN、预编译工具三方库third_party/引用的开源软件zlib、mbedtls 等这个分层不是死的但理解它很重要。拿到一块新板子第一件事是在 device/、vendor/、kernel/ 里找适配做应用开发主要关注 applications/ 和 foundation/arkui/接外设传感器往 drivers/ 和对应板级 hcs 配置里加东西。我建议新手花半天时间用tree -L 2把源码树结构打出来对着这张表过一遍比闷头看代码效率高得多。提示不同版本比如 3.2 Release 和 master目录划分会有差异早期版本 base/ 和 foundation/ 的组件归属不完全一样。看源码树时先确认你拉的分支避免拿旧地图导航新城市。2. 核心目录逐个解剖每个目录里到底有什么2.1 kernel/一套系统三种内核kernel/ 下面是三个候选内核liteos-a面向中大型 IoT 和带屏设备、liteos-m面向 MCU 级小型设备、linux标准系统的主力。标准系统——也就是跑得了 rk3568 这种带 GPU、能跑富 UI 的系统——用的是 linux 内核OpenHarmony 在主线 linux 基础上加了针对分布式场景的增强补丁以及 HDF 驱动框架在内核侧的对接。选择逻辑其实很清楚先看产品形态再看内存和实时性需求。做智能摄像头、带屏中控通常选 linux做温湿度传感器、智能开关这类 MCU 设备走 liteos-m介于中间的复杂 IoT 设备可以考虑 liteos-a。kernel 目录下的 README 也会写清楚每个内核的适用场景别一上来就纠结跟着产品需求走就行。2.2 device/、vendor/、soc/硬件适配的“三兄弟”这是最容易混的三个目录我刚入坑时也绕了很久。一句话总结soc 目录放的是芯片厂商比如 rockchip提供的平台公共代码board 目录放的是具体单板比如某厂商的 rk3568 开发板的板级代码vendor 目录放的是“产品”定义——也就是这块板最终做成什么、带哪些应用和配置。以 rk3568 为例你会看到这样的代码分布device/soc/rockchip/rk3568/芯片平台公共适配比如 GPU、多媒体编解码这类 SoC 级能力device/board/xxx/rk3568/具体开发板特有的引脚、屏幕、触摸、电源配置vendor/xxx/rk3568/产品配置比如打包镜像、预置应用、config.json。三者层层依赖soc 提供基础board 决定板级细节vendor 决定交付物。做适配时芯片原厂没动过的东西不要自己乱改优先改 board 层和 vendor 层这样以后芯片平台代码升级时冲突最小。我见过有人直接去改 soc 层的公共 dtsi结果一升级平台代码全部冲突血泪教训。2.3 foundation/ 与 base/分布式能力的“大本营”OpenHarmony 区别于其他系统的核心卖点是分布式。这部分代码绝大多数在 foundation/ 和 base/ 两个目录里。foundation/ 下面是子系统比如 communication分布式软总线、distributedschedule分布式调度、arkuiArkUI 声明式 UI 框架、multimedia多媒体框架等base/ 下面是更底层的公共能力比如 hiviewdfx日志/故障管理、security安全、startup启动恢复等。为什么拆成两个顶层目录我理解是按“复用层级”来区分base/ 更底层、更通用上层框架和服务都依赖它foundation/ 相对上层可以直接支撑应用开发。做普通应用开发打交道最多的是 foundation/arkui 和 foundation/ability元能力框架做系统定制base/ 里的 DFX、启动恢复几乎必动。搞清楚这个从属关系后定位问题的范围能缩小一大半。2.4 drivers/HDF 驱动框架设备接入的标准姿势OpenHarmony 的设备驱动不推崇直接写一堆内核模块草草了事而是有一套统一的硬件驱动框架 HDFHardware Driver Foundation代码集中在 drivers/。它分两部分一部分是框架本身hdf_core、framework另一部分是与具体内核/硬件适配的 adapter。HDF 的典型工作方式是“配置驱动 代码实现”驱动能力用 HCS 配置文件描述比如一个 I2C 触摸屏驱动你要在 device_info.hcs 里注册它的 device node在对应 .hcs 里配置总线、地址、中断引脚然后驱动代码按 HDF 规范实现接口。这样做的好处是换芯片、换板子时驱动代码可以不改只改配置就能适配。这也是 OpenHarmony 设备适配速度能快起来的底层原因。2.5 build/ 与 productdefine/构建指挥中心编译 OpenHarmony 不是直接敲 make而是用 hb 工具。hb 本身就在 build/ 里。构建的入口逻辑是先有产品定义productdefine/products 里的 json产品定义聚合需要的子系统、部件构建系统再去对应仓库里找组件的 BUILD.gn 来编译。productdefine/ 里主要看两类文件products/ 下的产品 JSON比如 rk3568.json声明了产品名、平台、依赖子系统列表common/ 下是公共部件定义把 OpenHarmony 的所有子系统按部件粒度登记。你要裁剪系统就是改产品 JSON把不需要的子系统从列表里拿掉。这个设计把“系统有什么”和“产品要什么”解耦了非常实用。我优化开机速度时第一步就是打开产品 JSON 看哪些重型子系统是被误拉进来的。2.6 容易被忽略但迟早要用的目录除了上面几个大头还有几个目录不常被提起但实战中迟早会碰上ark/ArkTS 的编译器和运行时做应用性能优化或研究方舟编译器时来这里third_party/几百个第三方开源组件编译报缺头文件、缺库时来这里找prebuilts/预编译工具链、python 环境等编译环境出问题先怀疑这里interface/SDK 头文件、IDL 定义应用开发者查接口签名的地方test/各子系统测试用例既有 xdevice 自动化测试平台也有模块单测。3. 实战走一遍RK3568 的源码树选型、设备树选择与编译3.1 为什么 rk3568 在源码树里有一堆设备树打开内核源码里 arch/arm64/boot/dts/rockchip/ 目录你会看到一堆 rk3568 开头的设备树文件rk3568-evb1-ddr4-v10-linux.dtb、rk3568-evb2-lp3-v10-linux.dtb、rk3568-dayu200.dtb……新手看到就懵了到底该选哪个。原因是 RK3568 这颗 SoC 被大量板卡复用但每块板子的硬件细节不一样DDR 是 lp3 还是 lp4/ddr4屏幕是哪家的 panel触摸是 I2C 还是 USB网口有几个全都反映在设备树里。设备树本质是“硬件的描述清单”内核靠它知道怎么初始化板子。选错设备树轻则某个外设不工作重则直接起不来。所以问题不是“哪个设备树通用”而是“你的板子到底是什么硬件”。开发板厂商出厂的固件用的设备树一定和板子硬件一致你只要找到对应名字即可。以常见的 rk3568 开发板比如 dayu200 这类产品为例产品配置走的是 dayu200 路径最终用到的就是 rk3568-dayu200.dtb 对应的那套 dts。3.2 三步锁定你的产品该用哪个设备树第一步看产品定义。在源码根目录执行hb set会列出当前源码树支持的产品或者在 productdefine/products/ 下找对应 json比如 rk3568.json 或 dayu200.json确认你当前是哪个产品。第二步顺着产品定义找 board。在 vendor/ 对应厂商目录下的 config.json 里会写明 board 是哪个类似board: rk3568再到 device/board/ 对应厂商目录下找到这块板的 kernel 构建脚本。第三步看构建脚本里的设备树指向。rk3568 的 kernel 构建脚本常见路径是 device/board/xxx/rk3568/kernel/build_kernel.sh会调用内核编译命令并指定 dtb 参数。你实际烧到板子上的 boot 镜像里打包了哪个 dtb就是由它决定的。注意不同厂商、不同版本路径名有差异但“产品 → 板子 → 内核构建脚本 → dtb”这条链路是通用的。找不到就沿着这个链路的每一步去 grep一定能定位到。3.3 修改设备树与重新编译的标准动作实战中经常要改设备树比如点亮一块新屏幕、打开一个串口、配置一个 GPIO。标准动作是这样的找到对应板子的 dts/dtsi 文件通常在 kernel 源码 arch/arm64/boot/dts/rockchip/ 下注意优先继承公共的 rk3568.dtsi不要什么都堆在主 dts 里按设备树语法添加或修改节点比如增加 I2C4 下的触摸屏节点配置好 reg、中断脚、复位脚重新编译内核和 boot 镜像hb build -f或单独编 kernel 目标烧录后通过串口确认设备树加载是否正常进入系统后可在 /sys/firmware/devicetree/base 下检查节点是否存在。一个容易踩的坑HDF 驱动环境下很多外设参数应该走 HCS 而不是 dts。有人把设备树改了又改外设还是没反应其实那个设备根本没走 Linux 原生驱动而是被 HDF 接管了改 dts 自然没用。判断方法很简单看这个外设在源码树里有没有对应的 HDF 驱动目录。3.4 从源码树到固件完整编译流程复盘以 Ubuntu 20.04 rk3568 标准系统为例我把完整流程走一遍。先准备环境装好 python3.8、git、gcc 等基础工具磁盘至少留 100GB源码加编译产物内存建议 16GB 以上。获取源码repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify repo sync -crepo sync 很容易被网络波动打断中断后重新执行即可增量同步不会重复下载已完成的部分。安装 hb 构建工具cd build ./build_scripts/hb_install.sh source ~/.bashrc验证是否可用hb -h。然后选择产品并编译hb set # 在弹出的列表里选你的板子对应产品 hb build -f第一次编译时间比较长rk3568 全量构建在主流配置机器上动辄一两个小时起耐心等。编译产物在 out/ 目录下标准系统镜像一般在 out/{产品名}/packages/phone/images/ 下包括 boot.img、system.img、vendor.img、userdata.img 等。刷机用开发板厂商提供的烧录工具即可。如果你以后尝试 x86 形态的 OpenHarmony流程也是一样的换一个 x86 产品定义再 hb build硬件适配层的关注点从 dts 变成对应的启动协议而已。4. 源码树实战问题排查我把踩过的坑都列给你4.1 仓库同步与版本不配套问题最常见的三个坑逐个说。第一manifest 分支和源码分支不一致。比如 manifest 用的 master但你手动把某个仓切到了其他分支编译时很容易出现接口对不上。建议除了自己要改的仓其他仓保持 manifest 锁定的版本不动不要手痒去切分支。第二repo sync 中断后部分仓不完整。补一次repo sync -c多数能解决个别仓反复失败可以先 repo start 一个新分支再 sync让本地指针归位。第三少拉子仓。官方 manifest 已经锁定了整套源码树不建议随便加第三方裁剪脚本或本地清单否则有的组件缺失编译失败时排查成本极高。4.2 设备树选错或改错后的典型症状把常见症状和排查方向整理成一张表遇到问题直接对号入座症状可能原因排查思路开机卡在内核早期串口无输出dtb 与硬件不匹配或 dts 内存配置不对确认 DDR 类型核对对应 dtsi屏幕黑屏但系统起来了dts 里 panel 时序或使能脚不对用 hdc 看系统日志查 display 服务状态触摸无反应I2C 地址/中断脚不对或驱动没加载核对触摸节点与硬件原理图dmesg 查 I2C网口/串口不通pinctrl 复用冲突检查 dts 里 pinctrl 配置排查外设冲突排查工具无外乎三样串口日志内核阶段、hdc shell系统阶段、dmesg/hilog运行日志。建议新板子到手第一件事就是把串口接好串口日志能省半条命。我调试新板子时必开串口比反复猜原因高效太多。4.3 在源码树里快速定位代码的方法源码树几百个仓直接在顶层 find 或 grep 会慢到怀疑人生。我的习惯是分四步。先判断功能属于哪个子系统。比如“开机画面”大概率在 foundation/graphic 或应用的 bootanimation 里参考前面分层表缩小范围在对应子系统目录里 grep 关键符号。例如找开机动画grep -r BootAnimation foundation/ --include*.cpp用编译日志反查。编译时看 out 目录下的 ninja log能看到具体编译了哪些源文件顺藤摸瓜比猜路径快借助 IDE。VSCode 打开源码树后让索引跑完再用全局搜索如果机器性能一般只把你研究的几个仓加进工作区体验会好很多。4.4 源码级调试的三板斧最后说调试。OpenHarmony 标准系统源码级调试我日常用得最多的是三招。第一招加日志应用层用 OH_LOG内核和驱动用 printk 或 dev_info先确认代码到底有没有走到、关键变量值是多少。别一上来就开调试器日志永远是最快的。第二招 hdc 连接hdc shell 进系统ps -ef 看进程hilog 看系统日志需要的话还能拉文件出来分析。第三招抓崩溃native 崩溃会生成 tombstone一般在 /data/log/faultlog/temp 下里面有调用栈排查崩溃基本靠它。补一句如果你改的是内核最省事的验证方式是单独编 kernel 并快速替换 boot 分区不用每次全量hb build -f。我第一次全量编了三次后来才发现单独编内核加打包的时间只有全量的三分之一做驱动调试能省大量等待时间。

相关新闻

2026/9/5 7:00:18

OpenHarmony源码树全解剖:从目录结构到RK3568设备树实战

1. 源码树不是迷宫,是你的地图很多刚接触OpenHarmony的朋友,第一眼看到那棵庞大的源码树,心态基本是崩溃的。几十个顶层目录、上千个子模块、一堆看不懂的缩写命名,光是从哪下手就能劝退一半人。我当年第一次拉完OpenHarmony全量代…

2026/9/5 6:55:18

Unity集成AI智能体:从API接入到代码生成实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 6:55:18

技术复盘博客写作指南:从活动保障到经验沉淀

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 7:45:20

如何用MCP把六个独立内容站点统一接入AI工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 7:45:20

本地动画生成工具部署指南:从环境配置到批量任务处理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 7:45:20

开源标书查重工具:文档相似度检查与本地部署实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 7:45:20

用Figma打造七周年贺图:从关键词到视觉系统的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 7:40:20

上位机开发工程师薪资达50万+:技术栈与职业发展分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/5 2:46:54

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/5 2:46:52

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/5 2:44:34

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/5 0:04:47

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流在大模型流式输出(Streaming)与智能体实时推流的架构中,生产环境中经常出现一种“上下游生产消费速率严重失衡”的极端情况: 生产端极速产出:大模型…

2026/9/5 2:45:13

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/5 2:46:50

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…