OpenHarmony硬件调试三板斧:串口日志、设备树核查与状态捕获 1. 为什么我把硬件调试的底气押在这三招上接触OpenHarmony硬件调试这几年几乎每隔几天就会在技术群里看到同一个问题冒出来“RK3568有那么多设备树到底选哪个”紧跟着的往往是“串口没输出”“启动到一半卡死”“网口怎么都不通”。这些问题看起来八竿子打不着可归根到底都是缺了一个硬件调试的抓手。OpenHarmony跟普通单片机开发完全是两个路子你面对的是从Bootloader到内核再到分布式服务的完整系统任何一个环节出问题表象都可能只是一句“黑屏”“卡住”“没反应”靠肉眼和万用表根本无从下手。所以我一直把OpenHarmony硬件调试提炼成三板斧串口日志、设备树核查、系统状态捕获。这套方法适用面很广。无论你刚拿到一块RK3568评估板还是自己画板子做OpenHarmony适配又或者只是在x86虚拟机里跑OpenHarmony做应用开发三板斧都能帮你把问题从“玄学”变成“证据链”。这期教程就围绕这三板斧展开我会把每一招的具体用法、背后原理、常见坑一次说清楚顺便把社区里关于设备树选型和串口连接的高频疑问一并拆掉。需要说明一下我这边的板子以RK3568系列为主但方法本身是通用的。无论是海思、瑞芯微还是全志平台只要跑的是OpenHarmony标准系统串口、设备树、崩溃日志这套排查逻辑都成立。下面直接进入第一板斧。2. 第一板斧串口日志启动全过程都在这根线上2.1 调试串口在RK3568上的接线与波特率先说最基础也最容易被卡住的一步怎么把串口接出来。OpenHarmony标准系统在RK3568平台上默认的调试串口是UART0就是通常在核心板/底板丝印上标记为DEBUG、UART_DBG或者DBG_TX/DBG_RX的那组引脚。配套的调试小板一般是USB转串口模块常见的芯片是CH340、CP2102或者FT232这类模块在Windows和Linux下都有现成驱动插上之后在设备管理器里能看到对应的COM口。接线规则不复杂交叉接调试板的TX接开发板的RX调试板的RX接开发板的TX然后共地GND。很多新手第一次接串口没输出超过一半的原因是TX/RX接成了直连两根线对调一下就好了。电平上RK3568核心板的调试串口通常是1.8V或者3.3V电平和USB转串口模块的电平不完全匹配时建议用带电平转换的模块但绝大多数评估板已经在底板做了电平匹配直接连模块就能用。接下来是波特率。OpenHarmony标准系统在RK3568上默认调试串口波特率是1500000也就是1.5Mbps。这一点跟很多传统嵌入式设备默认115200的习惯完全不同我刚接触时也在这上面栽过跟头拿着115200去连屏幕上全是乱码。但也有部分厂商的建议方案文档里写的是115200所以正确做法是先查你手头板卡的官方文档确认波特率确认不了就直接试1500000如果乱码再换115200。像MobaXterm、SecureCRT、PuTTY都能自定义波特率Linux下用minicom/picocommacOS直接用screen命令也能连。我平时在Windows下用得最多的是MobaXterm新建Session选Serial填上COM口号和波特率回车就能看到开机日志。Linux下推荐picocom一条命令就够sudo picocom -b 1500000 /dev/ttyUSB0如果你用的是虚拟机作为日常工作环境记得把USB转串口设备直通到虚拟机里否则宿主机能看到串口、虚拟机看不到。2.2 串口终端里的两类日志内核的dmesg与系统的hilog串口接通之后按一下开发板的复位键或者重新上电你会看到一整屏日志从眼前滚过去。很多人看到日志就晕不知道该看哪一段。这里有一个基本的分层概念对后续定位问题至关重要。第一类是内核日志包括U-Boot阶段和Linux内核阶段的输出。U-Boot阶段会打印SoC信息、DDR初始化结果、启动介质和环境变量等信息内核阶段会打印各个驱动的probe情况、设备树加载情况、内存布局等。这类日志在OpenHarmony系统起来之后可以通过dmesg命令重新查看。第二类是系统级日志也就是HiLog。OpenHarmony的应用框架、系统服务、分布式软总线、传感器、电源管理等模块都会通过HiLog体系记录日志。HiLog日志会通过系统的hilogd服务同时输出到串口控制台所以串口上看到的彩色日志如果没有关闭颜色的话大多数属于这一类。这两类日志的分工可以简单理解为内核日志告诉你“硬件层跑没跑通”HiLog告诉你“系统服务和应用层发生了什么”。排查启动问题通常先把内核日志和系统日志的分界时间点找到当你看到类似[OHOS]或者#开头的shell提示符出现时说明内核已经启动完毕init和后续系统服务开始运行后面打印的就是系统级日志了。在实际排查中我会同时开两个窗口一个窗口用MobaXterm盯着串口实时日志另一个窗口在板子上执行dmesg | grep -i fail\|error过滤内核报错。串口日志是实时流水适合看现场dmesg则是事后翻记录适合找线索。2.3 通过日志级别过滤快速锁定异常模块串口日志刷屏是一个很现实的问题。尤其是OpenHarmony标准系统开机后各种系统服务、分布式能力组件都会打日志一屏一屏往外滚你根本来不及看。这时候用过滤就很关键了。在串口控制台上如果系统已经正常起来并且能进入shell通过串口进入的shell你可以用hilog命令做级别过滤和关键字过滤。hilog的基本用法是hilog # 持续实时输出系统日志 hilog -e ERROR # 只输出包含ERROR的日志 hilog -e FATAL # 只看致命错误 hilog -w # 清空当前日志缓冲区 hilog -x # 退出hilog实时输出这套命令在调试阶段非常实用。我遇到系统服务反复重启或者某个应用崩溃时会先把实时日志停下来然后执行hilog -w # 复现一次问题操作 hilog -e FATAL清空缓冲区之后再做一次问题复现随后只查看FATAL级别的日志这样做的好处是把无关信息全部过滤掉问题的“第一现场”会非常干净。如果是内核驱动级别的问题dmesg里的fail、error、timeout就是重点对象配合时间戳或者驱动的名字一起grep比如网口驱动是gmac就执行dmesg | grep -i gmac\|stmmac\|eth内核日志里的报错信息和HiLog里的FATAL信息往往能互相印证。串口不是只看一遍就完事的东西它是整台设备的“飞行记录仪”把关键节点日志保存下来后续排查设备树或者服务状态时会反复用到。2.4 真机经验串口连不上、乱码、刷屏的排查方向串口部分最后集中说三个高频问题都是我实际踩过或者看别人踩过的。第一个是完全没有输出。按复位键后串口终端一片空白。优先检查接线是否交叉、GND是否共地、波特率是否与板卡文档一致、USB转串口模块是否被系统识别Windows下设备管理器有没有多出COM口。如果模块识别了但没输出再检查是不是接错了引脚有些底板上有好几组排针标注为GPIO的并不一定是调试串口。第二个是乱码。乱码意味着波特率不匹配或者电平逻辑有问题。先换波特率试1500000、115200、921600这几个都试一遍还是乱码的话检查USB转串口模块和板卡之间的电平特别是需要外接供电的模块看看有没有共地。还有一种情况是板卡上的调试串口被系统复用成其他功能了这个在OpenHarmony里可以通过设备树重新配置后面第二板斧会讲到。第三个是日志狂刷导致卡顿。系统起来后日志量太大串口工具都拖不动。这本身可以通过配置HiLog的输出级别来解决但更快的临时办法是在串口终端里按CtrlC中断当前的hilog输出回到shell提示符下再按需查看日志。商用调试中也有人直接在系统起来后把串口日志级别调低让串口只输出ERROR和FATAL。3. 第二板斧设备树先把“板子是谁”告诉内核3.1 为什么RK3568的设备树文件多到让人发懵热搜词里“openharmony的rk3568有许多设备树到底咋选”这个问题我几乎每天都能看到。根本原因在于OpenHarmony官方、芯片原厂、以及各开发板厂商会基于同一颗RK3568芯片维护多套设备树文件。RK3568是一颗通用SoC它本身只有芯片级的能力定义比如CPU核心、GPU、内存控制器、各类接口控制器但一块具体的板子上用的DDR是DDR3还是DDR4还是LPDDR4走的是哪个PHY地址网口用的是千兆还是百兆LCD屏幕的分辨率和时序参数触摸屏走I2C还是SPI这些全部由板级设备树来描述。所以你在内核源码的arch/arm64/boot/dts/rockchip/目录下会看到一大堆rk3568开头的dts文件和dtsi文件比如rk3568-evb1-ddr4-v10.dtsrk3568-evb2-lpddr4-v10.dtsrk3568-evb4-ddr4-v10.dtsrk3568-evb5-lpddr3-v10.dtsrk3568-nvr-demo-v10.dts这还只是原厂内核的一部分。各开发板厂商拿到源码后会基于这些文件复制一份改改名、改改外设配置就成了自己板卡的设备树。所以“设备树多”不是因为内核在有意制造困惑而是因为硬件组合本身太多。理解了这一点你的心态就会从“选哪个”变成“我的板子硬件到底是什么样”这个思路转变很关键。3.2 从dtsi到dts设备树的覆盖机制要理解设备树为什么可以一个套一个得先明白dtsi和dts的关系。dtsi是“include文件”类似于C语言的头文件定义的是可以被复用的设备树片段dts是最终编译成dtb的源文件。一个典型的RK3568工程会有这么几层rk3568.dtsiSoC级定义。描述CPU、中断控制器、I2C控制器、UART控制器、GMAC控制器等所有芯片内部IP的默认状态。注意这里多数节点默认status disabled具体用不用由板级决定。rk3568-evb.dtsi板级公共定义。这块板子上有哪些外设、哪些IO被复用了通常会写在这里。rk3568-evb1-ddr4-v10.dts具体型号定义。DDR类型、屏幕型号、触摸IC这些更“个性”的东西写在这里。各个文件通过#include一层层组合后包含的文件可以覆盖前面文件里的节点属性。这就是设备树最核心的机制继承加覆盖。你在某个具体的dts里看到一个gmac1节点它不是凭空出现的而是先在rk3568.dtsi里把gmac1控制器定义好再在这个文件里把status改成okay并补上PHY地址、复位引脚等信息。所以在改设备树之前必须知道自己正在操作的是哪一层。最常见的问题是在某个dtsi里改了外设配置结果编译出来的dtb根本没包含这个文件改了等于白改。正确做法是先追#include链确认当前dts确实引用了你改的文件。3.3 日常开发中如何锁定当前板卡对应的dts现在回答那个高频问题RK3568设备树到底咋选。我的做法是按下面几步来基本能锁定正确目标。第一步看外观丝印。大部分开发板会在PCB上标注型号比如EVB1、EVB2、V10等这些代号与设备树文件名字直接相关。找到丝印之后再到源码目录里找匹配的dts文件。第二步看内存颗粒类型和容量。DDR3、DDR4、LPDDR4在设备树里是不同的文件后缀ddr3、ddr4、lpddr4。如果你用的是6GB的LPDDR4板子结果选了ddr4的dts大概率识别出的内存容量不对系统起来之后动不动就出问题。确定内存类型最直接的办法是看板卡规格书或者拆开散热片看颗粒丝印。第三步看官方资料。OpenHarmony官方在文档中心的“标准系统入门”里对不同的开发板如RK3568 EVB系列都会列出对应的内核源码分支和设备树名称。很多厂商的README里也会写“本SDK基于rk3568-evb1-ddr4-v10.dts适配”。第四步看U-Boot日志。这一步非常有用。板子上电时U-Boot会打印出它读取的板级信息有些版本会直接显示Board: Rockchip Linux Board甚至包含具体的dts名称。串口日志里能看到一行类似Device Tree: rk3568-evb1-ddr4-v10.dtb的信息那就是U-Boot实际加载的设备树。第五步系统起来之后验证。这是最稳妥的兜底方案。板子能进系统后读取设备树中的model属性cat /sys/firmware/devicetree/base/model正常会输出类似Rockchip RK3568 EVB1 DDR4 V10 Board的字符串如果你手上板子明明是EVB2但输出的是EVB1那就说明当前加载的设备树和硬件不匹配烧录时需要重新打包正确的dtb。3.4 设备树编译、打包与加载验证在OpenHarmony工程里设备树的编译和打包不是单独执行的而是集成在内核编译链路中。你通常需要在板级目录下的配置文件中指定设备树名称。以RK3568为例在device/board或者vendor下相应板卡目录的config.gni或BUILD.gn中会有一个变量指定内核设备树文件名我这边常见的配置项类似kernel_device_tree_name或dts_name值就是rk3568-evb1-ddr4-v10.dts去掉“_dts”后缀的名字。配置好之后执行OpenHarmony的编译命令比如./build.sh --product-name rk3568 --ccache编译完成之后生成的dtb会被打包到boot分区镜像里。烧录时boot分区被写进板子U-Boot从boot分区读取dtb并传递给内核。也就是说设备树选错往往是在内核启动那一刻就错了。很多时候你在源码里改了dts重新编译后也烧录了但启动后没效果先去查一下编译产物里的dtb是不是你改的那个——这能省掉大量的无效排查时间。我习惯在拿到一个OpenHarmony内核源码树之后先找到目标dts然后用下面的命令快速查看它最终包含哪些关键配置grep -n gmac\|lcd\|touch\|i2c rk3568-evb1-ddr4-v10.dts | head -50这个操作能让你在一分钟之内对这个板卡的外设配置有个整体印象。3.5 选错设备树的典型现象与快速识别选错设备树的症状通常不是“完全不能开机”而是“带病运行”这一点特别容易坑人。我列一个自己遇到过的对照表方便你快速自查现象很可能的原因开机卡在U-Boot阶段根本进不了内核内存类型/容量参数不匹配DDR初始化失败内核启动过程中反复panic外设地址或中断冲突常见于引脚复用重叠系统能起来但网络不通eth0不存在GMAC节点未打开或者PHY地址/复位引脚不对屏幕有背光但无显示或颜色错乱LCD时序/分辨率参数不匹配触摸没反应触摸IC的I2C地址或中断脚配置不对USB设备不识别USB控制器或PHY配置错误快速识别当前设备树是不是匹配有几条捷径。第一是前面说的cat /sys/firmware/devicetree/base/model。第二是看dmesg里的DDR信息对比实际板卡的内存容量和类型dmesg | grep -i memory\|DDR第三是看外设驱动的probe日志。以网口为例如果设备树正确内核日志里会出现stmmaceth相关的成功绑定信息如果找不到PHY会报类似cannot attach to PHY的错误。这串日志往往比任何文档都诚实。4. 第三板斧崩溃与服务状态捕获让现场证据说话4.1 hdc通路的建立与日常命令串口日志负责看过程设备树负责看配置但有些问题发生得太快、复现太随机光靠串口抓不到。这时候就要用第三板斧——通过hdc工具进到系统内部抓崩溃现场和系统状态。hdc是OpenHarmony的设备连接工具功能类似Android调试里的adb。它支持USB连接和网络连接两种方式。USB连接时先确保设备上开启了开发者模式系统设置里连续点击版本号然后用USB线连接开发板的OTG口和电脑hdc list targets如果列出了设备序列号说明通路建立成功。网络连接用于远程设备或者虚拟机里跑OpenHarmony的场景需要在设备上开启网络调试后在主机侧执行hdc tconn 192.168.1.100:5555我经常用一个命令组合来确认系统核心状态hdc shell param get | grep -i version hdc shell hilog -e \FATAL\ hdc shell dmesg | tail -100hdc出现连接不上的问题先检查USB线是不是数据线很多线只能充电不能传数据再检查设备开发者模式有没有打开最后看hdc服务是否需要重启hdc kill hdc start4.2 faultlogger崩溃后自动留下的案底OpenHarmony系统里有一个叫faultlogger的组件专门负责记录系统和应用的崩溃信息。当某个进程发生崩溃比如空指针、段错误、非法指令faultlogger会自动把崩溃现场保存到日志目录。这是排查“偶现崩溃”最重要的证据来源比你在串口屏幕前干等强一百倍。查看崩溃日志的路径非常固定hdc shell ls -lt /data/log/faultlog/faultlogger/ | head -20文件命名一般包含模块名、进程名、进程ID和时间戳。拿到最新的崩溃文件后我用下面的命令把内容拉到本地仔细看hdc shell cat /data/log/faultlog/faultlogger/xxx_faultlog.log崩溃日志里重点看三块异常类型比如SIGSEGV、SIGABRT、寄存器现场、调用栈回溯。调用栈能直接告诉你崩在哪个函数里配合源码定位通常半小时内就能找到问题。很多开发者遇到崩溃第一反应是“重新编译试试”我的建议是先看faultlog往往比重编快得多。4.3 hidumper不重启系统也能拿系统状态有时候问题不是崩溃而是某个外设或服务状态不对比如LCD不亮、WiFi连不上、传感器没有数据。这时候用hidumper把系统内部状态“dump”出来比猜靠谱得多。hidumper是OpenHarmony自带的系统信息导出工具能输出CPU、内存、系统服务等多个维度的状态。它的参数比较多不同版本略有差异我习惯先执行hdc shell hidumper -h查看当前版本的帮助确认参数后再执行对应的dump操作。比如查看系统整体配置和负载可以用--cpuusage和--memory查看服务列表和状态用-s加服务名如果某个服务是你要调试的对象直接调用该服务的dump接口输出内部状态。hidumper的核心价值在于不需要重启不需要打断现场就能拿到系统运行时的内部视图。比如说你怀疑某个系统服务挂了通过hidumper查看它能发现服务其实还活着只是某个内部状态不对这时候问题就收敛到了该服务的日志上排查范围一下子缩小很多。4.4 开启coredump并解读最小线索崩溃日志faultlog记录的是异常发生时的寄存器信息和调用栈但有时候栈回溯不够深或者问题出在内存被写坏看不到直接原因。这时候就需要coredump也就是把进程崩溃瞬间的完整内存镜像保存下来离线用调试器分析。OpenHarmony的coredump功能默认不一定开启需要用系统参数控制。我常用下面这条命令查看当前状态hdc shell param get coredump.filter如果返回0或者不在预期的开启范围内就按官方文档把过滤等级调到合适值再复现一次问题。开启coredump之后崩溃瞬间会把核心转储文件写到指定目录通常是/data/core或/data/log/faultlog/temp下面。拿到coredump文件后配合对应版本的符号表用调试工具比如llvm或gdb就能还原出完整的调用堆栈。有一点要提醒coredump文件体积很大低内存设备开启后要留意存储空间。我一般只在需要深挖某个疑难崩溃时临时开启定位完就关掉不让设备长期处于这个状态。4.5 跑x86版OpenHarmony的调试补充热搜词里有一条“电脑版x86 openharmony”很多人用虚拟机跑OpenHarmony做应用开发和分布式调试。x86版本和RK3568这类真机的调试套路基本一致差别主要在串口和hdc的连接方式上。如果你用的是QEMU跑OpenHarmony x86镜像串口可以通过QEMU的启动参数映射出来。一个常见的做法是把串口重定向到pty设备qemu-system-x86_64 -serial pty -display gtk启动后QEMU会提示char device redirected to /dev/pts/3然后用minicom或picocom连接这个pts设备就能看到串口日志。如果想把串口输出直接放到终端里可以加参数qemu-system-x86_64 -nographic这样QEMU把虚拟串口和标准输入输出绑定所有串口日志直接打在当前终端上对快速启动和观察日志来说非常方便。hdc连接虚拟机里的OpenHarmony则可以通过QEMU的端口转发功能。把设备侧的hdc监听端口映射到宿主机比如qemu-system-x86_64 -netdev user,idnet0,hostfwdtcp::5555-:5555 -device e1000,netdevnet0然后在宿主机执行hdc tconn 127.0.0.1:5555就能连上。x86虚拟环境的硬件外设跟真机不一样设备树的概念相对弱化但崩溃日志、hidumper、hilog这套排查思路完全通用。5. 用一个真实场景串起来板子起来了但网口不通5.1 串口日志先定位“挂在哪一层”前面三招分开讲很多人还是不知道怎么组合。我拿一个实际案例完整走一遍一块RK3568开发板烧录OpenHarmony标准系统后系统能正常启动屏幕也亮了但网口插上网线后怎么都不通ifconfig看不到eth0。第一步我先看串口日志。在串口终端里执行dmesg | grep -i eth\|gmac\|stmmac\|phy如果日志里完全搜不到GMAC驱动的初始化信息说明设备树里GMAC节点没有打开或者PHY没有成功探测。如果日志里能看到stmmac相关信息但报错cannot attach to PHY说明驱动起来了但PHY物理层芯片没挂上问题通常在PHY的地址配置或者复位引脚上。这里有个判断技巧系统能进入shell说明内核整体没崩问题大概率是板级配置层面的优先怀疑设备树如果连内核都进不去那就回到DDR、启动介质、引脚复用这些更底层的问题。5.2 设备树核查确认“板子身份”第二步我执行cat /sys/firmware/devicetree/base/model结果打印出来的是Rockchip RK3568 EVB1 DDR4 V10 Board。但看板卡丝印和规格书手上这块是EVB2、LPDDR4的板子。到这里问题已经很明显烧录的boot分区里打包的设备树是EVB1版本和硬件不匹配。结合之前看的dmesg日志GMAC节点在EVB1和EVB2设备树里配置的PHY地址、复位GPIO都不一样所以驱动起来后找不到正确的外部PHY网口自然不通。定位到这一步后面就是标准的设备树修正流程在内核源码里找到EVB2对应的dts文件比如rk3568-evb2-lpddr4-v10.dts确认板级配置文件里要编译的dtb名称重新编译boot分区镜像再烧录验证。5.3 崩溃与服务状态dump进一步收口如果修改设备树重新烧录后网口还是不通就需要第三板斧上场。先用hdc shell连进系统执行hdc shell ifconfig -a hdc shell dmesg | grep -i \gmac\|stmmac\ | tail -50看接口是否存在。如果eth0出现了但没拿到IP检查DHCP或者手动配置IP这时候需要用网络层的排查手段去解决比如ping网关、检查路由表这部分就是另一个话题了。如果在日志里看到网口驱动反复报错但没有明显的设备树问题那就打开faultlog和历史日志hdc shell ls -lt /data/log/faultlog/faultlogger/ hdc shell hilog -e \DHCP\|wifi\|netmanager\以此判断是系统网络管理服务的问题还是硬件驱动的问题。一个网口不通的问题通过三板斧一层层排查下来基本不会出现“无从下手”的情况。6. 三板斧之后的习惯才是真正值钱的东西方法讲完了最后说几句掏心窝的话。三板斧本质上不是在教你三个孤立技巧而是在帮你建立一套闭环串口看过程、设备树看身份、状态捕获看现场。很多同学拿到板子第一件事是急着烧录、急着跑应用但我建议把顺序反过来先确认串口能通再确认设备树匹配最后再开始功能开发。这三件事如果没做扎实后续排查成本会成倍增加。我自己的习惯清单大概是这样新板子到手先花十分钟接线开串口把启动日志完整存一份再读一下设备树的model属性确认板卡身份顺便看一眼DDR配置系统正常运行之后做一次faultlog目录的基线记录这样后面出问题就知道哪些日志是新产生的。这些习惯看起来不起眼但在真正遇到疑难问题的时候它们能帮你省下一整天的排查时间。另外OpenHarmony版本迭代很快不同版本之间串口默认行为、hdc命令参数、faultlog路径可能都有细微差异。遇到和教程对不上的地方先查你当前版本文档再结合串口日志里实际打印的报错信息去判断这个能力比记住任何具体命令都更值钱。