ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

高通平台Camera驱动调试实战:从设备树到MIPI链路

高通平台Camera驱动调试实战:从设备树到MIPI链路 1. 上手前的架构地图Camera驱动到底管到哪一层说句实话很多刚接触高通平台的兄弟拿到工程机第一反应就是“Camera不行”然后一头扎进kernel log里翻。翻了半天要么是一堆看不懂的CamX/CamRTS报错要么是sensor ID读失败这种语焉不详的提示最后只能四处求人。我一直认为调试之前必须先搞清楚自己站在哪一层否则所有的排查动作都是在撞运气。高通平台的Camera软件栈从顶层到底层大概可以切成四层第一层是APP和framework也就是Android的Camera API和CameraService第二层是HAL层高通这边叫CamX加上一个可选的CHICamera Hardware Interface扩展层很多模组厂商的量产客制化逻辑都挂在CHI里面第三层是kernel驱动对应到msm-camera这个驱动家族里面细分为sensor、cci、csid、csiphy、isp、cpas、smmu、sync等一堆子模块第四层是硬件本身包括sensor、马达、闪光灯、镜头模组以及SoC内部的ISP、IFE、JPEG、ICP这些图像处理单元。对做驱动的人来说接触最多的是第三层和第四层之间的交互。高通在kernel侧提供了完整的Camera驱动框架路径一般在kernel/msm-*/drivers/media/platform/msm/camera/不同内核版本目录结构略有差异但核心模块基本没变。比如sensor目录管sensor的探测和电源序列cci目录管CCI总线的I2C通信csiphy和csid管MIPI物理层和协议层isp管IFE的流水线配置cpas管整个Camera系统的时钟和电源域分配。调试之前还有个关键动作确认自己用的是哪个platform。高通的平台代号和商业化命名对不上是常态比如SM8550在CAFCode Aurora Forum里的代号是kalamaSM8450是lahainaSM8250是kona。很多驱动代码路径、设备树节点名、寄存器map都跟平台代号强相关。你拿着kona的代码去改kalama的寄存器配置大概率是找不到对应寄存器甚至编译直接报错的。所以上手第一件事就是确认/proc/device-tree/model或者内核version string里的平台信息知道自己到底在哪个平台上干活。驱动开发者的工作边界也值得说清楚驱动层不负责图像效果只负责把图像数据正确、及时、稳定地送到ISP或者内存里。白平衡、降噪、HDR这些是效果工程师在CamX的tuning里干的活。驱动工程师的核心场景是sensor能不能被正确识别、上电时序是否正确、I2C能不能通信、MIPI能不能出图、时钟配得对不对、buffer能不能申请下来、request能不能按时完成。说白了驱动是“保底”的效果是“加分”的。如果底层数据通路都不稳效果做得再好也是空中楼阁。所以我的建议是调试之前先把下面这张逻辑链路刻在脑子里。用户点开相机AppHAL下发stream onkernel的cam_sensor驱动给sensor上电并通过CCI读sensor ID确认连接正常然后配置sensor的曝光、增益、帧长等寄存器CSID/CSIPHY按设备树配置的lane数和时钟初始化MIPI链路sensor开始输出RAW图数据经过IFE后写到申请好的buffer里HAL拿到buffer做后续处理。这条链路里任何一个环节出问题现象都可能是黑屏、花屏、卡死或者直接报错崩溃但根因可能差得很远。下面每一章都在讲这条链路上某个具体环节的排查手法。2. 驱动起不来的第一现场硬件连接与上电时序排查新板子回来或者新模组第一次上电最常遇到的就是sensor完全没反应。kernel log里翻来翻去就一句话cam_sensor: probe succeeded这种话根本没有或者直接报i2c read failed。这时候别急着查驱动代码先确认硬件是否真的活了。2.1 电压测量和波形抓取的先后顺序我自己的习惯是三步走。第一步用万用表量vdd、vddd、vddio三路供电是否有正常电压很多模组对电压纹波很敏感万用表只能量平均值所以第二步要上示波器抓上电瞬间的波形。特别是MCLKsensor要靠主控提供的时钟才能启动内部逻辑MCLK的频率和幅度不对sensor就算供电正常也起不来。高通的MCLK一般是从SoC的clock controller出来的频率常见19.2MHz但也有24MHz的模组这个值必须跟模组规格书对准。第三步是关键的一步抓XSHUTDOWN和RESET这两个引脚的时序。很多sensor对上电时序有严格先后要求比如先供电、再给MCLK、稳定几毫秒后再拉高XSHUTDOWN然后再等个几十毫秒才能开始I2C通信。驱动里这套时序是由power-sequence配置控制的定义在设备树里。调试时我经常遇到的现象是sensor ID读到了但偶尔读不到或者开机正常、休眠唤醒后失联。这类问题大概率是power sequence里的delay设置不给力某个步骤的间隔时间卡在sensor要求的临界点上冷机正常热机不正常的案例我碰到过不止一次。设备树里power sequence大概长这样power-sequence { qcom,power-seq-type gpio, regulator, gpio, gpio; qcom,power-seq-val gpio, ldo, gpio, gpio; qcom,power-seq-cfg 119 0 0, 0 0 0, 118 1 0, 119 1 0; qcom,power-seq-delay-us 10000, 1000, 10000, 20000; };这里每个数组元素和delay是一一对应的含义是依次执行“配置某个gpio/regulator为某个状态后再等多少微秒”。我踩过的一个坑是gpio编号用错了高通各平台的GPIO号不是连续的不同TLMM基址算出来的全局GPIO号可能相差几百。核对GPIO号的正确姿势是在设备树里找到对应平台的TLMM mapping文件或者直接用cat /sys/kernel/debug/gpio看当前gpio被谁claim了。2.2 常见错误的表象与定位方式sensor读不到ID的时候先分清是I2C NACK还是ACK了但回的数据不对。kernel log里如果出现cci: I2C NACK之类的关键字说明sensor根本没在总线上回应问题在供电、时钟、复位、I2C地址这几项上。如果log里没报NACK但读回来的ID和模组规格书对不上那基本是sensor的两个I2C地址引脚电平配错了或者设备树里配的slave地址跟实际不符。还有个非常隐蔽的坑sensor的FSIN引脚。这个脚在部分OV和SONY方案里是帧同步输入如果模组把FSIN引出来、板上悬空或者电平不定可能导致sensor内部状态机异常表现就是I2C通信正常但sensor不曝光、不出图。实际验证方法是把FSIN引脚强制拉低或拉高试一下或者查sensor驱动里有没有对FSIN做初始化。硬件连接这块我建议每个项目都总结一张表格把模组型号、I2C地址、供电电压、MCLK频率、lane数、XSHUTDOWN/FSIN对应的GPIO号、power sequence类型全部列出来。后面所有调试都围绕这张表展开一旦sensor异常先拿表对照一遍物理连接至少能排除掉一半的硬件嫌疑。3. 寄存器配错时怎么一步一步追回来sensor能动起来之后下一个大坑就是寄存器配置。模组厂给过来的sensor driver的初始化寄存器表动不动就是几百上千行长表很多高位的配置项含义非常隐晦。寄存器配错的表现五花八门预览偏色、帧率不对、曝光异常、花屏、甚至ISP直接报错。问题在于驱动人员往往没法轻易判断某个寄存器到底是干嘛的只能靠经验猜。这里分享几个我常用的追查思路。3.1 把寄存器设置拆成功能分组我不建议拿到寄存器表就从上往下一行行看那样信息密度太低。我的做法是先按功能把寄存器分组芯片版本和ID类比如0x00、0x01这类、软件复位和Standby控制、AGC/增益相关、曝光时间相关、HTS/VTS这类时序相关、镜像和Binning相关、测试图案输出、MIPI/LVDS输出控制。这需要参考sensor datasheet或者模组厂提供的驱动说明文档但大部分情况下从寄存器名字上也能猜个大概比如vts、hts这种缩写出现频率极高。有一点必须提醒不同厂商的sensor寄存器地址不通用同一个功能在不同型号上可能完全不是一个地址所以不要拿OV的健忘经验去套SONY查寄存器一定要以当前模组的datasheet为准。曝光和帧率相关的寄存器在高通驱动调试中是最容易出问题的。高通HAL的三A算法会通过驱动层设置曝光和增益如果你发现出图的亮度异常、自动曝光不工作、预览帧率跟预期差很远那大概率是驱动对曝光寄存器和VTS垂直消隐/帧长寄存器配置不当。这里有个实用的推算方法先算出sensor当前的pixel clock然后根据VTS和HTS推算实际帧率。如果你从寄存器表里读到的VTS/HTS算出的帧率和预期值对不上说明寄存器配置和HAL侧设置的曝光参数之间有冲突。3.2 用i2c-tools在板端直接操作有时候单纯靠逻辑分析不直观我习惯直接在板子上操作。高通的CCI总线其实也是标准I2C只要你知道sensor挂在哪个CCI口上、地址是多少就可以用i2c-tools直接读。# 列出I2C总线 i2cdetect -l # 扫描指定总线上的设备注意有些sensor对总线扫描敏感可能触发异常 i2cdetect -y 10 # 从0x10地址寄存器读1字节 i2cget -y 10 0x20 0x10 # 向0x10地址寄存器写0x03 i2cset -y 10 0x20 0x10 0x03不过i2c-tools在Android/user空间直接操作CCI总线的时机要选好如果Camera服务已经起来了直接用i2c-tools去读写sensor寄存器可能跟驱动的访问互相打架。所以我一般在开机后、Camera服务启动前或者先停掉Camera相关服务再操作。这招在追踪“某个寄存器写入到底生效了没有”的时候特别管用我经常用它验证驱动里某个配置写进去的是不是预期的值。3.3 从报错日志倒推寄存器冲突驱动跑着跑着出问题先别急着改代码把log里的关键行先读懂。常见的和高通驱动相关的报错有camsensor: sensor_ops-apply_settings failedcam_cci: cci_read failedcam_isp: stream on failed, type: 3cam_sync: sync device timeoutimx577: failed to set digital gain每一类报错的排查方向差别很大。apply_settings failed说明驱动在应用sensor settings时某个函数返回了错误可能是I2C写失败也可能是在某个中间步骤校验不过。sync device timeout则是request完成超时的表现图像流根本没有走完。建议用户空间工具抓到这些关键字后再结合kernel的dynamic debug把msm-camera子系统的日志级别临时调高看更底层的细节。高通的驱动框架里很多地方直接用CAM_ERR(CAM_SENSOR, xxx)这种宏打log如果当前log级别把debug级过滤了那些只言片语很难串起来。寄存器调试这块有时候还得靠“对比法”。同一个sensor在不同平台上跑的配置只要平台一致比如都是kalama大部分寄存器配置可以直接对比。如果相同模组在某个平台正常、另一个平台异常把两份驱动的初始化寄存器表找差异最能快速定位问题。注意排除平台本身的硬件差异比如lane数不同、MCLK频率不同、CSI口不同这些会导致时序或链路参数有差异不代表寄存器配置本身错了。4. 设备树配置错误的常见现场与排查链路设备树在高通Camera驱动里承担了很重的配置职责。sensor节点挂在哪个CCI口、用的哪个CSID和CSIPHY、每个CSID的lane数、电源用的哪个regulator、GPIO是哪个、reset和shutdown脚的极性、sensor的profile信息等等全部由设备树描述。很多“驱动起不来”的问题根子都在设备树配置错。4.1 设备树节点的关键字段及其含义sensor设备树节点长这样sensor_rear_wide { status ok; qcom,mode gpio; cci-master 0; qcom,cam-power-seq-type cam_vio, cam_vaf, cam_vana; qcom,cam-power-seq-cfg 0 1 0, 1 1 0, 2 1 0; qcom,cam-power-seq-delay 10000, 10000, 10000; gpios tlmm 119 0, tlmm 118 0, tlmm 117 0; qcom,gpio-reset 1; qcom,gpio-req-tbl-num 0 1 2; qcom,gpio-req-tbl-flags 0 1 1; qcom,gpio-req-tbl-label CAMIF_MCLK0, CAM_RESET0, CAM_VANA0; cam-supply-names cam_vio, cam_vaf, cam_vana; };这里容易出问题的字段我列几个cci-mastersensor挂在哪个CCI口上取值0或1。如果设备树里写的是CCI0但物理上sensor接到了CCI1I2C通信必然失败。gpios三个GPIO通常分别对应MCLK、RESET、其他控制脚。很多人会忽略qcom,gpio-req-tbl-flags这个字段决定GPIO方向配成input了往外拉是拉不动的。qcom,cam-power-seq-type电源序列的类型可以是regulator类型或者gpio类型与cam-supply-names搭配使用。这里顺序错了或者名字对不上驱动probe时就会在请求电源处失败。qcom,cam-phy-sel或phy-selMIPI PHY选择有些平台有多个CPHY或者DPHY配置选错了表现为带宽异常或者完全不出图。除了sensor节点Camera驱动还需要CPAS、CSID、CSIPHY等节点的配置。很多新人在设备树里只改了sensor节点忘了检查两个sensor是否共享同一组CSI/CSID资源。比如后置主摄和前置共用同一个CSI口但两个sensor的lane数加起来超过了4条kernel侧就会在cam_cpas初始化时报资源冲突。4.2 设备树排查的具体手法在板端确认设备树生效字段最直接的方法是查/proc/device-tree。# 查看sensor节点的实际解析结果 cat /proc/device-tree/soc/cciac4a000/qcom,i2c-custom-mode # 查看某个sensor节点下所有支持的模式 ls /proc/device-tree/soc/cciac4a000/qcom,cam-sensor0/ # 直接看某个属性 cat /proc/device-tree/soc/cciac4a000/qcom,cam-sensor0/qcom,cam-power-seq-type这种方法看到的是设备树解析之后的二进制值如果看到的值跟你预期不符说明dtbo没编进去或者被覆盖了。高通平台用dtbo/DTB overlay机制同一个内核镜像可以适配不同模组的设备树出问题时先确认烧到板子上的dtbo是不是最新版本这个坑经常导致“我改了设备树但完全没生效”。SMMU相关的配置错误也是个老大难。高通的ISP通过IOMMU管理内存buffer如果sensor节点的iommus属性或qcom,iommu-dma配置不对stream on就会报SMMU fault。这类报错的特征是log里有arm-smmu相关call trace。排查时查看/sys/kernel/debug/arm-smmu/下的寄存器信息配合dmesg里的SMMU fault地址往往能看出是哪个buffer的映射出了问题。设备树的排错链路其实可以总结为一个三段式思路。第一步查解析确认设备树字段是否按照预期生效第二步查资源确认GPIO、regulator、clk这些物理资源是否被正确请求和释放有没有被其他模块占用第三步查运行时在驱动probe和stream on的路径上加入动态打印输出设备树解析出的关键参数跟实际硬件做对照。这个链路走完大部分设备树层面的问题都能水落石出。5. 图像出问题时先把驱动嫌疑排除掉图像效果问题是最容易让人抓狂的。我经常收到这类反馈“图像偏绿”“条纹闪烁”“画面撕裂”“整体亮度不对”。很多人第一反应去找效果工程师但实际上一大半“图像异常”的根子在驱动侧。我的原则是任何图像问题先把驱动嫌疑排除掉再往效果方向查。下面按常见现象逐个拆解。5.1 花屏、条纹、色偏的驱动侧根因花屏和条纹这类问题90%以上是MIPI链路配置和sensor输出配置不匹配。MIPI链路端涉及lane数、差分信号数据速率、时钟通道极性。sensor输出端涉及输出格式RAW8、RAW10、RAW12等、数据位宽、是否启用PHY切换、是否启用虚拟通道。以RAW10为例高通CSID解析RAW10时有两种打包方式一种是每个pixel按10bit紧凑排列另一种是每4个pixel打包到5个byte里也叫“unpacked”或者“packed”模式。如果sensor侧输出的是packed RAW10而CSID侧配置的是unpacked画面上就会出现规律的条纹和错位看上去像“图像被剪碎了”。这类问题从log里很难直接看出来因为它不会报错只是图像数据解释方式不对。要验证这个问题一个简单的方法是输出sensor的test pattern。几乎所有sensor都有test pattern模式通过寄存器可以切到纯色、彩条或者棋盘格输出。如果test pattern在预览上显示正常说明MIPI链路、CSID解析、ISP管线都是通的问题在sensor的实际图像输出配置上如果test pattern也花屏那问题就在链路参数或CSID解析配置上跟sensor本身没关系了。// 以某个sony sensor为例开启测试图案的寄存器写法 // reg 0x0601 bit[3:0] 0x1 输出彩色竖条纹 sensor-reg_settings (struct cam_sensor_i2c_reg_setting[]) { { 0x0601, 0x01, 0, CAM_SENSOR_I2C_BYTE_DATA }, };驱动里临时把sensor切到test pattern再切回来是定位花屏问题最有效的招数之一。注意切回正常模式后要重新初始化一遍sensor或者设置正确的输出模式寄存器否则会出现测试图案残留或者黑屏。5.2 黑屏和亮度异常的驱动侧排查顺序黑屏分两种。一种是完全无数据流HAL侧报buffer handle不到数据驱动侧log出现stream on fail或者fence timeout另一种是有数据流但图像全黑说明sensor在出图但内容全黑要么是曝光时间为0、增益为0要么是sensor没有正确曝光比如镜头盖没打开或者IR cut不对。全黑图重点查曝光和增益相关的寄存器以及FSIN引脚状态。亮度异常则是驱动配置和sensor实际能力不匹配的表现。比如sensor支持的最大曝光时间是按行数算的如果VTS寄存器配小了曝光行数被截断画面就会过暗。反过来如果VTS配得很大帧率掉下来同时曝光时间范围变大可能出现过度曝光。这里一定要理解曝光、VTS、帧率三者的关系曝光时间最长不能超过一帧的总时长总时长由VTS乘以每行时间决定。所以调整帧率时必须同步修改VTS和曝光上限否则曝光范围不对会导致效果工程师没法调。驱动侧的3A参数一般由HAL的CHI override配置下发驱动只要正确地把这些参数翻译成sensor寄存器写入即可。如果发现Auto Exposure不工作手动设置曝光值图像亮度有反应那问题在3A算法和HAL的连接如果手动设置曝光值也没反应那问题在驱动对曝光寄存器的写入上。用手动曝光测试来分割问题边界是个好方法HAL侧改override或者直接用v4l2-ctl这类工具设定曝光参数观察图像亮度是否变化就能把排查范围缩小一半。5.3 帧率和分辨率不对时的驱动侧检查预览帧率不对也分两种情况一是整体帧率低于预期二是帧率跳动不稳定。整体帧率偏低先检查MIPI数据速率是否足够。数据速率不够会导致带宽瓶颈CSID侧可能直接丢弃帧或者报带宽不足。高通CSID有一个带宽计算的公式和lane数、数据位宽、pixel clock相关设备树里的qcom,mipi-csi-phy参数如果与实际sensor输出不匹配可能出现帧率减半的现象。帧率不稳定则优先查VTS寄存器是否被HAL动态调整。如果驱动在某个流程里把VTS写死了或者没有正确处理HAL下发的frameLengthLines参数就会出现帧率波动。此时在驱动里把每次配置的frame length lines值dump出来和预期值做对比基本能断定问题在哪一侧。分辨率方面一个常见的坑是binning模式没有正确配置。sensor在binning模式下的输出尺寸是原始分辨率的1/2或1/4如果驱动配置的sensor output尺寸和ISP侧期望的尺寸不一致要么裁切不对要么出图尺寸错误。这类问题通常在切换分辨率或者切换binning模式时出现排查时重点检查模式下对应的active_w、active_h、line_length_pclk这些参数是否与sensor datasheet一致。6. msm框架下的沉淀池debugfs与fence超时处理高通Camera驱动调试最让人头疼的就是它把很多状态沉淀到了debugfs和kernel日志里却很少有人告诉你该去哪里看。我见过太多人遇到问题只会抓logcat抓了半天全是HAL层的错误反而把kernel侧最直观的信息错过了。6.1 值得常看的debugfs节点高通平台的Camera驱动会在debugfs下暴露一批节点常见的路径是/sys/kernel/debug/cam_sensor、/sys/kernel/debug/cam_cci、/sys/kernel/debug/cam_cpas等。每个节点对应的信息维度不同我整理了一张表供参考节点路径关注内容适用场景/sys/kernel/debug/cam_sensorsensor的probe状态、power sequence执行情况、当前modesensor起不来、休眠唤醒异常/sys/kernel/debug/cam_cciCCI总线错误计数、各master的I2C通信统计I2C异常、总线冲突/sys/kernel/debug/cam_cpas时钟和电源域的open/close状态、带宽汇总stream on失败、资源冲突/sys/kernel/debug/cam_syncsync object状态、fence注册与signal状态fence timeout、request完成超时/sys/kernel/debug/cam_smmuSMMU映射表、page fault计数地址映射错误、内存访问异常有段时间我处理一个问题现象是相机打开后预览前几帧有明显卡顿之后正常。用cam_sync的debugfs节点看不活跃的fence发现每次打开相机都会有几个之前session的fence没有及时signal导致HAL侧等了一会儿才继续。这个从用户态log里完全看不到但在debugfs里一目了然。6.2 fence timeout的完整排查链路fence timeout是kernel侧报出来的一种典型错误log里通常出现cam_sync: sync device timeout或者cam_fd: hw timeout。fence在这里的角色是同步机制类似Android图形栈里的fence专门用来保证Camera request的各个阶段按顺序完成。一个request从HAL下发到驱动会经过sensor配置、ISP处理、HW输出、buffer填充等多个阶段每个阶段都对应一个fence全部signal了才算request完成。fence timeout出现时先做的是在kernel log里找到具体的fence对象名和超时时间。然后通过debugfs查这个fence当前的状态它是处于pending、signaled还是error状态它在等哪个下游对象它的owner是谁。这几个信息能帮你判断问题是在HW处理阶段还是在上层驱动配置阶段。完整排查链路大概是这个顺序。第一步确认fence timeout的具体位置是sensor侧、ISP侧还是JPEG/ICP侧。第二步查看对应硬件引擎的log比如ISP超时就找cam_isp相关的ERR日志JPEG超时就找cam_jpeg。第三步用ftrace或者perfetto抓一下时间线看request从下发到哪个时间点完全失去响应。第四步查看SMMU是否有fault因为一旦SMMU fault硬件引擎可能直接hang住fence永远不会signal。第五步如果以上都没发现基本可以怀疑是硬件问题用压力测试脚本反复做stream on/off和分辨率切换看能不能稳定复现。高通平台支持用perfetto抓取kernel的ftrace事件配合Camera HAL层的trace能把一个request从应用层到硬件引擎的时间线拉出来。这对定位“fence超时到底卡在哪一段”很有帮助。抓取方法是在板子上先使能atrace和kernel trace# 抓取kernel侧的camera相关trace echo 1 /sys/kernel/debug/tracing/events/msm_cam/enable echo 1 /sys/kernel/debug/tracing/tracing_on # 然后复现问题抓完关闭 echo 0 /sys/kernel/debug/tracing/tracing_on cat /sys/kernel/debug/tracing/trace /data/local/tmp/cam_trace.txtperfetto抓出来的trace里能直接看到request在某个CSL硬件引擎上停留了多久如果停留时间超过预期而硬件没有中断上报那问题的嫌疑就在硬件中断或者驱动中断处理逻辑上而不是在上层配置。6.3 静态信息之外别忘了动态状态debugfs节点看的是当前状态但很多问题是状态跳变过程中出的。这时候需要让驱动在关键路径上打印更多信息。高通msm-camera驱动支持用dynamic debug来打开某些文件的pr_debug信息在板端操作echo file drivers/media/platform/msm/camera/cam_sensor/cam_sensor_dev.c p /sys/kernel/debug/dynamic_debug/control echo file drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c p /sys/kernel/debug/dynamic_debug/control打开了这些动态打印之后再复现一次问题得到的信息量比默认log大得多。注意dynamic debug会对性能有轻微影响别全量打开按需打开怀疑的文件即可。定位完问题要记得关掉否则日志量太大会把可用存储空间吃掉。7. 日志分级与高效抓取从开机崩溃到效果回归很多调试场景都需要完整的日志支撑但怎么抓才高效、怎么抓才能抓到关键信息这里面的门道其实挺多。高通的Camera日志体系分成三大块kernel logdmesg、HAL logCamX/CamRTS、以及Android上层loglogcat。三块各自记录了不同层面的信息缺一不可。7.1 Kernel侧日志的抓取技巧kernel侧日志主要通过dmesg拿到但要抓到Camera驱动的完整log直接dmesg往往不够。原因是内核log buffer默认可能不够大开机到复现问题的时间跨度太长早期的关键log被覆盖了。我的做法是抓串口log或者pstore/ramoops某些硬件平台支持在异常时把内核log保存到独立分区。还有一种情况是内核log本来就设计了分级过滤loglevel或ignore_loglevel启动参数会影响dmesg能看到多少信息。如果怀疑驱动里用pr_debug或dev_dbg打印的关键信息没出现先确认内核启动参数里有没有打开dynamic debug或者当前loglevel是否允许debug级输出。Kernel侧常用log tag我列一下Log tag所属模块常见用途cam_sensorsensor驱动sensor probe、power sequence、settings应用cam_cciCCI控制器I2C读写、总线错误cam_csidCSID驱动CSI协议解析、错误中断cam_csiphyCSIPHY驱动PHY配置、时钟、测试图案cam_ispISP驱动stream on/off、buffer管理cam_cpasCPAS驱动时钟电源、带宽分配7.2 CamX/HAL日志的开关与筛选HAL层的日志是由camxoverridesettings.txt控制的这个文件通常在vendor/etc/camera/路径下。CamX的日志模块划分很细从CamX通用框架、ChiOverridesCHI层、Sensor、ISP、Stats、ICP等模块都有独立的log级别控制。调试时按需打开对应模块即可不要全量打开否则logcat会被刷爆反而抓不到有效信息。// camxoverridesettings.txt 示例 OverrideLogPriorityWarn LogPriorityCamXInfo LogPrioritySensorVerbose LogPriorityISPVerbose LogPriorityStatsInfo LogPriorityICPWarn注意修改这个文件后要重启CameraServer才能生效高通的CameraServer可以在不开机重启的情况下通过stop/start重启adb shell stop camera adb shell start camera不过部分平台上直接stop camera会连带把CameraProvider等服务一起停掉稳妥起见还是重启后生效。HAL层的logcat过滤可以用adb logcat -s CamX:V CamX:W这种方式按优先级过滤或者用正则匹配。CamX日志里最有价值的信息是它会把每次stream on的关键配置摘要打出来包括分辨率和格式、buffer数量、3A算法开关等。抓到这部分内容后再跟设备树和驱动配置对比很多时候问题就已经浮出水面了。7.3 高效日志抓取的实践组合我实际调试时最常用的组合是三种手段并行。第一种是后台持续抓dmesg和logcat到文件保留最近几十分钟的滚动日志第二种是用perfetto做用户态和内核态的trace特别是修fence timeout这类跟时间线强相关的问题第三种是针对特定模块打开dynamic debug和CamX模块级日志。三管齐下既能看宏观状态又能看微观时间线还能看具体模块的内部变量。有兄弟问我日志抓多久合适我个人经验是抓到你稳定复现一次问题的时间窗口的2到3倍。比如问题每30秒出现一次那至少抓90秒的日志。有些间歇性问题的触发依赖特定时序只抓几秒钟大概率错过现场。日志分析有个习惯也值得养成拿到log后先看时间戳把所有内容按时间线对齐。dmesg的时间戳和logcat的时间戳不能直接对比要把boottime转换成elapsed realtime再对齐。perfetto抓出来的trace自带统一时间线处理跨层问题时效率高得多。7.4 用好on-device的日志滚动与持久化在板上长时间抓log最尴尬的是抓了几十分钟发现存储空间满了后面关键内容全丢了。我一般会在抓log之前先清理分区预留足量空间adb shell logcat -c adb shell dmesg -c adb shell ls -lh /data/vendor/camera/ dump_all_logs.txt如果问题只出现在开机早期比如开机后十几秒内Camera就崩溃那提前进bootloader抓串口log更靠谱。高通平台的sbl和aboot阶段也会输出一部分硬件初始化信息这些信息在Android起来之后是看不到的。串口log抓不到的情况下也可以看/sys/fs/pstore/下的ramoops记录某些异常重启场景的last log会沉淀在那里。8. 最后几个实战里沉淀出来的经验代码能跑通只是开始真正让人头疼的往往是那些间歇性的、环境相关的疑难杂症。我最后分享几个从项目里实际摸索出来的经验权当给后面的人少走弯路。第一个经验调试信息必须分层管理驱动代码里至少要留好sensor日志、cci总线日志、isp流水线日志三个维度的打印开关。别把所有log都塞到一个级别里否则线上问题出来看log根本没法分层过滤。我习惯在每个模块入口和关键状态迁移点都留一句可开关的pr_info默认关闭排查时再按需打开。这个习惯帮我省了无数次全量抓log的体力活。第二个经验遇到诡异问题先怀疑“非Camera侧因素”。我处理过一个sensor偶尔失联的问题查了两周最后发现是同一根flex排线在设备组装后会被另一个器件压住导致MIPI差分信号在特定温度下阻抗异常。驱动代码改成什么样都没用物理层的问题必须用示波器才能看穿。所以遇到间歇性问题先花半小时确认机械结构和信号完整性别一上来就在代码里乱试。第三个经验善于利用“基线对比”。同样是kalama平台同样型号的sensor之前某个项目上跑得好好的换了个模组厂之后问题频出。这种时候我第一件事是找模组厂要参考驱动拿上一版稳定的驱动和当前驱动做全量diff重点对比power sequence、初始化寄存器表、MCLK频率、lane配置这几项绝大多数兼容性差异都能在这几步里找到。之前有一次偏绿问题diff下来居然发现新模组的sensor内部白平衡寄存器默认值跟旧版不同驱动里补一组初始化寄存器就解决了。第四个经验日志和配置要做版本管理。Camera调试最怕“上次调好的配置哪去了”。设备树、camxoverridesettings、sensor驱动寄存器配置这三类东西每次改动都要落版本并且记录在案的还要注明变更原因和验证结果。我见过太多项目因为某次调参没记录后面回退的时候彻底抓瞎只能重新盲调一遍。做高通Camera驱动调试本质上是一个信息收集、分层归因、逐步排除的过程。底层的数据通路和硬件特性是地基地基不稳上层什么都是空的。把这套调试方法刻在脑子里遇到问题按这个思路走一遍大部分疑难杂症都能找到方向。剩下的那些实在查不出来的记录下来那就是你下一篇文章的最佳素材。
返回列表