简介:这份文档面向高通平台开发与调试工程师,尤其是刚接触高通芯片设备、需要快速上手常用工具的技术人员。内容围绕QPST、QRCT、QXDM与Trace32四款工具展开,覆盖从文件传输、EFS文件系统浏览、代码烧录,到射频配置测试、日志抓取分析,再到基于JTAG的内核级实时追踪与断点调试,帮助读者建立高通平台调试工具的整体认知框架。资源包内仅含1个docx文档,约45KB,以文字说明与操作要点整理为主,便于随身查阅和快速检索。目前已有158人学习下载,适合作为入门索引或日常调试时的速查参考。读者可从中了解QPST各组件(配置、服务编程、软件下载、RF NV项管理器、EFS浏览器)的职责划分,以及QRCT、QXDM、Trace32各自的适用场景,为后续深入阅读官方用户指南打下基础。
1. 高通平台常用调试Tool介绍:从死机日志到性能瓶颈,一套工具链怎么串起来
做嵌入式开发的朋友大概率遇到过这种场景:板子跑着跑着突然重启,串口只吐出一行乱码;或者功能都正常,但帧率就是上不去,CPU 占用率居高不下。这时候如果只会加 printf,效率会低到让人怀疑人生。高通平台(Qualcomm SoC)在移动端、车载、物联网设备里出货量巨大,围绕它其实有一整套成熟的调试工具链,覆盖从内核崩溃、内存泄漏、GPU 渲染到功耗分析的全链路。这篇笔记不讲空泛概念,而是按“先能抓到现场,再能定位根因,最后能验证修复”的顺序,把常用工具、参数配置和踩坑经验一次讲清楚。适合刚接手高通平台 BSP 或驱动调试的工程师,也适合想系统梳理调试手段的老手。
2. 抓现场:崩溃与日志类工具怎么用
调试的第一步永远是“拿到现场”。高通平台基于 Linux/Android,但它在标准内核之上加了不少自家机制,比如子系统重启(Subsystem Restart,SSR)、RAM dump 采集、以及 QXDM 这类底层诊断通道。如果只会看 logcat,很多问题根本抓不到。
2.1 用 RAM dump 抓内核崩溃现场
当设备发生内核 panic 或 watchdog 触发时,高通平台通常会把内存镜像保存到特定分区或通过 USB 导出。常见做法是使用ramdump工具配合 QPST 或开源脚本解析。下面是一个典型的采集与解析流程:
# 1. 设备进入 EDL 或 crash dump 模式后,确认 USB 设备被识别 lsusb | grep -i qualcomm # 2. 使用开源工具采集内存镜像(以某模拟项目为例) python3 collect_ramdump.py --port /dev/ttyUSB0 --output ./dump_20250101 # 3. 解析 dump 中的内核日志与调用栈 python3 parse_ramdump.py --dump ./dump_20250101 --symbols ./vmlinux --out ./crash_report.txt逻辑说明:第一步确认设备处于可采集状态,避免对着错误端口空跑。第二步的collect_ramdump.py是常见开源方案,参数--port指定串口或 USB 转串口设备,--output指定镜像存放目录。第三步解析时最关键的是--symbols,必须传入与当前运行内核完全匹配的vmlinux文件,否则调用栈全是地址,等于白抓。
参数说明:--port在不同平台上可能是/dev/ttyUSB0或/dev/ttyACM0,建议先用dmesg | tail确认枚举出的设备名。--symbols对应的 vmlinux 必须来自同一编译产物,版本号、编译时间、配置项都要一致,否则解析出的函数名会错位。
提示:RAM dump 文件动辄几个 GB,采集前先确认磁盘剩余空间,别抓到一半磁盘满了,现场就丢了。
2.2 用 QXDM 与 QCAT 看底层信令
QXDM 是高通平台常用的诊断日志工具,能抓到 modem、ADSP、CDSP 等子系统的详细日志。很多射频、通话、传感器问题在 Android 层看不到,但在 QXDM 里一目了然。使用流程通常是:设备端开启 diag 端口,PC 端 QXDM 连接后加载对应 filter 文件,抓取日志保存为.isf格式,再用 QCAT 打开分析。
常见配置项包括:
| 配置项 | 作用 | 常见取值 |
|---|---|---|
| Diag Port | 诊断端口 | /dev/diag或 USB 映射端口 |
| Filter File | 日志过滤规则 | 按子系统加载对应.xml |
| Log Mask | 日志掩码 | 按需勾选,全开会导致日志爆炸 |
| Save Format | 保存格式 | .isf便于 QCAT 解析 |
这里最容易翻车的是 Log Mask 全开。曾经有个项目,同事为了“抓全一点”,把所有 mask 都勾上,结果十分钟生成了 20GB 日志,设备直接卡死,问题没复现反而多了个新问题。正确做法是先明确怀疑方向,只开相关子系统的日志。
2.3 用 dmesg 与 ramoops 做轻量级现场保留
不是所有问题都值得上 RAM dump。对于偶发但不算致命的错误,ramoops是更轻量的选择。它把内核最后一段日志保存在保留内存里,重启后还能读出来。配置通常在设备树里完成:
reserved-memory { ramoops@ffc00000 { compatible = "ramoops"; reg = <0x0 0xffc00000 0x0 0x100000>; record-size = <0x20000>; console-size = <0x40000>; ftrace-size = <0x20000>; pmsg-size = <0x20000>; }; };逻辑说明:reg指定保留内存的起始地址和大小,record-size是每条崩溃记录的大小,console-size保存控制台日志,ftrace-size保存函数跟踪,pmsg-size保存用户空间写入的日志。配置好后,内核崩溃时自动写入,重启后通过/sys/fs/pstore/读取。
参数说明:保留内存地址不能和系统其他保留区域冲突,建议参考平台默认 dtsi 里的 ramoops 节点修改。record-size不宜过大,否则浪费内存;也不宜过小,否则关键栈信息被截断。一般 128KB 到 256KB 是常见范围。
3. 定位根因:性能与内存类工具怎么配
抓到现场只是第一步,真正难的是从一堆日志里找到“谁把系统搞挂了”。这一章讲性能剖析和内存泄漏定位,都是高通平台上验证过的组合拳。
3.1 用 Perfetto 与 systrace 抓性能瓶颈
Perfetto 是现在 Android 平台上的主力性能工具,取代了老的 systrace。它能同时抓取 CPU 调度、GPU 渲染、Binder 调用、频率电压等信息。高通平台对 Perfetto 有额外支持,比如可以抓取 GPU 频率和 DDR 带宽。
典型抓取命令:
# 在设备上启动 perfetto 抓取,持续 10 秒 adb shell perfetto -o /data/misc/perfetto-traces/trace.pftrace -t 10s \ -c /system/etc/perfetto/default.cfg # 拉取到本地并用 UI 打开 adb pull /data/misc/perfetto-traces/trace.pftrace .逻辑说明:-o指定输出文件,-t指定抓取时长,-c指定配置文件。配置文件决定了抓哪些 category,比如sched、freq、gpu、binder等。抓完后用 Perfetto UI 打开,能看到时间轴上各个 CPU 核心的调度情况和频率变化。
参数说明:-t 10s是常用时长,太长会导致文件过大且难以分析。配置文件建议基于default.cfg修改,只增加需要的 category。如果怀疑 GPU 问题,务必加上gpu和gpu_mem相关 category;如果怀疑调度问题,加上sched和freq。
注意:Perfetto 抓取本身有开销,长时间抓取会影响性能数据。建议先短时间抓取定位大致方向,再针对性延长。
3.2 用 kmemleak 与 slabinfo 定位内核内存泄漏
内核内存泄漏是嵌入式设备的老大难问题,表现为可用内存越来越少,最终 OOM。高通平台内核通常已经使能了kmemleak,只需要在启动参数里打开。
配置方式:
# 在内核命令行加入 kmemleak=on # 启动后手动触发扫描 echo scan > /sys/kernel/debug/kmemleak # 查看疑似泄漏点 cat /sys/kernel/debug/kmemleak逻辑说明:kmemleak=on开启内核内存泄漏检测,它通过跟踪内存分配和释放来发现“分配了但没释放”的块。echo scan触发一次全量扫描,扫描结果会列出疑似泄漏的调用栈。
参数说明:kmemleak对性能有影响,量产版本一般不开,只在调试版本使用。扫描间隔可以通过echo scan=10 > /sys/kernel/debug/kmemleak设置自动扫描,但更推荐手动触发,避免干扰性能测试。
配合slabinfo可以看具体 slab 缓存的变化:
# 连续观察某几个 slab 的增长 while true; do grep -E "kmalloc-|dma-|bio-" /proc/slabinfo >> slab_log.txt sleep 5 done逻辑说明:/proc/slabinfo列出所有 slab 缓存的当前对象数和总对象数。如果某个缓存的 active 对象数持续增长且不回落,基本可以锁定泄漏方向。
参数说明:grep过滤出常见的内核对象缓存,避免日志过大。sleep 5是采样间隔,太短会刷屏,太长可能错过突增点。
3.3 用 simpleperf 做用户态热点分析
用户态 CPU 占用高,但不知道具体在哪个函数,simpleperf是最顺手的工具。它基于 perf 事件,能采样用户态和内核态的调用栈。
# 在设备上采样 10 秒,记录调用栈 adb shell simpleperf record -p $(pidof com.example.app) -g -o /data/local/tmp/perf.data --duration 10 # 生成报告 adb shell simpleperf report -i /data/local/tmp/perf.data --sort dso,symbol逻辑说明:-p指定进程号,-g表示记录调用栈,--duration指定采样时长。报告里按动态库和符号排序,能直接看到哪个函数占用最高。
参数说明:--sort dso,symbol是最常用的排序方式,先按动态库再按符号。如果怀疑是内核态问题,可以去掉-p改为全系统采样,但数据量会大很多。
4. 避坑与常见问题:那些让人熬夜的调试翻车现场
这一章记录几个高频踩坑点,每个都按“现象 → 原因 → 解决”写清楚,希望能帮你少走弯路。
4.1 现象:RAM dump 解析出来全是问号
原因:vmlinux 与设备运行的内核不匹配。常见情况是编译了多个版本,拿错了文件;或者设备已经 OTA 升级,但本地还是旧符号表。
解决:解析前先确认设备内核版本,用adb shell cat /proc/version或从 dump 里提取版本字符串,然后找到完全对应的 vmlinux。如果找不到,只能重新编译同版本内核。
4.2 现象:Perfetto 抓取后看不到 GPU 频率
原因:配置文件里没有使能 GPU 相关的 category,或者平台没有导出 GPU 频率节点。
解决:检查配置文件是否包含gpu和freq相关 category。如果仍然没有,确认内核是否使能了 GPU 频率导出,部分平台需要额外打补丁。
4.3 现象:kmemleak 扫描后系统变慢甚至卡死
原因:kmemleak 全量扫描会遍历所有内存对象,内存越大耗时越长,期间可能持有锁导致卡顿。
解决:只在调试版本开启,且避免在性能测试时扫描。如果必须扫描,选择系统空闲时手动触发,不要设置自动扫描。
4.4 现象:QXDM 抓到的日志在 QCAT 里打不开
原因:日志保存格式不对,或者 QCAT 版本与 QXDM 不匹配。
解决:保存时选择.isf格式,这是 QCAT 原生支持的格式。如果仍然打不开,检查 QCAT 版本是否与 QXDM 配套,版本差异过大可能导致解析失败。
4.5 现象:simpleperf 报告里符号全是地址
原因:没有指定符号表路径,或者被测进程的符号被 strip 了。
解决:用--symfs指定符号表根目录,确保包含带符号的库文件。如果是自己编译的模块,保留一份未 strip 的版本专门用于分析。
5. 进阶技巧:把工具串成自动化流水线
单次调试靠手动操作没问题,但如果要反复验证修复效果,手动就太慢了。我一般会把常用工具串成脚本,一键完成“抓取 → 解析 → 生成报告”的流程。下面是一个简化示例,展示如何把 RAM dump 采集和解析自动化:
#!/bin/bash # auto_debug.sh - 自动采集并解析 RAM dump set -e DUMP_DIR="./dump_$(date +%Y%m%d_%H%M%S)" VMLINUX="./symbols/vmlinux" PORT="/dev/ttyUSB0" mkdir -p "$DUMP_DIR" echo "[1/3] 采集 RAM dump..." python3 collect_ramdump.py --port "$PORT" --output "$DUMP_DIR" echo "[2/3] 解析 dump..." python3 parse_ramdump.py --dump "$DUMP_DIR" --symbols "$VMLINUX" --out "$DUMP_DIR/report.txt" echo "[3/3] 提取关键信息..." grep -E "Call trace|PC is at|BUG:|Unable to handle" "$DUMP_DIR/report.txt" > "$DUMP_DIR/key_findings.txt" echo "完成,关键信息见 $DUMP_DIR/key_findings.txt"逻辑说明:脚本先创建带时间戳的目录,避免覆盖历史数据。然后依次执行采集、解析、关键信息提取。最后一步用grep过滤出崩溃报告里最关键的几类信息,省去人工翻大文件的时间。
参数说明:VMLINUX必须指向与设备当前内核完全匹配的符号文件,建议在脚本里加一个校验步骤,比如比对版本字符串。PORT根据实际枚举结果修改,可以做成自动探测。
除了 RAM dump,Perfetto 和 simpleperf 也可以类似自动化。比如写一个脚本,先抓 Perfetto,再用trace_processor生成 CPU 占用统计,最后和基线对比。这样每次修复后跑一遍,就能快速判断问题是否真的解决。
还有一个容易被忽略的技巧:把调试工具的版本也纳入管理。不同版本的 QXDM、Perfetto、simpleperf 对同一份数据的解析结果可能有差异,建议在项目里固定一套工具版本,避免“上次能解析这次不行”的玄学问题。
最后说个血泪教训:调试工具再强,也替代不了对系统架构的理解。我曾经花了两天追一个内存泄漏,最后发现是某个驱动在 probe 失败时没有释放已经申请的资源。工具帮我定位到了泄漏点,但真正理解“为什么这里会漏”还是得靠读代码和熟悉驱动模型。工具是放大镜,不是替代品。希望这些经验能帮到你,少熬几个夜。
本文还有配套的精品资源,点击获取