1. MTK平台Camera Sensor移植全景解析
在MTK Android平台上移植一颗新的Camera Sensor,远不止是写个驱动那么简单。以工业安防领域常用的Sony IMX335(5MP MIPI RAW)为例,整个移植过程涉及内核层、设备层、HAL层共10多个配置目录的协同修改。这些配置文件就像散落的拼图碎片,漏掉任何一块都会导致相机功能异常,而系统给出的错误提示往往与实际问题毫不相关。
我经历过无数次深夜调试,发现90%的问题都出在配置文件的遗漏或错误上。比如最常见的现象:sensor ID读取正常,但相机服务就是无法启动;或者更隐蔽的问题——AE(自动曝光)算法失控导致画面忽明忽暗。这些问题背后,往往是一个被忽略的metadata目录,或者电源时序中某个电压值的配置错误。
2. 移植前的准备工作
2.1 硬件环境确认
在开始移植前,必须确保硬件环境符合sensor要求:
-
电源规格验证:
- IMX335需要三路供电:DOVDD 1.8V、DVDD 1.2V、AVDD 2.9V
- 特别注意:AVDD 2.9V不是常见的2.8V,必须使用专用LDO
- 建议用示波器测量各路上电时序和纹波(<50mV)
-
接口信号检查:
bash复制# 通过GPIO dump工具确认复位信号和电源使能信号 adb shell "echo 1 > /sys/kernel/debug/gpio" adb shell cat /sys/kernel/debug/gpio- MIPI CSI时钟频率应为456MHz(4-lane配置)
- I2C信号需用逻辑分析仪确认无毛刺
-
模组物理参数:
- 确认镜头光圈值(如F2.4)
- 测量实际焦距(如3.5mm)
- 记录sensor物理尺寸(1/2.8英寸)
2.2 软件基础环境
MTK平台不同版本路径差异对照表:
| 组件 | Android 9路径 | Android 11路径 |
|---|---|---|
| Kernel驱动 | kernel-4.14/drivers/misc/mediatek/imgsensor | kernel-5.10/drivers/misc/mediatek/imgsensor |
| HAL层配置 | vendor/mediatek/proprietary/custom/mt6765/hal | vendor/mediatek/proprietary/custom/mt6873/hal |
| Device配置 | device/mediatek/mt6765 | device/mediatek/mt6873 |
提示:建议先准备好参考sensor的完整代码(如imx258),后续移植可以基于此修改
3. 内核层移植详解
3.1 Sensor ID与驱动注册
在kd_imgsensor.h中定义sensor基本信息:
c复制// 注意:ID高位是厂家代码,低位是型号代码
#define IMX335_SENSOR_ID 0x0335 // Sony厂家代码0x01,型号0x35
#define SENSOR_DRVNAME_IMX335_MIPI_RAW "imx335mipiraw"
// 像素时钟计算公式:
// pclk = linelength * framelength * fps
// IMX335@30fps: 2200 * 1125 * 30 = 74.25MHz
#define IMX335_MAX_PCLK 74250000
驱动注册需要修改两个关键文件:
imgsensor_sensor_list.h中添加函数声明:
c复制extern MUINT32 IMX335_MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
imgsensor_sensor_list.c中添加到驱动数组:
c复制struct IMGSENSOR_SENSOR_LIST kdSensorList[] = {
{IMX335_SENSOR_ID, SENSOR_DRVNAME_IMX335_MIPI_RAW, IMX335_MIPI_RAW_SensorInit},
/* 其他sensor... */
};
3.2 电源时序配置
imgsensor_cfg_table.c中的电源时序必须严格按datasheet编写:
c复制static struct IMGSENSOR_POWER_SEQ power_sequence_imx335[] = {
{RST, Vol_Low, 0}, // 复位拉低
{DOVDD, Vol_1800, 0}, // 数字IO电源1.8V
{AVDD, Vol_2900, 0}, // 模拟电源2.9V(关键!)
{DVDD, Vol_1200, 1}, // 数字核心1.2V
{SensorMCLK, Vol_High, 1}, // 时钟使能
{RST, Vol_High, 2} // 复位释放
};
常见电源问题排查方法:
- 测量各电源电压是否达标
- 检查上电时序是否符合要求
- 确认电源使能GPIO是否正确映射
3.3 I2C通信实现
I2C驱动需要特别注意以下几点:
c复制static struct imgsensor_i2c_addr i2c_addr_imx335 = {
.i2c_addr_table = {0x34, 0x6C, 0xff}, // 8-bit写地址
.i2c_id = 0x01, // I2C控制器编号
.i2c_speed = 400, // 400kHz标准模式
};
// 寄存器读写函数示例
static kal_uint16 read_cmos_sensor(kal_uint32 addr)
{
kal_uint16 get_byte = 0;
char pusendcmd[2] = {(char)(addr >> 8), (char)(addr & 0xFF)};
iReadI2C(pusendcmd, 2, (u8 *)&get_byte, 1, i2c_addr);
return get_byte;
}
调试技巧:如果I2C通信失败,先用i2c-tools测试:
bash复制adb shell i2cdetect -y 1 # 扫描I2C设备 adb shell i2cget -f -y 1 0x34 0x0000 w # 读取sensor ID
4. HAL层配置全解析
4.1 ProjectConfig.mk关键配置
必须确保以下四个变量都正确配置:
makefile复制# 主sensor配置
CUSTOM_HAL_IMGSENSOR = imx335_mipi_raw
CUSTOM_HAL_MAIN_IMGSENSOR = imx335_mipi_raw
CUSTOM_KERNEL_IMGSENSOR = imx335_mipi_raw
CUSTOM_KERNEL_MAIN_IMGSENSOR = imx335_mipi_raw
# 辅助配置
CUSTOM_HAL_LENS = dummy_lens # 定焦镜头配置
CUSTOM_KERNEL_LENS = dummy_lens
4.2 四大HAL目录详解
4.2.1 3A参数目录(imgsensor/ver1/imx335mipiraw/)
包含约50个调优参数文件,主要分为:
- AE参数:
ae_feature_imx335mipiraw.h - AWB参数:
awb_feature_imx335mipiraw.h - AF参数:
af_feature_imx335mipiraw.h - ISP调优:
isp_tuning_imx335mipiraw.h
关键参数示例:
c复制// ae_feature_imx335mipiraw.h
static struct ACDK_AE_FEATURE_STRUCT ae_feature_imx335 = {
.bEnableSmoothAE = KAL_TRUE,
.u4AEMode = AE_MODE_AUTO,
.u4MinExposureGain = BASEGAIN * 16, // 最小增益1x
.u4MaxExposureGain = BASEGAIN * 64, // 最大增益4x
.u4MinShutter = 1000, // 最小快门1ms
.u4MaxShutter = 33000 // 最大快门33ms
};
4.2.2 平台metadata目录(imgsensor_metadata/imx335mipiraw/)
包含6个关键文件:
config_metadata_imx335mipiraw.h- 静态特性配置config_metadata_tag_imx335mipiraw.h- 标签定义config_metadata_tag_custom_imx335mipiraw.h- 自定义标签
关键配置示例:
c复制// 分辨率配置必须准确
static const int32_t ACTIVE_ARRAY_WIDTH = 2592;
static const int32_t ACTIVE_ARRAY_HEIGHT = 1944;
static const float PHYSICAL_SIZE_WIDTH = 4.536f; // mm
static const float PHYSICAL_SIZE_HEIGHT = 3.416f; // mm
4.2.3 Feature table目录(sendepfeature/imx335mipiraw/)
只有一个文件但很关键:
sendep_sensor_feature_imx335mipiraw.h
内容示例:
c复制static struct SENSOR_FEATURE_STRUCT feature_table_imx335[] = {
{SENSOR_FEATURE_SET_ESHUTTER, 0, NULL},
{SENSOR_FEATURE_SET_GAIN, 0, NULL},
{SENSOR_FEATURE_SET_DUAL_GAIN, 0, NULL},
// ...约20个特性配置
};
4.2.4 Common metadata目录(最易遗漏!)
路径:common/hal/imgsensor_metadata/sensor/imx335mipiraw/
必须包含的文件:
config_static_metadata.sensor.imx335mipiraw.h
内容框架:
c复制namespace NSCam {
namespace NSFeature {
struct SensorStaticInfoCOMMON {
// 约200行的sensor特性描述
const int32_t sensitivityRange[2] = {100, 1600};
const int64_t exposureTimeRange[2] = {1000000, 33000000}; // ns
// ...
};
} // NSFeature
} // NSCam
血泪教训:缺少这个文件会导致camerahalserver不断崩溃重启!
5. 参数调优实战技巧
5.1 分辨率与镜头匹配
必须确保以下参数协调一致:
-
Active Array:
c复制#define IMX335_ACTIVE_WIDTH 2592 #define IMX335_ACTIVE_HEIGHT 1944 -
Physical Size:
c复制#define IMX335_PHYSICAL_WIDTH 4536 // 单位um #define IMX335_PHYSICAL_HEIGHT 3416 -
镜头参数:
c复制static const float LENS_APERTURE = 2.4f; // F值 static const float LENS_FOCAL_LENGTH = 3.5f; // 焦距(mm)
5.2 定焦sensor特殊配置
工业相机通常使用定焦镜头,需要关闭AF功能:
-
ProjectConfig.mk:
makefile复制
CUSTOM_HAL_LENS = dummy_lens CUSTOM_KERNEL_LENS = no_lens -
AF参数:
c复制static struct AF_FEATURE_STRUCT af_feature_imx335 = { .bEnableAF = KAL_FALSE, // 关闭自动对焦 .i4AFMode = AF_MODE_OFF, .i4FixedFocus = 0, // 固定焦距 };
5.3 AE算法调优
IMX335的曝光计算比较特殊:
c复制// 曝光计算公式:
// 实际曝光行数 = VMAX寄存器值 - SHR0寄存器值
// 必须确保VMAX >= SHR0 + 1
static void set_shutter(kal_uint16 shutter)
{
kal_uint16 vmax = shutter + 1;
write_cmos_sensor(0x0340, (vmax >> 8) & 0xFF); // VMAX_H
write_cmos_sensor(0x0341, vmax & 0xFF); // VMAX_L
write_cmos_sensor(0x0202, (shutter >> 8) & 0xFF);// SHR0_H
write_cmos_sensor(0x0203, shutter & 0xFF); // SHR0_L
}
经验:必须使用group hold功能,确保VMAX和SHR0原子更新
6. 调试技巧与问题排查
6.1 常见问题速查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| I2C通信失败 | 1. 地址错误 2. 电源未开启 3. 时序问题 |
1. 用i2cdetect扫描 2. 测量电源电压 3. 检查上电时序 |
| Sensor ID读取为0 | 1. 复位信号异常 2. 时钟未使能 |
1. 检查reset GPIO 2. 测量MCLK信号 |
| HAL服务崩溃 | 1. metadata缺失 2. 参数越界 |
1. 检查common metadata目录 2. 查看logcat崩溃日志 |
| 画面花屏 | 1. MIPI配置错误 2. 时钟抖动 |
1. 检查lane数量和速率 2. 测量时钟质量 |
6.2 关键日志分析
-
Kernel日志:
bash复制adb shell dmesg | grep "imgsensor"正常应看到:
code复制[imgsensor] imx335_mipi_raw_SensorInit OK [imgsensor] IMX335 detected ID:0x0335 -
HAL日志:
bash复制adb logcat | grep -E "CamHal|IMGSENSOR"重点关注:
- Sensor初始化完成日志
- 3A算法启动日志
- 任何ERROR级别的报错
6.3 实测工具推荐
-
I2C调试:
bash复制adb shell i2cdump -f -y 1 0x34 # 查看sensor寄存器 -
信号测量:
- 使用示波器检查:
- MIPI时钟和数据眼图
- 电源纹波
- 复位信号时序
- 使用示波器检查:
-
图像测试:
bash复制
adb shell am start -n com.android.camera2/com.android.camera.CameraActivity
7. 移植检查清单(终极版)
内核层:
- [ ]
kd_imgsensor.h中定义SENSOR_ID和DRVNAME - [ ]
imgsensor_sensor_list.h/c注册驱动函数 - [ ]
imgsensor_cfg_table.c配置电源时序 - [ ] defconfig中添加sensor名称
- [ ] 驱动代码同时放在v1和v1_1目录
设备层:
- [ ]
device/mediatek/common/kernel-headers/kd_imgsensor.h同步更新
HAL层:
- [ ] ProjectConfig.mk四个IMGSENSOR变量
- [ ] 创建imgsensor/ver1/imx335mipiraw/目录及参数文件
- [ ] 创建imgsensor_metadata/imx335mipiraw/目录及文件
- [ ] 创建sendepfeature/imx335mipiraw/目录及文件
- [ ] 创建common/hal/imgsensor_metadata/sensor/imx335mipiraw/目录(最易漏!)
- [ ]
sensorlist.cpp注册sensor - [ ]
cfg_setting_imgsensor.cpp配置MCLK等参数
参数验证:
- [ ] 分辨率参数与实际一致
- [ ] 镜头参数正确(定焦/变焦)
- [ ] 物理尺寸精确到um级
- [ ] AE算法参数适配sensor特性
移植完成后,建议进行至少24小时老化测试,特别关注:
- 长时间运行后的温升情况
- AE稳定性(无闪烁或跳动)
- 图像质量一致性