OpenHarmony硬件调试三板斧:日志、串口与hdc的实战应用

📅 发布时间:2026/9/8 11:57:23
OpenHarmony硬件调试三板斧:日志、串口与hdc的实战应用 做OpenHarmony系统开发这两年多我最常被问到的问题不是“业务代码怎么写”而是“板子上电以后我该干点啥”“日志全空白怎么定位”“RK3568那么多设备树文件到底选哪个”。说句实话这些才是系统实战开发里真正卡人的地方。今天这一篇我就把硬件调试的“三板斧”拆开揉碎——日志、串口、hdc讲讲我在真实项目里是怎么用这三样东西把一块不听话的板子调通的。这篇内容定位为【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】的一部分适合刚拿到开发板、正在搭OpenHarmony系统环境或者已经能烧录但跑起来就各种异常的开发者。硬件调试这件事听着玄乎其实日常高频用到的手段就是三板斧日志让你看到系统内部发生了什么串口让你在系统最早期也能听到呼吸hdc则让你在系统跑起来之后有完整的动态视图。三板斧配合好了绝大多数启动异常、驱动问题、系统卡死都能被一步步逼近到根因。1. 先说清楚为什么硬件调试要讲“三板斧”1.1 系统级开发和纯应用开发调试逻辑完全是两回事做OpenHarmony系统开发和写一个纯应用是完全不同的体验。应用开发时IDE里面有断点、有watch、有调试器代码没走对地方鼠标点一下就看到了。但系统开发面对的是一块嵌入式开发板硬件刚上电那一刻整个系统就是一个“黑盒子”。屏幕上可能连个画面都没有更不要说断点了。我在带新人时发现大部分人的第一反应是先打开代码看逻辑来回翻半天然后跑个demo发现还是不行就不知道该干嘛了。这个思路倒不能说错但顺序反了。系统开发遇到问题第一步永远不是看代码而是先确认“系统现在到底跑到了哪一步”。这一步靠什么确认靠日志、靠串口、靠设备状态。这三样就是硬件调试三板斧的由来。1.2 三板斧具体是哪三样它们各自管哪一段第一板斧日志系统hilog printk/dmesg。负责把系统运行过程中的关键信息输出出来是“黑盒子”内部状态的最直接映射。第二板斧串口UART。负责在系统最早期——从Bootloader到内核启动阶段——提供唯一的输出通道。屏幕没起来、网络没起来、USB没起来的时候串口往往是你唯一的眼睛。第三板斧hdcOpenHarmony Device Connector。负责在系统运行起来后提供交互式调试能力类似Android开发中的adb。有了它你可以进shell、看进程、查内存、抓日志、传文件。这三板斧覆盖了设备从“上电”到“系统运行”的全过程。串口管最早期日志管全过程hdc管运行态。三板斧之间是互补关系不是替代关系。很多人会觉得“我已经开了日志还要串口干什么”但你要知道日志输出的前提是日志系统本身已经跑起来了。如果问题发生在日志系统初始化之前那除了串口没有任何工具能看到现场。1.3 新手最容易犯的三个调试误区我梳理了一下带项目过程中见过的典型误区基本可以归纳为三条第一只看业务日志不看底层日志。业务进程crash了但真正的原因可能是某个驱动没有加载、某个节点权限不对这些信息业务层往往感知不到得去翻内核日志。第二一上来就接仿真器、上JTAG把调试动作搞得特别重。其实大多数启动问题三板斧就足够定位不需要上重型工具。调试工具越复杂引入的变量越多反而不利于快速定位。第三不复现就乱猜。系统开发里面一次崩溃的原因可能有好几种不靠日志把现场记录下来靠猜是猜不出来的。2. 第一板斧日志——先把“黑盒子”变成“透明盒子”2.1 OpenHarmony日志体系的基本格局OpenHarmony系统里的日志输出从底层到上层大概分这几层层次日志工具查看方式适用场景BootloaderU-Boot log串口直接看引导阶段、DDR初始化、启动参数是否传入内核printk / dev_dbgdmesg / 串口驱动加载、中断、DMA、文件系统系统服务HiLoghilogcatinit进程、samgr、分布式软总线等应用框架HiLoghilogcatability生命周期、业务逻辑、崩溃栈在OpenHarmony里用户态日志的核心命令是hilogcat它和Android的logcat用法非常像但背后是一套独立的日志系统和缓冲设计。内核日志则沿用Linux的printk体系通过dmesg查看。很多入门开发者最大的困惑是我在代码里加了printf为什么串口看不到这里要敲个重点——用户态的printf默认走的是标准输出如果这个进程不是由控制台直接启动的或者它的stdout被重定向到其他地方了你就什么也看不到。正确的做法是用OpenHarmony的HiLog接口写日志通过hilogcat看而不是依赖printf。2.2 调试过程中真正高频的hilog用法我日常用的hilog命令就那么几条但每条都能解决一类具体问题。# 实时查看全部日志 hilogcat # 按关键字过滤日志调驱动时最常用 hilogcat -e i2c # 按优先级过滤只看error级别 hilogcat -e E # 带时间戳和线程信息定位时序问题 hilogcat -T -v time # 清空缓冲排除历史干扰 hilogcat -c这里特别说下-e的过滤。刚接触系统调试的人经常犯一个错误hilogcat刷得飞快满屏都是系统服务的信息自己的日志被淹没了。这时候不要干瞪眼直接用hilogcat -e 关键字把无关内容全部滤掉。关键字的选取也有讲究最好是用你自己定义的TAG或独特的打印内容比如一个罕见的标识字符串这样过滤最干净。另外调试阶段我极其推荐把TAG设计得短而独特。短是为了日志行不冗余独特是为了过滤时不会和系统日志撞车。比如驱动调试统一以xxx_drv格式命名一看就知道是哪个模块。2.3 “日志没输出”到底是谁的锅日志没输出这是新手头上最大的一座山。我把它拆成几种情况完全没有任何日志先排除串口连接问题再看内核启动参数里有没有配置console输出。有启动日志但用户态日志为空大概率是hilog服务没起来或者进程的日志级别被过滤了。有用户态日志但内核日志看不到检查printk的console级别默认情况下info以上级别才往console输出。# 查看当前printk日志级别配置 cat /proc/sys/kernel/printk # 输出格式: 当前级别 默认级别 最小级别 启动级别printk的日志级别有一套经典的数字定义0到7数字越小级别越高。默认console级别是4也就是只有KERN_WARNING及以上的日志才会打印到consoleKERN_INFO这类比较低级别的默认看不见。调试驱动的时候经常需要在启动参数里加上loglevel8把级别拉满或者临时用echo 8 /proc/sys/kernel/printk调整但是重启会失效。我踩过的一个坑是.config里开了某个驱动的debug打印但内核日志级别不够导致dev_dbg输出的内容全部被吞了。后来才发现不是代码问题纯粹是级别设置问题。所以遇到“驱动好像没工作”的时候先看一眼printk级别再下结论。2.4 日志规范与性能取舍日志好用的前提是会用但如果滥用日志本身也会成为系统负担。在串口115200波特率下每秒大约只能输出11KB左右的数据如果日志打印频率过高串口会严重拖慢系统启动速度甚至导致watchdog超时。实际操作中我的习惯是正常版本产品尽量少打日志留info和error级别就够了。调试版本里把关键模块的日志全部打开但只开到debug级别不无限加详细打印。高频路径比如中断、硬件定时器回调里不要打日志要用计数器和环形缓冲在内存里记录等系统空闲再导出。这个习惯让我避免了很多“加了日志反而复现不了问题”的尴尬。3. 第二板斧串口——从开机第一行到panic现场的保命通道3.1 串口接线和参数看着简单但最容易翻车串口的硬件接线本身不复杂一个USB转TTL模块加三根线的事。但这里面的细节往往比想象中多我把关键点列出来电平匹配开发板的调试串口通常是3.3V TTL电平个别老平台可能是1.8V选USB转串口模块时要看清支持哪种电平。接线顺序GND先接然后接TX、RX注意开发板TX接模块RX开发板RX接模块TX。波特率OpenHarmony标准系统在部分RK3568板卡上默认调试串口波特率是15000001.5M也有很多板卡是115200。如果串口终端出现乱码先别急着怀疑硬件去改波特率试试。波特率这个问题特别值得单独说。很多人在RK3568上拿到的OpenHarmony镜像串口默认配置是1500000而新手习惯用SecureCRT或MobaXterm默认的9600或115200结果打开就是一屏乱码然后疯狂怀疑自己的串口线坏了。我做过不止一次“远程指导换波特率”的事换完立刻正常。所以拿到一块板子第一步是确认调试串口波特率到底是多少去翻板级文档或内核dts里的chosen节点。3.2 串口输出的三个阶段每个阶段的log含义完全不同我曾经把串口输出比作“系统从沉睡到苏醒过程中的心电图”不同阶段能看到的信号完全不同。第一阶段BootloaderU-Boot阶段。这个阶段串口能看到SoC厂商的初始化信息包括DDR大小、时钟、存储介质、环境变量等。对于“系统完全没反应”的问题这个阶段最关键——它能确认芯片是否在工作、DDR是否初始化成功、有没有加载到boot.img。第二阶段内核启动阶段。能看到内核版本、设备树加载情况、驱动初始化顺序。最常见的卡死现场就是在这个阶段比如某个驱动在probe的时候卡住了串口输出停在最后一行不再继续。这种信息直接指向问题模块。第三阶段init与系统服务阶段。能看到init进程逐步启动系统服务的过程。如果你发现串口输出混乱、init反复重启往往是init配置或某个关键服务crash了。确认看的是哪个阶段才能判断问题属于哪一层。这是定位问题的基础。3.3 串口完全没输出按这个顺序查如果板子上电以后串口终端干干净净一个字符都没有不要慌按照下面这个顺序一步步来万用表确认开发板供电是否正常核心板有没有电流。这一点很重要有时候你以为串口坏了其实是板子压根没上电。检查串口模块驱动是否正常ls /dev/ttyUSB*或设备管理器里能看到COM口。确认接线正确尤其是TX和RX有没有接反GND有没有共地。确认波特率设置正确尝试不同的常见值。如果换了一块板子串口就有输出那说明原板卡的调试串口或者核心板本身有问题。有一次我排查一个“串口无输出”的问题前面四项都排除了最后发现是开发板上一颗LDO坏了导致调试串口电平根本没起来。这种情况靠串口自己是不可能知道的只能用万用表去量电平。所以串口调试的基础技能其实是会用万用表。3.4 串口的日志过滤与转储技巧串口输出信息量太大也是个问题。系统启动时内核会打印大量信息很多内容转瞬即逝仅仅靠肉眼盯着屏幕是没有办法捕捉的。我的做法是用工具把串口内容实时记录到电脑上然后再慢慢分析。在Linux上我一般用minicom加日志参数Windows下用MobaXterm自带的日志记录功能。下面是一个Linux下通过minicom保存串口日志的典型方式# 安装minicom sudo apt install minicom # 配置串口参数-D指定设备-b指定波特率 minicom -D /dev/ttyUSB0 -b 1500000 # 实际调试时用script命令把终端内容同时保存到文件 script -f uart_log_$(date %Y%m%d_%H%M%S).txt还要注意一点当需要长时间开机抓log时建议买一个带硬件缓存的USB转串口模块避免电脑端USB休眠导致丢数据。对那种只在深夜出现一次的问题挂机把日志记录下来第二天再分析比人工盯一晚上靠谱得多。4. 第三板斧hdc与板上信息采集——把“动态视图”补全到运行态4.1 hdc在OpenHarmony调试中的角色hdc这个名字全称是OpenHarmony Device Connector是OpenHarmony系统中负责与设备通信调试的枢纽工具。用过Android adb的人会觉得很熟悉但hdc不是adbcopy它有自己的参数体系和连接方式。在系统已经成功启动的前提下hdc能够做的事情非常多# 进入设备shell hdc shell # 在shell里查看hilog hdc shell hilogcat # 查看已连接的设备 hdc list targets # 上传文件到设备 hdc file send ./test.txt /data/test.txt # 从设备拉取文件 hdc file recv /data/log/test.log ./hdc的价值在于它提供的是一个“活的系统视图”而不是像串口那样只能看输出。通过hdc shell我可以随时查看系统状态、改配置、抓取一次操作前后的差异这就是运行态调试和启动阶段调试本质的区别。4.2 常用排查命令组合在OpenHarmony中调试系统问题下面这些命令的组合拳我几乎天天在用# 查看内核日志 hdc shell dmesg # 查看help动参数 hdc shell cat /proc/cmdline # 查看进程列表重点关注异常进程 hdc shell ps -ef # 查看CPU负载 hdc shell cat /proc/loadavg hdc shell top # 查看内存信息确认是不是内存耗尽 hdc shell cat /proc/meminfo # 查看系统参数OpenHarmony特有的param体系 hdc shell param get # 查看设备分区布局 hdc shell cat /proc/partitions这套组合能快速回答几个核心问题内核状态好不好、系统有没有在正常工作、资源够不够、设备配置对不对。很多“诡异”的问题最后都能在这套命令里找到线索。我印象很深的一个例子某个rk3568板子上系统的某个能力模块老是异常退出业务日志里看不到任何有价值的信息。后来我用hdc shell dmesg一看发现内核里有大量Out of memory的杀进程记录。系统内存本就紧张某个服务还常驻大块匿名内存杀掉之后反复重启看着像软件bug实际是内存配置不合理。这类问题的定位思路三板斧缺一不可。4.3 日志落盘与离线分析有些问题出现的时间不固定复现一次要很久而且现场可能没有电脑连着串口。这种时候必须依赖日志落盘。hdc shell里可以开启hilog持久化把日志写到设备上的文件问题复现后再把文件拉出来分析。具体流程一般是# 进入设备shell hdc shell # 启动hilog持久化到文件指定缓冲区大小 hilog -w core -f /data/log/hilog -n 100 -m 1024 # 问题复现后停止 hilog -w stop # 退出hdc shell后在电脑端拉取日志 hdc file recv /data/log/hilog ./还有一种更轻量的方式就是直接把hilog的缓存实时导出来。真要说哪种最好得看具体场景。我自己习惯在问题复现前就把持久化打开宁可多抓一些无关日志也不要漏掉关键时刻的一行信息。4.4 hdc连不上的时候三板斧内部怎么互相救援hdc连不上是运行态调试里最常遇到的窘境。设备明明上电了屏幕可能也亮了但hdc list targets就是空的。这时候需要冷静分析可能原因一hdc服务本身没启动。OpenHarmony的hdc守护进程是在init阶段拉起的如果系统启动过程有异常hdc就可能没起来。可能原因二USB枚举失败了。USB线、接口、供电方式都会影响。可能原因三系统已经卡死但外观看不出来。这种局面下我是用串口重新接入系统先看ps -ef里有没有hdc进程再用dmesg | grep usb看USB枚举有没有成功。这个过程正好体现了三板斧的配合串口是保底的入口日志提供判断依据hdc是最终要恢复起来的调试手段。三者像一个闭环互相兜底。5. 实战案例RK3568板子起不来我用三板斧定位的过程5.1 先选对设备树RK3568这么多dts到底怎么选RK3568应该是OpenHarmony社区里最活跃的硬件平台之一但正因为活跃问题也最多。其中最经典的问题就是系统根目录下有那么多和rk3568有关的dtb文件该烧哪一个先说结论选择设备树的依据不是“哪个长得像”而是三个硬指标——DDR类型、asic芯片型号有无带安全特性、板级外设差异。以OpenHarmony常见内核5.10的编译输出来看常见的RK3568设备树文件大致有这些设备树文件适用板卡情况rk3568-evb1-ddr3-v10.dtbEVB1评估板DDR3内存颗粒rk3568-evb1-ddr4x-v10.dtbEVB1评估板DDR4X内存颗粒rk3568-evb2-lpddr4-v10.dtbEVB2评估板LPDDR4内存颗粒rk3568-toybrick.dtbToybrick系列板卡rk3568-nvr-demo-v10.dtbNVR方案演示板如果你的板子是核心板加底板的组合那就要仔细看核心板上的DDR是什么类型再从上面这个列表里挑对应的dtb。DDR类型对不上内核启动早期就可能直接hang住或者进系统后内存不稳定、应用随机崩溃。另外同一个开发板在不同发行版本里设备树文件名可能略有出入。我的建议是优先找板卡配套的官方文档或README里指定的设备树文件名实在找不到再按内存类型和板级配置去排查。5.2 串口停在Boot阶段先确认loader的状态有一次我手里的RK3568板卡烧录OpenHarmony之后上电串口信息停在U-Boot 2017.09 ... ...然后就再也没有后续输出。从串口信息来看Bootloader阶段已经执行了一部分但显然没有完成。遇到这种情况我的排查路径是先确认loader是从什么介质读取的有没有读到正确的U-Boot环境变量。确认分区表结构和烧录的镜像是否匹配。重点确认dtb有没有被正确加载启动参数有没有完整传递给内核。当时最后定位出来的原因挺意外的设备树文件里DDR类型写的是LPDDR4但板上实际贴的是DDR4颗粒。内存参数不对启动过程中一旦访问到错误的内存配置就hang住。换回匹配的dtb之后系统一路顺畅启动。这个案例说了两件事一是设备树选择是启动问题里优先级非常高的一层二是串口输出虽然只停在一行但它已经帮你把范围框死在Bootloader到内核初始化这一段了。5.3 内核起来了但黑屏日志与hdc交叉验证另一个典型案例是串口已经能看到内核日志init进程也在跑但HDMI输出黑屏。这种情况下系统没有完全死掉因为hdc可以连上日志也还在滚动。问题被定位到显示链路。我用hdc shell hilogcat -e HDMI过滤显示相关日志又用hdc shell dmesg | grep -i vop看内核显示控制器的工作状态再检查HDMI的电源和时钟。最后发现是某个版本的显示驱动对特定分辨率时序支持不完整导致协商失败屏幕没有信号。这类问题的共性特征是系统核心功能正常只有某个外设不工作。这时候三板斧的使用重点不再是“能不能起来”而是“为什么这个设备没有起来”。日志里的-e过滤在这个阶段尤其好用可以把海量系统日志迅速收敛到指定模块。5.4 三板斧组合定位一个“随机重启”难题再分享一个更折腾的案例。某块板子在使用过程中随机重启重启间隔从几分钟到几小时不等没有任何业务征兆。这类问题是嵌入式开发里最磨人的一类因为它不规律、难复现。我的组合打法是这样先打开串口挂机记录让板子持续运行同时开启hilog持久化保证系统重启后崩溃现场能留在文件里hdc则定期从设备拉取日志快照做一些定时的节点信息采集。最终线索来自串口和内核日志的交叉比对——设备在重启前串口最后几行总会伴随着某个网卡驱动的错误信息而且时间点非常接近。进一步查发现是那颗网卡芯片在特定数据包压力下触发了一个内核race condition进而导致系统panic并自动重启。如果当时只盯着业务日志这个问题大概率是无解的状态因为业务层看到的只有“系统没了”。有了内核日志和串口的配合才能把崩溃前的真实现场还原出来。6. 三板斧之外几个容易让人怀疑人生的排查细节6.1 电源和复位是很多“系统问题”的真正源头在写代码的人的视角里系统崩了首先怀疑软件我可以理解。但我在这行做了十几年见过太多“软件问题”最终查到硬件头上。最典型的场景是板子跑一段时间后随机重启或者某个外设偶尔失灵。这种问题三板斧能帮你看现象但根因有可能在电源质量上。RK3568这种多核应用处理器对电源质量要求并不低如果供电电流余量不足或者电源纹波过大高负载场景下就容易异常。我在调试这类问题时习惯在电源入口放一个稳压源观察负载变化时的电流曲线同时用示波器盯关键电源轨的纹波。这和硬件调试三板斧是互补的软件三板斧负责定位“问题发生在哪个模块”示波器和万用表负责确认“是不是供电或信号质量的问题”。6.2 串口电平、日志缓冲这些细节决定成败有一些细节看着不起眼但每一个都可能让你在那排查两个小时串口电平不匹配不要拿5V的USB转串口模块直接怼3.3V的调试串口长期用可能烧引脚。日志缓冲太小hilog缓冲被大量日志塞满后旧日志会丢失很多关键信息可能在你打开日志之前就已经被冲掉了。串口线和USB转接芯片质量便宜的CH340模块在1500000波特率下可能不稳定有条件优先用质量可靠的FT232或CP2102系列。hdc和串口同时使用时的干扰某些情况下日志量特别大会抢占系统资源这时候可以先临时降级日志级别或者把日志转成文件输出。这些细节教科书上不会写但都是我一个个坑踩过来的。举个例子串口波特率1500000下劣质USB转串口线很容易出现偶发乱码一次两次你可能觉得是系统随机问题实际上就是电平驱动能力不够。换根线就好了。6.3 调试的心态和方法论记录、二分、交叉验证最后回到方法论上。三板斧是工具工具背后是一套思考方式。我总结下来系统调试的有效流程永远是三步记录现场。不管能不能立刻看懂先把串口日志、内核日志、hilog落盘。没有现场数据一切分析都是空谈。二分定位。先判断是硬件层、内核层、系统服务层、还是应用层的问题再逐层缩小范围。不要一开始就钻到某一段代码里。交叉验证。不要只信一个来源。串口说系统卡在内核驱动就用hdc看系统是否真的还在跑hilog说某个服务崩了就用dmesg看有没有对应的内核报错。我也越来越意识到硬件调试三板斧不仅仅适合OpenHarmony任何嵌入式Linux系统开发、甚至是单片机开发这套方法论都成立。区别只是具体命令和工具名不同但“通过串口抓早期、通过日志看内部、通过shell工具看运行态”的思路完全一致。最后分享一个小习惯我会在每块开发板上架调试环境时花十分钟把串口连接、hdc连接、日志落盘全部跑通并确认保存路径固定。这套准备工作看上去不起眼但在真正遇到难缠问题的时候它就是你和“崩溃现场”之间最短的距离。调试这件事功夫在事前三板斧如果只是等到出问题才想起来用效果会大打折扣。