2. 必备调试环境搭建:ADB与Kernel Log配置、Trace32/Lauterbach连接脚本、QACT与Chimera工具安装、MMCAMERA与CHI架构的编译选项
调试环境,说白了就是你跟硬件对话的「翻译官」。环境没搭好,后面所有分析都是空中楼阁。我见过太多工程师花几周追一个bug,最后发现是log没开全——这种冤枉路,咱们不走。
这一章,我把Camera调试最核心的几块环境拆开讲。每块我都会告诉你:为什么要配、怎么配、配完怎么验证。
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权限,适合持续监控 |
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
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
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的执行时间
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
make clean再重新编译。增量编译有时不会重新生成依赖文件,导致你改了选项但实际没生效。我吃过这个亏——调了两天的pipeline问题,最后发现是增量编译没把新选项编进去。
2.5 本章知识体系总览
下面这张图把本章涉及的调试环境组件和它们之间的关系画了出来。你可以把它当作一张「调试地图」——遇到问题时,先看问题出在哪个层面,再选择对应的工具。
tools/debug_env/目录下,换项目直接跑。这样既省时间,又不会漏步骤。