2. 必备调试环境搭建:ADB与Kernel Log配置、Trace32/Lauterbach连接脚本、QACT与Chimera工具安装、MMCAMERA与CHI架构的编译选项

调试环境,说白了就是你跟硬件对话的「翻译官」。环境没搭好,后面所有分析都是空中楼阁。我见过太多工程师花几周追一个bug,最后发现是log没开全——这种冤枉路,咱们不走。

这一章,我把Camera调试最核心的几块环境拆开讲。每块我都会告诉你:为什么要配、怎么配、配完怎么验证。

核心观点:调试环境不是一次性工作。每换一个平台、每升一次基线,都要重新检查一遍。我习惯把环境搭建脚本化,放到Git里管理,换项目直接跑脚本。

2.1 ADB与Kernel Log配置

ADB是Android调试的基石。但很多人只停留在adb logcat,忽略了Kernel侧的信息。Camera的很多硬伤——比如IRQ丢失、i2c传输超时、电源域没上电——都只会在Kernel log里暴露。

2.1.1 ADB基础配置

  • 多设备管理:用adb devices列出所有设备,然后用adb -s <serial>指定目标。我习惯在.bashrc里写个alias:alias adbc='adb -s $(adb devices | grep "device$" | head -1 | cut -f1)'
  • 权限问题:如果adb devices显示unauthorized,检查USB调试授权弹窗。有些设备需要先adb kill-server再adb start-server。
  • 无线ADB:调试Camera模组时,有线连接经常因为机械结构受限。我推荐用adb tcpip 5555切到无线模式,然后adb connect <IP>。注意:无线ADB在大量log输出时可能丢包,关键抓log阶段还是用有线。

2.1.2 Kernel Log的「三板斧」

Kernel log有三个来源,各有各的用途:

命令 数据源 典型场景
dmesg Kernel ring buffer 驱动加载、中断、DMA、电源管理
logcat -b kernel Kernel log buffer (Android) 与HAL层时间戳对齐的场景
cat /proc/kmsg 实时Kernel消息 需要root权限,适合持续监控
我的习惯:抓Camera问题log时,我会同时开三个终端:一个跑dmesg -w,一个跑logcat -b all,一个跑抓图脚本。这样Kernel、HAL、应用层的时间线能完全对齐。

2.1.3 动态调试等级调整

默认的Kernel log等级往往不够细。Camera驱动里很多关键路径——比如ISP pipeline的每个stage切换——都是dev_dbg级别的,默认不输出。

# 查看当前log等级
cat /proc/sys/kernel/printk
# 输出示例:7 4 1 7
# 第一个数字是当前console log等级,7表示所有级别都输出

# 临时调高(重启后失效)
echo "8 4 1 8" > /proc/sys/kernel/printk

# 动态打开某个驱动的debug
echo "file cam_sensor.c +p" > /sys/kernel/debug/dynamic_debug/control
echo "module msm_camera +p" > /sys/kernel/debug/dynamic_debug/control
注意:动态debug控制依赖内核配置CONFIG_DYNAMIC_DEBUG。如果/sys/kernel/debug不存在,先执行mount -t debugfs none /sys/kernel/debug。我曾经在一个客户项目上折腾了半天,最后发现他们的内核根本没开这个配置——白费功夫。

2.2 Trace32/Lauterbach连接脚本

当系统完全卡死、ADB连不上、logcat不输出的时候,Trace32或Lauterbach是你最后的救命稻草。它能让你直接看CPU的PC指针、寄存器状态、内存内容——说白了,就是「开颅手术」级别的调试。

2.2.1 连接脚本的核心结构

一个标准的Lauterbach连接脚本(.cmm文件)包含以下部分:

; 1. 初始化调试器接口
SYStem.CONFIG.INTERFACE JTAG
SYStem.CONFIG.CPU SDM845
SYStem.CONFIG.FREQuency 100MHz

; 2. 连接目标
SYStem.UP
WAIT 500ms

; 3. 初始化MMU和缓存
SYStem.Option.MMU ON
SYStem.Option.CACHE ON

; 4. 加载符号表
Data.LOAD.Elf "path/to/vmlinux" /NoCODE
Data.LOAD.Elf "path/to/camera.ko" /NoCODE

; 5. 设置断点
Break.Set 0xFFFFFF800A1B2C3C /Program

; 6. 启动目标
GO
避坑指南:我曾经在调试一个Camera驱动死锁问题时,发现Trace32连上后CPU停在WFI指令上,但所有核的PC指针都指向同一个spin_lock函数——这就是典型的死锁特征。如果没有Trace32,光靠log根本看不出这个模式。

