Qualcomm android camera 架构简析及如何debug
一. Camera模组(CCM)介绍:
CCM一般包含四大件: 镜头(lens)、传感器(sensor)、软板(FPC)、图像处理芯片(DSP):
Camera的成像原理可以简单概括如下:
1、CCD/CMOS将被摄体的光信号转变为电信号—电子图像(模拟信号)
2、由模/数转换器(ADC)芯片来将模拟信号转化为数字信号
3、数字信号形成后,由DSP或编码库对信号进行压缩并转化为特定的图像文件格式储存
4. 送到cpu中处理并display。
二. 电路图
1. 电源
--dvdd,iovdd,avdd。
2. I2c
由于I2C接口采用OpenDrain机制,器件本身只能输出低电平,无法主动输出高电平,只能通过外部上拉电阻RP将信号线拉至高电平。因此I2C总线上必须有上拉电阻!
阻值:I2C的上拉电阻可以是1.5K,2.2K,4.7K, 电阻的大小对时序有一定影响,对信号的上升时间和下降时间也有影响,一般接1.5K或2.2K。不能低于1k。高于10k。
过小的话灌入端口的电流变大,低电平变高。过大上升平缓。
通产情况下,SDA,SCL两条线上的上拉电阻取值是一致的,并上拉到同一电源上。
在I2c总线可以串连300欧姆电阻RS可以用于防止SDA和SCL线的高电压毛刺.
3. Mipi
而DDR是一个时钟周期内传输两次次数据,它能够在时钟的上升期和下降期各传输一次数据,因此称为双倍速率同步动态随机存储器
MIPI的通道模式和线上电平。在正常的操作模式下,数据通道处于高速模式或者控制模式。在高速模式下,通道状态是差分的0或者1,也就是线对内P比N高时,定义为1,P比N低时,定义为0,高低速分别200MV,1.2V.
控制模式:LP11,LP10,LP01,LP00四个状态;MIPI协议规定控制模式4个不同状态组成的不同时序代表着将要进入或者退出高速模式等;比如LP11-LP01-LP00序列后,进入高速模式。下图为线上电平的图示
MIN [ Settle count * T(Timer clock)] > T(HS_SETTLE)_MIN
MAX [ Settle count * T(Timer clock)] < T(HS-PREPARE)+T(HS_ZERO) - 4*T(Timer clock)
三.AndroidCamera框架简析
从Android框架看,分为四层:应用层、应用框架层、库层、内核层。
库层是Android与底层硬件通信接口,它封装底层硬件接口实现该模块的具体逻辑,并以服务的形式通过Binder通讯机制暴露给应用框架
1.camera应用层
2.Framework.Camera client/service
3.硬件抽象层HAL Hardware Abstraction Layer
1.1、camera应用层
Camera 的应用层在Android 上表现为直接调用SDK API 开发的一个Camera 应用APK 包。主要对 android.hardware.Camera(在Framework中) 类的调用,并且实现Camera 应用的业务逻辑和UI 显示。
使用这个android.hardware.Camera类,需要在Manifest 文件声明Camera 的权限,另外还 需要添加一些 元素来声明应用中的Camera 特性。
......
1.2、Framework层
1.android.hardware.Camera封装类。
/frameworks/base/core/java/android/hardware/Camera.java
这是Android 提供给app层调用的java接口。这个类用来连接或断开一个Camera 服务,设置拍摄参数,预览,拍照等。作为Android SDK Camera部分提供给上层应用,并通过JNI的方式调用本地C++代码。
Camera的JAVA native调用部分(JNI):/android/frameworks/base/core/jni/android_hardware_Camera.cpp。承接JAVA 代码到C++ 代码的桥梁。
1.3.Camera框架的client部分:
代码位置:/android/frameworks/av/camera/ICameraClient.cpp
这部分的内容编译生成libcamera_client.so 。与另外一部分内容服务端libcameraservice.so 通过进程间通讯(即Binder 机制)的方式进行通讯
1.4.Camera框架的service部分
代码位置:/android/frameworks/av/camera/ICameraService.cpp
这部分内容被编译成库libcameraservice.so 。CameraService 是Camera 服务,Camera 框架的中间层,用于链接CameraHardwareInterface 和Client部分 ,它通过调用实际的Camera 硬件接口来实现功能,即下层HAL层。
1.5、硬件抽象层HAL
这层的代码在/android/hardware/qcom/camera, 直接和底层硬件驱动相关的。
框架层对下在CameraHardwareInterface.h头文件中定义了Camera硬件抽象层的接口,它是包含纯虚函数的类,必须被实现类继承才能使用。HAL层正好继承CameraHardwareInterface接口,依据V4l2规范实例化底层硬件驱动,使用ioctl方式调用驱动.
代码流程:
1、Camera apk----java
2、camera java interface,JNI-----(java—>C++)
3、camera client-----C++
4、camera services----C++
5、HAL----C++
6、camera drv
a. 点击Camera 应用后,进入CameraActivity.java,完成初始化,
onCreate 调用setModuleFromIndex 方法,赋值 mCurrentModule = new PhotoModule();
mCameraDevice = CameraUtil.openCamera(
mActivity, mCameraId, mHandler,
mActivity.getCameraOpenErrorCallback())
其中mCameraDevice是com.android.camera.CameraManager.CameraProxy;的实例。
CameraUtil属于公共的API,用于给不同模块提供对Camera的不同操作。
在它openCamera 方法里,执行:
CameraHolder.instance().open(handler, cameraId, cb);
其中CameraHolder.instance()单例模式。目的就是控制,相机开启的只有能是一个。再次开启前,要确认上次已经销毁。
b、 在CameraManager系统服务,获得camera设备对象为Camera设备提供操作的方法。
public CameraProxy cameraOpen(
Handler handler, int cameraId, CameraOpenErrorCallback callback);
CameraProxy 里AndroidCameraProxyImpl类这个接口就是将对Camera 接受和发送的操作,送达到Camera设备。
这个接口的实现类是AndroidCameraProxyImpl,这个类属于AndroidCameraManagerImpl的内部类。在AndroidCameraManagerImpl.java 里面还有一个内部类CameraHandler,这个类属于Handler。在CameraHandler的handleMessage方法里,就是根据不同的消息参数来对android.hardware.Camera
进行控制。比如打开,释放,对焦,变焦等等
c. jni
应用里通过CameraProxy对象发送消息给CameraHandler处理,CameraHandler通过android.hardware.Camera的接口去调用JNI层的方法,Camera JNI实现在android_hardware_Camera.cpp里
d. Camerahal
Camera HAL层的接口是通过CameraHardwareInterface类的各个方法给framework调用, CameraHardwareInterface对象在CameraClient里实现,并且CameraClient封装了Camera硬件的各个操作的接口.
Camera.cpp里的每一个Camera的操作方法最后都调用ICamera接口里定义的方法,这个接口被BpCamera继承,BpCamera是binder机制的标准使用方法,他对应的调用类就是BnCamera.
e. 为了实现一个具体功能的Camera,在最底层还需要一个硬件相关的Camere 驱动库(例如通过调用video for linux 驱动程序和Jpeg 编码程序实现)。这个库将被Camera 的服务库libcameraservice.so 调用。
f.Camera内核code
Driver,csid,csiphy..
android启动和camera probe:
Probe:Server.c->main
四.Camera debug:
Sensor log:
adb shell setprop persist.camera.hal.debug.mask 536870919
HAL/mm-camera-interface/mm-jpeg-interface CDBG_HIGH() 和CDBG() log都会被打印. CDBG_ERROR() log总是被打印
0-27位决定打印模块(目前只有三个模块):
§Bit0: HAL (hardware/qcom/camera/QCamera2/HAL)
§Bit1: mm-camera-interface (hardware/qcom/camera/QCamera2/stack/mm-camera-interface)
§Bit2: mm-jpeg-interface (hardware/qcom/camera/QCamera2/stack/mm-jpeg-interface)
adb shell setprop persist.camera.sensor.debug 3
§ SERR(), SHIGH()和SLOW() log会被打印
adb shell setprop persist.camera.imglib.logs 4
§ IDBG_ERROR(), IDBG_HIGH() , IDBG_MED(), IDBG_LOW()都会被打印
adb shell setprop persist.camera.pproc.debug.mask 805306375
§805306375 = 0x30000007, 表示PPROC/C2D/CPP模块CDBG_HIGH(), CDBG(), CDBG_LOW() 都会被打印.
Bit0: PPROC (mm-camera2/media-controller/modules/pproc-new)
§Bit1: C2D (mm-camera2/media-controller/modules/pproc-new/c2d)
§Bit2: CPP (mm-camera2/media-controller/modules/pproc-new/cpp)
adb shell setprop persist.camera.mct.debug.mask 536870913
§536870913 = 0x20000001, 表示MCT CDBG_HIGH(), CDBG() 都会被打印.
0-27位决定打印模块(目前只一个模块):
§Bit0: PPROC (mm-camera2/media-controller/mct)
adb shell setprop persist.camera.ISP.debug.mask 16777217
§16777217 = 0x1000001, 打开ISP_MOD_COM. ISP_MOD_LINEARIZATIO log
Bit 0: ISP_MOD_LINEARIZATION
Bit 1: ISP_MOD_ROLLOFF
Bit 2: ISP_MOD_DEMUX
Bit 3: ISP_MOD_DEMOSAIC
Bit 4: ISP_MOD_BPC
Bit 5: ISP_MOD_ABF
Bit 6: ISP_MOD_ASF
Bit 7: ISP_MOD_COLOR_CONV
Bit 8: ISP_MOD_COLOR_CORRECT
Bit 9: ISP_MOD_CHROMA_SS
Bit 10: ISP_MOD_CHROMA_SUPPRESS
Bit 11: ISP_MOD_LA
Bit 12: ISP_MOD_MCE
Bit 13: ISP_MOD_SCE
Bit 14: ISP_MOD_CLF
Bit 15: ISP_MOD_WB
Bit 16: ISP_MOD_GAMMA
Bit 17: ISP_MOD_FOV
Bit 18: ISP_MOD_SCALER
Bit 19: ISP_MOD_BCC
Bit 20: ISP_MOD_CLAMP
Bit 21: ISP_MOD_FRAME_SKIP
Bit 22: ISP_MOD_STATS
Bit 23: ISP_MOD_COLOR_XFORM
Bit 24: ISP_MOD_COM
adb shell setprop persist.camera.stats.debug.mask 7
§7 = 0b111, 打开AEC/AWB/AF log
Bit 0: STATS_DEBUG_MASK_AEC_LOG
Bit 1: STATS_DEBUG_MASK_AWB_LOG
Bit 2: STATS_DEBUG_MASK_AF_LOG
Bit 3: STATS_DEBUG_MASK_ASD_LOG
Bit 4: STATS_DEBUG_MASK_AFD_LOG
MSM8916 Android 5.0 Camera log -HAL
adb shell setprop persist.camera.hal.debug 2
§表示HAL/mm-camera-interface/mm-jpeg-interfaceCDBG_HIGH() 和CDBG() log都会被打印. CDBG_ERROR() log总是被打印
adb shell setprop persist.camera.sensor.debug 2
§表示sensor module (mm-camera2/media-controller/modules/sensors)SERR() , SHIGH() 和SLOW() log都会被打印.
CPP-log
没有动态开关,需要修改mm-camera2/media-controller/modules/pproc-new/cpp/cpp_log.h里面定义的CPP_LOG_VERBOSE后重新编译
§CPP_LOG_VERBOSE = 0,只有CPP_ERR() log被打印
§CPP_LOG_VERBOSE = 1,CPP_ERR(), CPP_HIGH() log被打印
§CPP_LOG_VERBOSE = 2,CPP_ERR(), CPP_HIGH(), CPP_DBG() log被打印
§CPP_LOG_VERBOSE = 3,CPP_ERR(), CPP_HIGH(), CPP_DBG() , CPP_LOW() log都被打印
§默认CPP_LOG_VERBOSE = 1
adb shell setprop persist.camera.mct.debug 2
§表示MCT(mm-camera2/media-controller/mct)CDBG_ERROR(), CDBG_HIGH(), CDBG() 都会被打印
adb shell setprop persist.camera.stats.debug 2
§打开AEC ERR/HIGH/LOW log, 即AEC_ERR()/AEC_HIGH()/AEC_LOW() log会被打印
Bit 0-1: STATS_DEBUG_MASK_AEC_LOG
§Bit 2-3: STATS_DEBUG_MASK_AWB_LOG
§Bit 4-5: STATS_DEBUG_MASK_AF_LOG
§Bit 6-7: STATS_DEBUG_MASK_ASD_LOG
§Bit 8-9: STATS_DEBUG_MASK_AFD_LOG
§Bit 10-11: STATS_DEBUG_MASK_Q3A_LOG
§Bit 12-13: STATS_DEBUG_MASK_STATS_LOG
§Bit 14-15: STATS_DEBUG_MASK_IS_LOG
adb shell setprop persist.camera.global.debug 2
§表示HAL/Sensor/MCT/3A 所有ERROR/HIGH/LOW log都会被打印
Kernel log:
Sensor bring up and 常见问题的分析:
如果有高通lisence的同学也可以看看下面文档
参考文档:
80-NU323-2SC_D_Multimedia_Driver_Development_and_Bringup_Guide_-_Camera_Simplified_Chinese.pdf
80-NL239-33SC_D_Linux_Camera_Debugging_Guide_Simplified_Chinese.pdf
80-ND717-2BX_MSM8X10-MSM8X12_SOFTWARE_INTERFACE_FOR_OEMS.pdf