资讯动态

OpenHarmony硬件调试三板斧:串口、设备树与寄存器实战

发布时间:2026/9/6 10:14:59 来源:尧图企业网站定制
1. 三板斧为什么是串口、设备树和命令行交互先交代一下背景。我接触开源鸿蒙OpenHarmony是从一块RK3568开发板开始的板子拿到手第一个感觉是系统不再是压缩包里一个固件那么简单的单片机玩法它是一个完整的多进程操作系统。你面对的不再是为什么程序没跑起来而是内核起来了没有、用户态哪个服务挂了、硬件有没有被系统里的某个驱动偷走。这种时候如果没有一套高效的硬件调试手段光靠看代码看一天也看不出个所以然。我在社区里看到不少初学者问RK3568到底该选哪个设备树电脑版x86 OpenHarmony怎么调试板子串口完全没有输出怎么办这些问题其实都可以被同一套调试方法论覆盖。我习惯把它叫做硬件调试三板斧第一斧串口日志。判断系统活没活、活到了哪一步、死在哪个模块。第二斧设备树。操作系统怎么看待这块板子上的硬件资源选错dts一切白搭。第三斧Shell交互与寄存器读取。系统已经跑起来之后直接在运行态摸硬件、改状态、验证猜想。为什么偏偏是这三样而不是JTAG、示波器、逻辑分析仪因为对绝大多数做OpenHarmony系统适配和业务开发的人来说你首先要解决的是系统级软硬件协同问题而不是单纯的硬件电气问题。串口、设备树、命令行交互是成本最低、见效最快、覆盖场景最广的组合。示波器和逻辑分析仪当然重要但那是黑客级硬件问题才需要的武器日常90%的外设不通、引脚被占用、驱动没加载三板斧就能定位到根因。这套方法不仅适用于RK3568也适用于Hi3516、RK3399以及QEMU模拟器甚至x86平台。把这三板斧练熟之后你会发现OpenHarmony的调试思路和Linux内核开发非常接近很多经验是可以平移的。2. 第一板斧串口日志系统状态的生命体征2.1 接线和波特率90%的人卡在第一步OpenHarmony开发板的调试串口在硬件上通常就是一组UART引脚三个关键信号GND、TX、RX。接线时有一个最容易犯的错就是板子的TX要接USB转串口模块的RX板子的RX接模块的TX也就是交叉连接。GND必须共地否则逻辑电平参考点不一致收到的全是乱码。波特率方面RK3568平台默认调试串口波特率一般是115200部分厂商的定制板可能改成921600或1500000具体以板卡硬件手册为准。如果串口工具里看到一堆乱码而你又确认接线没问题大概率就是波特率设错了。另外要养成好习惯插上USB转串口后先在设备管理器或Linux的/dev/ttyUSB0确认设备节点存在再打开串口工具避免工具打开串口失败的尴尬。我用的是MobaXterm自带的串口会话和minicom两个工具Windows下也可以用PuTTY。基本配置就是# Linux下用minicom minicom -D /dev/ttyUSB0 -b 115200 # Windows下PuTTY # Session - Serial - Line: COM3, Speed: 1152002.2 日志分三段看U-Boot、Kernel、Hilog串口连上之后按下板子的电源键或复位键会看到一大段输出。很多人面对滚动日志一脸懵其实可以按阶段拆开看U-Boot阶段从开机到内核解压之前。这里能看到DDR初始化信息、设备树加载、启动介质识别。如果RK3568板子在U-Boot阶段就卡住多半是DDR配置不对或固件选错。Kernel阶段从Starting kernel到init进程启动。在这里能看到设备树里各节点是否成功注册驱动是否probe哪个外设初始化失败。Hilog阶段用户态服务的日志OpenHarmony的分布式软总线、元能力、HDF驱动框架的日志都走hilog。每个阶段对应不同的问题域。比如你发现触摸屏没反应但当串口还在正常输出开机日志、系统能进桌面那问题大概率不在内核而在HDF驱动或用户态服务。反过来如果串口log停在Starting kernel ...之后的某一行比如某个GPIO相关的驱动panic那就要回到内核驱动和设备树去找原因。看Kernel日志时我习惯先在串口工具里把全部日志保存成文件再搜索关键字。串口滚屏速度非常快肉眼根本追不上保存文件才是正经做法。在MobaXterm里可以直接右键复制minicom可以用minicom -C log.txt将日志写入文件。Hilog的命令行用法也值得单独说。进入系统Shell后# 查看所有日志 hilog # 按关键字过滤 hilog | grep -i hdf # 按等级过滤 hilog -L D # 只看DEBUG以上的日志2.3 串口完全无输出的定位思路这是最让人头皮发麻的情况板子上电串口工具一个字符都没有。我的排查顺序是看板子电源指示灯是否点亮电流表是否有电流跳动。没电流说明根本没上电或核心板没启动。检查USB转串口模块有没有被系统识别Linux下ls /dev/ttyUSB*Windows下看设备管理器是否出现COM口。检查线序是否接反。串口线是最容易接反的板子上的丝印有时还会标错。换一个波特率试。有些板子的BootROM阶段用高波特率后面才切到115200。如果始终无输出用一根杜邦线把板子的TX和RX短接然后在串口工具里发送字符看能不能回显。能回显说明UART外设本身是通的问题在板子的发送端没起来。最后一步检查启动介质。RK3568如果boot引脚拨到了无系统介质启动就可能完全没有日志输出需要用RKDevTool重新烧录。串口调试的经验之谈一定要养成第一时间保存完整启动日志的习惯。很多问题是在你反复改代码之后才暴露的回头翻旧日志对比上一次好的时候是什么输出往往能快速定位。3. 第二板斧读懂设备树RK3568那么多dts到底怎么选3.1 为什么RK3568有一堆设备树文件在OpenHarmony的Linux内核源码路径下RK3568的设备树文件通常位于kernel/linux/linux-5.10/arch/arm64/boot/dts/rockchip/如果你进入这个目录会看到几十个以rk3568开头的dts文件rk3568-evb1-ddr4-v10.dts、rk3568-evb2-lpddr4-v10.dts、rk3568-evb4-lpddr3-v10.dts……第一次看到这些文件不懵才怪。这个多是有原因的同一颗SoC下游板卡厂商可以自由选择DDR类型、不同型号的屏幕、不同规格的摄像头模组和扩展接口这些差异最终都要体现在设备树里。而Rockchip官方为了让一套内核支持尽可能多的评估板给每块评估板都建了一份dts。选错的后果很直接系统可能能启动但DDR容量识别不对、屏幕点不亮、某个GPIO控制的电源一直不输出。更隐蔽的是选错dts后某些节点地址冲突驱动的probe像抽风一样有时成功有时失败。3.2 选择设备树的正确姿势我的经验是选dts不要看文件名猜而是从三个维度去对齐第一看板卡的硬件版本和DDR类型。这是最硬性的区分条件。板卡手册或板卡丝印上通常会标注DDR4还是LPDDR4、LPDDR3。例如rk3568-evb1-ddr4-v10.dtsEVB1底板DDR4rk3568-evb2-lpddr4-v10.dtsEVB2底板LPDDR4rk3568-evb4-lpddr3-v10.dtsEVB4底板LPDDR3如果是第三方核心板厂商一般会在文档里直接声明用了哪个dts作为基线。比如很多开发板说明里会写本板基于rk3568-evb2-lpddr4-v10.dts修改。第二看编译产物。如果板子之前烧过系统且能启动进入Shell后执行以下命令可以直接看到当前实际加载的设备树兼容字符串cat /proc/device-tree/compatible比如输出中带有rockchip,rk3568-evb2-lpddr4-v10-board之类的字符串那当前用的就是该dts。如果你能用网络或ADB连上正在运行的板子这是最准确的办法不需要猜。第三看productdefine和vendor配置。OpenHarmony的编译过程并不是直接去dts目录翻牌子而是通过vendor下的产品配置来指定。以RK3568的dayu200为例配置文件里会有一段类似dts: rk3568-dayu200-lpddr4.dts或在内核编译脚本中通过CONFIG_DTC、CONFIG_ARM64_DTS指定。你修改好dts后编译内核时会生成对应的dtb文件路径通常在out/kernel/ARCH_ARM64/linux-5.10/arch/arm64/boot/dts/rockchip/rk3568-xxx.dtb这个dtb会被打包进resource.img或boot.img。烧录时要确认烧对了分区。3.3 改设备树最常见的三个坑第一坑只改了dts但没重新编译内核资源烧录的仍是旧dtb。这是新手最容易遇到的问题。改dts后必须重新生成dtb再打资源包再烧录resource或boot分区。OpenHarmony的编译命令大致是./build.sh --product-name rk3568 --build-target kernel之后在内核输出目录里找到新dtb。第二坑pinctrl引脚复用冲突。dts里配置了一个UART同时又配置某个GPIO用同一个引脚就会导致功能错乱。比如你把UART2的TX/RX引脚复用成了GPIO系统起来后串口可能就哑了。排查方式我在第四板斧里详说用debugfs查看pinmux实际状态。第三坑status属性。很多节点默认status disabled如果你的板子需要这个外设但没改状态驱动完全不会加载。修改时记得把disabled改成okay。这部分的经验总结一句话设备树不是写出来就完了它是一个运行时的硬件视图你一定要在系统起来后去验证当前生效的dtb确实包含你改的节点。验证方法很简单cat /proc/device-tree/soc/uart2/status输出okay才是真的生效。4. 第三板斧Shell与寄存器交互直接在运行态摸硬件4.1 用hdc进入开发板命令行OpenHarmony的调试通道是hdc类似Android的adb。开发板开机后用USB线连接PC和开发板终端里执行hdc list targets能看到设备序列号就说明通道建立成功。接着hdc shell就进入了开发板的Shell。这个Shell是OpenHarmony自己的命令集和Linux略有差别但cat、ls、echo、mount这些基础命令都能用。如果没有hdc环境也可以通过串口进入Shell效果一样。进入Shell之后三板斧的第三斧才算真正抡起来你不是只看看日志你可以在系统运行状态下去检查硬件状态、读取寄存器、手动导出节点。4.2 内存寄存器直接读写的两个工具调试硬件最爽的事情莫过于直接读寄存器看硬件当前状态。OpenHarmony系统里常用的两个工具是io和devmem。io命令是OpenHarmony自带的寄存器读写工具用法示例# 读32位寄存器 io -r -32 0xfe2c0000 # 写32位寄存器 io -w -32 0xfe2c0000 0x00000001devmem也是直接访问物理地址的经典工具# 读物理地址0xfe2c0000处的4字节 devmem 0xfe2c0000 32 # 写 devmem 0xfe2c0000 32 0x00000001这两个工具本质相同都是把物理地址映射到用户空间去读写。注意寄存器地址是物理地址不能拿虚拟地址去套否则轻则读到无意义数据重则直接segment fault。我经常用这套命令来验证某个外设是否被正确初始化。比如怀疑GPIO没有输出高电平就找到对应的GPIO控制器的寄存器基地址读取数据寄存器核对bit值是否符合预期。这种方法比单纯看代码可靠得多因为寄存器反映的是硬件真实状态。4.3 引脚复用状态怎么看RK3568的引脚复用或者说pinmux是调试外设时最绕不开的一环。运行系统后进入Shell可以通过debugfs查看当前的引脚复用状态# 如果debugfs没挂载先挂载 mount -t debugfs none /sys/kernel/debug # 查看pinctrl信息 cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins输出会列出每个引脚的当前功能。比如某个引脚本应配置为I2C的SCL但pinmux里显示的却是GPIO那就说明有东西抢占了引脚或者dts配置没生效。同样地GPIO的状态可以从这里看cat /sys/kernel/debug/gpio它会列出所有GPIO控制器下每个引脚的输入输出方向、当前电平、占用者。有一次我调试一个红外发射管代码里明明调用了GPIO写高电平但实测始终是低。用cat /sys/kernel/debug/gpio一看引脚被另一个驱动request掉了方向上显示输入我当然写不进去。顺着这个线索去查dts发现两个外设节点配置了同一组引脚。4.4 中断、时钟和资源占用检查如果外设不工作还要检查中断和时钟是否就绪。常用命令# 查看中断占用和触发次数 cat /proc/interrupts # 查看物理内存映射 cat /proc/iomem # 查看内核模块 ls /sys/module/proc/interrupts非常有用你的驱动注册了中断后如果中断号在列表里没有出现或者中断计数不增长说明中断根本没有触发问题在硬件信号链而不是软件逻辑。/proc/iomem则可以看到各个外设的物理地址区间被谁占用如果两个驱动申请了重叠的地址区域后面加载的那个通常probe失败并报resource busy。第三板斧的本质是一种逆向验证。日志和设备树告诉你系统应该怎么看硬件而寄存器、pinmux、interrupts告诉你硬件实际在怎么工作。两者对上软件逻辑基本稳了两者对不上bug就在这里。5. 综合实战从点灯不亮到定位引脚被复用完整排查过程把三板斧串起来看一个真实案例。有一次我在RK3568开发板上调试一个外接的LED指示灯驱动逻辑很简单注册GPIO、写高电平点亮。代码编译烧录后LED却纹丝不动。我当时的排查链路是这样走的第一步看串口日志。启动日志中有没有对应驱动的probe成功信息我执行hilog | grep -i my_led发现驱动确实加载了probe返回成功没有任何error。于是排除了驱动没加载这个层次问题缩小到引脚物理状态不对。第二步查设备树。确认我使用的GPIO编号在dts里对应的引脚。打开dtsgpio4 { ... }中我配置的是GPIO4_C2这个引脚。这里要算一下对应的GPIO全局编号RK3568的GPIO分为GPIO0到GPIO4每组32个引脚GPIO4_C2就是4×32 2×8 2 146。我记住这个编号备用。第三步进入Shell用debugfs看实际状态。执行hdc shell mount -t debugfs none /sys/kernel/debug cat /sys/kernel/debug/gpio在输出里搜索146结果发现这个引脚确实被标记为输出但current value是low。更诡异的是占用者那一栏显示的是AnotherDriver并不是我的LED驱动名。这就解释了一切我的驱动probe成功只是因为它拿到了dts节点但在request gpio时可能被内核的GPIO子系统分配了其他引脚或者引脚已被别的驱动抢先request。第四步带着疑问回到dts。我搜了一下pinctrl相关配置果然发现另一个外设节点把GPIO4_C2所在的引脚组声明为了某个特殊功能比如I2S的数据引脚。dts里的pinctrl优先级比我的GPIO配置更高内核在初始化时先把引脚复用成了I2S功能我的GPIO请求自然失败。第五步修改dts把这个存在冲突的外设节点里对应的pinctrl配置去掉或把LED换到另一个没被占用的引脚重新编译内核烧录resource分区。再次上电LED亮了。这个案例几乎每个步骤都在三板斧之内串口日志定位驱动加载状态设备树定位配置源头Shell和debugfs定位运行时的真实硬件状态。没有一步用到了示波器所有根因都能在软件层面看到。还有一个典型的串口完全无输出排查案例。某块核心板在烧录官方固件后串口无输出我第一反应不是怀疑硬件而是怀疑烧录的boot镜像里U-Boot的调试串口配置不对。后来查了一下开发板的官方文档发现它的调试串口默认用的是UART2但有一批板子在硬件改版时把调试串口移到了UART3。我修改U-Boot的dts配置后重新烧录日志立刻出来了。这种问题如果不了解dts和串口映射很容易误判为板子坏了。6. x86版的OpenHarmony调试以及三板斧如何平移很多人在没有实体开发板的情况下想在电脑上先跑一跑OpenHarmony。这里要考虑电脑版x86 OpenHarmony这个方向。OpenHarmony官方有x86_64的镜像可以用来在QEMU或真实PC上启动系统。它的调试思路与RK3568开发板并没有本质区别只是串口和Shell入口略有不同。在QEMU里跑x86镜像时串口通常被重定向到stdio或socket你依然可以在宿主机上看到内核日志。进入系统后同样可以用hdc连上去做Shell交互。设备树方面x86平台主要用的是ACPI和DTS混合的方式不像ARM板卡那样直接改dts那么频繁。但第三板斧里的Shell寄存器操作在x86上依然可用只是寄存器地址变成了x86的IO地址空间或MMIO地址devmem依然能读。我的建议是如果纯粹熟悉OpenHarmony的分布式能力和HDF驱动框架x86镜像QEMU完全够用成本为零但如果你要深挖硬件适配还是要有一块真实的RK3568板子因为DDR训练、电源时序、引脚复用这些只有真板子才暴露得出来。实际操作中我维护着一个小本子记录每个板子对应的dts、串口波特率、烧录分区表和三板斧常用命令每次换新板子先把这些信息补齐。这套准备工作比任何调试技巧都节省时间。最后再分享一个日志过滤的小技巧系统日志量大的时候可以先调整hilog的日志级别减少干扰项hilog -G off -g tag:my_driver或者直接用grep把关键信息摘出来。很多外设问题在日志里其实只体现为一两行warning或error但它们常常混在几千行日志里被忽略。带grep的过滤习惯应该成为调试的肌肉记忆。三板斧练熟之后面对一块未知的OpenHarmony板子你不会再胆小。串口、设备树、Shell和寄存器把这三斧头抡好大部分硬件适配问题都能在自己手里终结。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价