搞过OpenHarmony开发的人都有过这种经历:板子拿到手,固件烧完,摁下电源键,屏幕不亮、串口没有输出、hdc也连不上,这时候大部分人第一反应是怀疑板子坏了或者固件有问题。但根据我做过的几十块RK系列板卡调试经验来看,绝大多数“看起来玄学”的硬件问题,根源都出在三个非常基础的地方:串口日志没看全、设备树选错、运行态信息没抓到。这就是为什么我一直跟团队里的人说,OpenHarmony硬件调试真正管用的就是三板斧——串口日志、设备树、hdc加hilog组合。这套方法不高级,但能覆盖日常开发中八成以上的硬件问题。这篇教程就把这三板斧怎么磨、怎么用、怎么看日志、怎么定位问题完整讲清楚,适合刚从应用开发转到系统开发的人,也适合第一次拿RK3568开发板跑OpenHarmony的嵌入式老手。
1. 先定调子:硬件调试的本质是"缩小搜索空间"
1.1 三板斧到底解决了什么
很多人把硬件调试想得很复杂,觉得必须示波器、逻辑分析仪、协议分析仪全套上阵才能开工。其实在OpenHarmony这种系统级开发场景里,绝大多数问题发生在软件配置和硬件之间的适配层,真正需要测信号完整性的场景反而少见。所谓三板斧,对应的是三层问题:
- 串口日志解决的是“系统到底跑到哪一步了”,让你知道是DDR初始化失败、U-Boot没起来、内核panic还是用户态服务崩溃。
- 设备树解决的是“软件认为硬件长什么样”,RK3568这种引脚复用极其灵活的芯片,一个引脚既能做I2C又能做GPIO还能做PWM,配置错一个pinctrl,外设就不工作。
- hdc加hilog解决的是“系统起来了之后运行态发生了什么”,比如某个服务起不来、某个硬件节点注册失败、IPC通信超时,这些在启动日志里往往看不到。
把这三板斧用熟练,你不需要猜,只需要按顺序收集信息,问题范围就能从“整块板子”缩小到“某一个寄存器”甚至“某一个GPIO引脚”。
1.2 为什么示波器和逻辑分析仪不是首选
不是说示波器没用,而是要区分场景。在OpenHarmony开发中,真正需要示波器的场景是:MIPI-DSI屏幕闪屏、音频信号失真、电源纹波过大、高速信号眼图问题。这些属于模拟域和信号完整性范畴,软件配置无论怎么改都解决不了。但在实际开发里,遇到更多的其实是“I2C设备读不到地址”“触摸屏没有中断上报”“以太网PHY link不上”这类问题,看着像硬件坏了,实际上八成是设备树里地址写错、GPIO复用冲突、中断号对不上。先用三板斧把软件配置问题排除干净,再去动用示波器,效率比直接上仪器高得多。
我见过不少新手一上来就怀疑硬件,把板子寄回给厂商,厂家测了一圈说没问题,结果回来发现是设备树里i2c频率配置过高导致通信不稳定。这不是板子的问题,是调试思路的问题。
2. 第一板斧:串口日志——一根USB转串口线穿透整个系统
2.1 接线和工具准备
串口是整个OpenHarmony硬件调试的底线,无论上层用什么调试工具,串口永远是最后一条退路。RK3568开发板的标准调试串口一般是3.3V TTL电平,板上会留一组调试排针或测试点,常见的丝印标注是TX、RX、GND,部分板子还有VCC。
接线规则很简单:板子的TX接USB转串口模块的RX,板子的RX接模块的TX,GND接GND。千万别接VCC,TTL模块的VCC一般是给需要供电的板子准备的,接了反而可能烧掉调试接口。USB转串口芯片推荐CP2102或CH340,便宜稳定,FT232也行但性价比不高。实测下来CP2102在长时间抓日志时不容易掉线。
连接好之后,确认设备节点。Linux下用ls /dev/ttyUSB*查看,Windows下在设备管理器里看COM口号。打开串口工具有两个常用选择:
- Linux/macOS推荐
minicom或picocom,轻量稳定。 - Windows推荐MobaXterm或PuTTY,都支持串口会话。
关键参数是波特率,RK3568平台的OpenHarmony调试串口默认波特率一般是1500000(1.5Mbps),但也有部分板子用115200,具体看板卡说明书。串口参数设置为:波特率1500000(或115200)、8位数据位、1位停止位、无校验、无流控。流控必须关闭,不少新手卡在这一步,打开RTS/CTS之后只能出不能收。
minicom配置命令:
minicom -s进入配置界面,选择Serial port setup,把串口设备改成/dev/ttyUSB0,波特率改成1500000,关闭硬件流控,保存退出。
2.2 抓启动日志,判断卡死在哪个阶段
接线完成后,先打开串口工具,再给板子上电。完整的启动日志大致分三个阶段,每个阶段卡住都有不同的典型原因,我整理了一个对照表:
| 日志阶段 | 出现的关键字 | 卡死在这里的常见原因 |
|---|---|---|
| U-Boot之前 | DDR、ddr、bl31、bl2 | DDR配置错误、电源时序异常、固件不匹配 |
| U-Boot阶段 | U-Boot 2017.09、Hit any key to stop autoboot | 启动介质不对、boot分区损坏、dtb加载失败 |
| Kernel阶段 | Booting Linux、Init、Freeing unused kernel memory | 设备树不匹配、驱动初始化失败、根文件系统挂载失败 |
| 用户态阶段 | init、service、SA | 某个系统服务崩溃、selinux权限拒绝、HDF驱动注册失败 |
实际操作中最常见的情况是日志走到一半就停住了。这时候先不要急着下结论说“死机了”,要区分两种情况:一种是系统真的卡住,另一种是console没有输出但系统还在跑。区分方法很简单,等几秒看串口是否还会有零星输出,或者直接看板子上的LED是否还在闪烁。
如果确认是卡死,根据停住的位置判断方向。比如日志停在DDR初始化直接没有任何输出,优先查电源和DDR配置;如果U-Boot起来但加载内核失败,优先查boot分区烧录是否正确;如果内核解压完成但卡在某个驱动的probe函数,优先查设备树配置。
有个排查启动阶段问题的实用技巧:在U-Boot阶段打断启动进入命令行,执行printenv查看启动参数,确认console参数是否指向了正确的串口。RK平台常见配置是console=ttyFIQ0,1500000n8,如果被改成了别的串口或者波特率不对,内核日志就会“消失”。
2.3 串口没有输出的常见原因
串口接上之后什么都没有,这是新手遇到最多的状况。按照出现频率排序,逐个排查:
- TX/RX接反。这是概率最高的错误,尤其是有的人习惯用排针母座转接的时候容易搞混方向。把TX和RX对调再试。
- GND没接。串口通信是共地协议,不接GND大概率收不到任何数据。
- 波特率不对。板子写的是1500000,你用了115200去收,输出就是乱码或者完全没有。还有部分板子的调试串口从U-Boot到内核会切换波特率,注意观察。
- 串口芯片驱动没装。
ls /dev/ttyUSB*什么都看不到,先确认这个。 - console参数被禁用。这种情况系统其实正常运行,只是串口不输出,可以先用hdc连上系统,再
dmesg看日志确认。
检查工具本身是否正常的小技巧:把USB转串口模块的TX和RX直接短接,然后打开串口工具随便发几个字符,如果能收到自己发的字符,说明模块和工具链路没问题,问题出在板子端。
注意:RK平台的调试串口设备节点是
/dev/ttyFIQ0,不是/dev/ttyS0。如果修改内核cmdline或者看代码时注意区分,偶尔有人在这里绕晕。
3. 第二板斧:设备树——RK3568源码里那一堆dts别靠猜
3.1 为什么RK3568会有这么多设备树文件
第一次下载OpenHarmony内核源码编译RK3568的开发者,打开kernel/linux/arch/arm64/boot/dts/rockchip/目录大概率会懵一下:里面密密麻麻摆着几十个rk3568-*.dts文件,有rk3568-evb1-ddr4-v10.dts,有rk3568-evb2-lpddr4-v10.dts,还有一堆rk3568-xxx-demo.dts。为什么同一个芯片需要这么多设备树?原因有两点:
第一,RK3568本身定位是工控和消费级通用的芯片,下游厂商用它做NAS、做平板、做盒子、做边缘计算设备,同样的SoC搭配不同的DDR颗粒、不同的PMIC电源方案、不同的屏幕、不同的外设接口组合,就必须有不同的设备树来描述这些差异。
第二,OpenHarmony社区和芯片厂商的BSP会同时维护EVB参考板、第三方厂商量产板、以及各种自研板卡的设备树。这些文件从底层看差异其实不大,但细节上每一个都对应一款真实存在的硬件配置。
所以“到底选哪个”这个问题不能靠猜,而是要逆着设备树的生成和加载链路去找。
3.2 选错设备树会踩到哪些坑
选错设备树不是“启动不了”这么简单,很多问题表面上跟设备树毫无关系,实际根因却在设备树。我列几个亲测过的:
- 屏幕不亮:选了不带特定MIPI-DSI panel节点的设备树,内核不会初始化显示控制器,屏幕自然没反应。
- 触摸屏无响应:触摸IC的I2C地址在设备树里配置错误,或者中断GPIO和实际硬件不匹配。
- 千兆以太网速率异常:PHY芯片的寄存器配置或reset引脚不对,导致link起来速率变成百兆甚至不通。
- WiFi无法扫描:SDIO接口的pinctrl复用冲突,或者电源使能GPIO没正确配置。
- 系统启动到一半反复重启:DDR类型或频率配置与板载颗粒不匹配,内核起来后内存访问异常触发panic。
这些问题的共同特点是:编译、烧录都能完成,启动日志也不一定有明显的错误关键字,但外设就是工作不正常。这时候不要怀疑硬件,先去核对设备树。
3.3 正确选定设备树的链路
确定设备树不是拍脑门,而是沿着一条链路去追。完整的链路是:产品配置 -> 编译产物 -> 烧录打包 -> U-Boot加载。
第一步:从产品配置确认编译目标。
OpenHarmony的编译是通过productdefine和device/board下的配置文件驱动的。以标准RK3568 EVB板为例,产品配置在vendor/rockchip/rk3568/目录下,编译时会根据config.json里的配置决定使用哪个内核和哪个设备树。如果用的是官方开发板,直接参考社区默认配置即可。
第二步:从编译产物确认实际生成的dtb。
编译完成后,内核编译产物目录下会生成对应的.dtb文件。比如默认配置编译出来的是rk3568-evb1-ddr4-v10.dtb,那烧录包里带的就是它,U-Boot也会加载这个名字对应的dtb。换句话说,你不需要自己在那一堆dts里挑,编译系统已经帮你选好了,前提是你没改错配置文件。
第三步:U-Boot阶段确认加载的dtb。
板子上电后进U-Boot命令行,执行:
printenv重点看fdtfile变量,这个变量直接指定U-Boot加载哪个dtb文件。如果这里面的值和你的板子实际硬件不匹配,那就是问题根源。
第四步:烧录后验证系统实际使用的设备树。
系统起来之后,执行:
hdc shell cat /proc/device-tree/model cat /proc/device-tree/compatible如果打印出来的model名称和你的板卡对不上,比如跑的是Rockchip RK3568 EVB1 DDR4 V10 Board,但你的板子实际是EVB2或者自研板,那就说明设备树用错了。还有一个更直观的命令:
ls /proc/device-tree/目录下的顶层节点就能看出这个设备树为哪些外设预留了配置。
如果没有现成设备树怎么办。
自研板卡是最常见的情况。不建议从头写dts,正确姿势是从官方EVB的dts中选一个最接近的作为模板,在此基础上改差异点。改的优先级是:
- DDR类型和频率,这个错了起不来。
- 调试串口号和波特率,改错了看不到日志。
- 电源IC型号和I2C地址,错了系统会在内核初始化阶段挂掉或无法调节电压。
- 各外设的I2C地址、reset/irq gpio号、pinctrl配置,错了对应外设无响应。
每次只改一个模块,保存后编译、烧录、验证,这样在哪一步出了错能快速定位。
提示:OpenHarmony内核编译时修改设备树后,需要重新编译内核并重新烧录
boot分区或dtb分区。有些时候你会发现改了dts重新编译后效果没变化,先确认一下有没有单独烧写dtb分区,或者U-Boot里是不是还缓存着旧的dtb。
4. 第三板斧:hdc与hilog——系统起来之后的运行态诊断
4.1 hdc连接与常用调试姿势
系统能正常启动到桌面或者shell之后,串口的使命就基本完成了,运行态的调试主力切换到hdc。hdc是OpenHarmony的开发者调试工具,功能和Android的adb类似,但命令体系和协议完全不一样,别拿adb的思路硬套。
连接方式分两种:USB连接和网络连接。USB连接是默认方式,开发板通过USB线连接电脑后,在系统设置中开启开发者模式,然后在电脑上执行:
hdc list targets能列出设备说明连接正常。如果列不出来,优先检查三件事:
- USB线是不是纯充电线,换一根数据线试试。
- 开发板的USB调试开关是否打开。
- hdc服务是否在运行,执行
hdc kill再hdc start重启服务。
网络连接用于多设备联调或USB不稳定的时候,在hdc shell里面执行:
hdc tconn 192.168.1.100:5555IP换成开发板的实际IP,端口默认5555。USB模式和网络模式可以共存,但要注意如果USB先连着,网络tconn可能会连接失败,先拔掉USB再试。
hdc最常用的几个命令组合:
hdc shell # 进入系统shell hdc file recv /data/log /tmp/ # 从设备拉取日志文件 hdc file send ./xxx /data/ # 推送文件到设备 hdc hilog # 抓取hilog日志 hdc shell dmesg # 查看内核日志建议第一次拿到板子就把这几条命令跑一遍,确认基本链路通畅,后续调试会顺很多。
4.2 hilog过滤:在茫茫日志里捞出关键信息
hilog是OpenHarmony的系统日志工具,对应Android的logcat。刚上手的时候容易犯一个错误:直接执行hilog然后被海量日志淹没,什么都看不出来。正确的做法是先加过滤条件。
按服务标签过滤:
hilog | grep POWER hilog | grep DISPLAY hilog | grep SOFTBUS按日志级别过滤,排查错误时最有用的命令:
hilog | grep " E "只显示Error级别以上的日志,能滤掉绝大多数噪音。如果系统某个服务反复重启,用这个命令能快速看到报错内容。
按进程名或进程号过滤,先通过ps -ef找到对应服务的pid,然后:
hilog | grep "进程名"对于硬件调试还有一个很有用的组合:把hilog重定向到文件,完整记录一段时间,然后拉回PC分析:
hilog -w start # 复现问题 hilog -w stop hdc file recv /data/log/hilog/ /tmp/日志文件比较大,拉回来之后用grep配合关键字去查,比在设备上实时盯屏幕高效。实测一次完整启动到桌面的日志量在50MB左右,用文件方式不会漏信息。
4.3 内核态与硬件状态查看
用户态日志看完了,硬件相关的问题要下探到内核态。dmesg是最基础的手段:
hdc shell dmesg | grep -i "fail\|error\|timeout"但这个命令只显示错误,很多外设问题是“没报错但不工作”。这时候需要主动查看内核为外设建立的设备节点和sysfs信息。
查询I2C总线上挂了哪些设备:
ls /sys/bus/i2c/devices/如果某个传感器芯片的设备树地址配错,或者I2C通信失败,这个目录下就不会出现对应的设备节点。
查询GPIO状态:
cat /sys/kernel/debug/gpio这个文件会列出当前所有GPIO的占用情况和电平状态,能确认外设的复位脚、中断脚是否被正确拉高拉低。
查询中断触发情况:
cat /proc/interrupts看对应的中断号计数是否在增加,如果不增加说明中断没有产生,问题可能出在设备树的中断配置或硬件连接上。
这一套组合下来,系统起来了但外设不工作的问题,基本都能定位到具体是“设备没被注册”还是“注册了但通信失败”还是“通信正常但中断不触发”,再往下就是查看对应驱动代码和寄存器配置的问题了。
5. 三板斧之外的必要补刀:分布式联调与x86模拟器的差异
5.1 分布式硬件调试场景
OpenHarmony最被看重的能力是分布式,但在分布式场景下调试硬件问题,很多人会掉进同一个坑:单板调试没问题,多板组网之后功能异常,不知道该查哪边。
先说结论:分布式硬件调试仍然是用三板斧的逻辑,只是把范围从单板扩展到多板。每一步排查都要先确认“当前这个问题发生在哪块板上、是硬件层还是传输层”。
举例来说,手机和开发板组网后发现远程调用开发板的传感器数据超时。先不要急着查软总线源码,按照顺序做三件事:
第一,分别确认两块板的hilog里有没有SOFTBUS相关的error日志:
hilog | grep SOFTBUS | grep " E "第二,确认两块板的网络连通性:
hdc shell ip addr show第三,确认传感器在开发板上单独测试是否正常:
hdc shell sensor --list绝大多数分布式硬件问题最终都会被定位到某一端的硬件节点配置错误或者网络链路不稳定,真正需要深入分布式通信协议底层去排查的频率并不高。三板斧的逻辑在分布式场景下依然成立:先把每一端的硬件问题排除干净,再怀疑分布式框架本身。
5.2 x86模拟器与真机硬件调试的区别
社区里经常有人问“能不能用电脑模拟器跑OpenHarmony做硬件开发”。答案是可以跑,但只能做应用层开发和部分HDF驱动框架的验证,硬件调试必须回到真机。
x86模拟器环境下没有真实的GPIO、I2C、SPI、传感器这些硬件,设备树的作用被极大弱化,启动流程里也没有DDR训练、PMIC配置这些环节。它的调试重点是验证三个层面:
- 应用逻辑和UI是否正常
- 系统服务之间的IPC通信是否正常
- 标准HDF驱动接口的调用链路是否正常
在模拟器里做调试,串口基本用不上,串口输出直接重定向到了虚拟终端;hdc可以通过网络连接模拟器;hilog的用法和真机完全一致。所以如果是在模拟器里做开发,串口这一板斧可以直接放下,聚焦设备树(其实没有太多的设备树概念)和hilog这两板斧就够了。
但这里有一个重要提醒:很多在模拟器上验证正常的HDF驱动代码,搬到真机上不一定能跑通。因为硬件配置信息在模拟器里是假的,到了真机才真正走设备树匹配、中断申请、引脚复用的流程。所以如果你最终目标是真机硬件产品,模拟器只适合做功能验证,硬件调试的主战场永远是带着串口线和真实开发板的工作台。
5.3 调试环境搭建的投资回报
每次带新人入门OpenHarmony,我都要求他们做的第一件事不是读代码,而是花十五分钟把串口、hdc、hilog这三条链路全部打通,并且把这几个命令背下来:
minicom(或者个人习惯的串口工具)打开串口hdc list targets确认设备在线hdc shell dmesg | grep -i error确认内核干净hilog | grep " E "确认系统服务干净
这套环境搭完之后,你做的每一步修改——改设备树、换驱动、调参数——都可以用这几条命令快速验证效果,形成“改动-验证-再改动”的闭环。很多人在开发中后期被莫名其妙的稳定性问题折磨,回头反思,往往是最开始没有建立一个干净的基线环境,导致后续所有改动都无法对照。单板、x86模拟器、分布式多板联调这三个环境下的调试方式有明显差异,先把适用范围搞清楚比多做几步调试动作更重要。
6. 实战收尾:三板斧组合定位一次"屏幕点不亮"
6.1 故障描述与初始排查
最后用一个真实案例把三板斧串起来走一遍,这个案例非常有代表性,症状是“RK3568开发板跑OpenHarmony,系统可以启动到桌面,HDMI输出正常,但MIPI-DSI屏幕点不亮”。
接到这个问题,先按第一板斧检查串口启动日志,关键看显示相关驱动的初始化信息。在串口输出里找到显示链路相关的关键字:
dmesg | grep -i "drm\|dsi\|panel\|lvds"日志显示rockchip-drm有初始化,但mipi_dsi相关的panel驱动没有匹配成功,具体报错是panel not found。到这里问题范围缩小到了设备树对屏幕panel节点的配置。
6.2 从设备树到运行态的逐层定位
第二板斧上场,检查当前系统实际加载的设备树:
cat /proc/device-tree/model确认加载的设备树是rk3568-evb1-ddr4-v10.dtb,这个板子做的硬件修改恰好是把默认的HDMI方案换成了MIPI-DSI屏,但dts里没有添加对应的panel节点。
找到内核源码里的dsi节点配置,在/sys/firmware/devicetree/下查看显示器节点的存在情况:
ls /proc/device-tree/果然没有看到dsi相关的panel子节点。于是重新修改设备树,在dsi@fe060000节点下补充panel配置,指定正确的compatible字符串、复位GPIO、初始化序列,重新编译内核烧录boot分区。
6.3 第三板斧验证结果
系统重启后,用hdc连上设备,先用hilog验证驱动是否match成功,还是用过滤命令:
hilog | grep DRM这次能看到panel驱动的probe调用日志,说明panel节点被正确识别了。再查显示链路状态:
cat /sys/class/drm/card0-HDMI-A-1/status cat /sys/class/drm/card0-DSI-1/statusDSI节点的状态从disconnected变成了connected,屏幕点亮,问题解决。
整个排查过程没有用到示波器,也没有改一行驱动代码,纯粹靠串口定位方向、靠设备树确定配置、靠hilog验证结果,三板斧走一遍就结束了。这个案例不是特殊情况,外设相关的问题十有八九都是这个模式。屏幕、触摸、WiFi、声卡、传感器、以太网,全部适用。
6.4 三板斧解决不了的情况
必须说明的是,三板斧不是万能的。如果上述排查已经确认设备树配置完全正确、运行态日志干净、驱动probe成功,但外设依然不工作,这时候才轮到示波器和逻辑分析仪上场。比如触摸屏有中断上报但坐标乱跳,可能是I2C时钟线信号质量差;音频有输出但底噪大,可能是电源纹波问题;屏幕偶尔闪屏,可能是MIPI信号线等长没做好。这一类模拟域问题,软件配置改不动,必须用硬件仪器去量。
所以在团队协作中,三板斧的真正价值是帮助你把问题尽可能往前推,把所有软件能排除的变量全部排除干净,最后剩下的硬件问题再交给仪器和处理手段去解决。这也是一种分工逻辑,软件工程师先用三板斧定位,确认不是软件问题再转给硬件工程师,避免大家一开始就在错误的方向上消耗时间。