2.2.2 常用调试命令速查

命令 作用 Camera调试场景
Register.view 查看寄存器 检查CSID、CSIPHY寄存器值
Data.dump 内存转储 查看ISP output buffer内容
Break.Set 设置断点 在cam_irq_handler处下断
Trace.Extend 指令追踪 分析中断响应延迟

2.3 QACT与Chimera工具安装

这两个工具是Qualcomm Camera调试的「左右手」。QACT负责tuning参数调整,Chimera负责pipeline可视化。

2.3.1 QACT安装要点

  • 版本匹配:QACT的版本必须与目标平台的CAMSS驱动版本对应。我见过有人用QACT 8.x去调SM8450平台,结果所有寄存器地址都偏移了——调了一周才发现是工具版本不对。
  • License配置:QACT需要license文件。把license.lic放到$QACT_INSTALL_DIR/license下,然后设置环境变量LM_LICENSE_FILE。
  • XML描述文件:每个sensor都需要一个XML文件描述其寄存器映射。这个文件通常由sensor vendor提供,但经常有错误。我习惯拿到XML后先用QACT的「Validate」功能跑一遍。

2.3.2 Chimera的pipeline可视化

Chimera能把你代码里定义的pipeline拓扑画成图形。这对理解复杂的CHI pipeline特别有用。

# 启动Chimera
cd $CHIMERA_HOME
./chimera -platform offscreen  # 无头模式,适合远程调试

# 加载pipeline描述文件
File -> Open -> select_pipeline.xml

# 常用操作
- 双击node查看其属性(session ID、link handle)
- 右键连接线查看带宽占用
- 使用「Timeline」视图看每个stage的执行时间
个人经验:有一次客户反馈预览画面有周期性抖动。我用Chimera打开pipeline图,发现IFE和IPE之间有一条多余的buffer link——这条link在代码里是条件编译的,但客户打开了那个宏。Chimera的图形化展示让我5分钟定位到了问题,而之前代码review了两轮都没发现。

2.4 MMCAMERA与CHI架构的编译选项

编译选项决定了你的Camera HAL层会包含哪些功能模块。配错了,要么功能缺失,要么性能下降。

2.4.1 MMCAMERA关键编译开关

宏定义 作用 调试建议
MM_CAMERA_FEATURE_DSDN 双摄降噪 调试双摄时打开,单摄时关闭以减小log
MM_CAMERA_FEATURE_HFR 高帧率模式 调试慢动作视频时必开
MM_CAMERA_FEATURE_STREAMING 流式处理 默认打开,关闭后走legacy路径
ENABLE_PERF_LOG 性能log 调试帧率问题时打开,会输出每个stage耗时

2.4.2 CHI架构的编译配置

CHI架构的编译选项在chi-cdk/build目录下的chi_build_config.h中定义:

// 打开CHI的详细log
#define CHI_DEBUG_ENABLE 1

// 打开pipeline验证(推荐调试阶段打开)
#define CHI_PIPELINE_VALIDATION 1

// 打开buffer统计
#define CHI_BUFFER_STATS 1

// 关闭Usecase优化(调试时关闭,避免优化掩盖问题)
// #define CHI_USECASE_OPTIMIZATION 1
重要:CHI架构的编译选项改动后,必须make clean再重新编译。增量编译有时不会重新生成依赖文件,导致你改了选项但实际没生效。我吃过这个亏——调了两天的pipeline问题,最后发现是增量编译没把新选项编进去。

2.5 本章知识体系总览

下面这张图把本章涉及的调试环境组件和它们之间的关系画了出来。你可以把它当作一张「调试地图」——遇到问题时,先看问题出在哪个层面,再选择对应的工具。

Camera调试环境知识体系 问题现象:卡死 / 花屏 / 丢帧 / 性能差 调试手段选择(根据问题严重程度) ADB + Kernel Log 适用:系统未完全卡死 dmesg / logcat / dynamic debug 抓取HAL + Kernel时间线 Trace32 / Lauterbach 适用:系统完全卡死 JTAG连接 / 寄存器查看 断点 / 指令追踪 QACT + Chimera 适用:tuning / pipeline问题 QACT:tuning参数调整 Chimera:pipeline可视化 底层支撑:MMCAMERA / CHI 编译选项配置 核心原则 环境搭建脚本化 → 版本管理 → 换平台/升基线后重新验证
最后说一句:调试环境不是配完就完事的。每次换平台、每次升基线,都要重新验证一遍。我习惯把环境搭建写成shell脚本,放到项目的tools/debug_env/目录下,换项目直接跑。这样既省时间,又不会漏步骤。