尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

MT65xx平台GC032A摄像头驱动移植与调试全记录

MT65xx平台GC032A摄像头驱动移植与调试全记录 简介本资源是面向嵌入式开发工程师与Android BSP工程师的MT65xx平台GC032A图像传感器定制驱动源码包解决原厂驱动在兼容性、功耗与图像质量方面的适配瓶颈适用于手机、行车记录仪及安防监控类终端的摄像头模块开发与调优。压缩包共9个文件72KB含6个头文件.h定义寄存器配置与接口协议、1个C文件.c实现核心初始化逻辑、1个CPP文件.cpp封装YUV数据流处理以及1张关键时序图.jpg直观展示GC032A上下电时序规范便于硬件协同验证。已有1110人学习下载资源结构聚焦HAL层与Kernel层联动设计包含gc032a_yuv驱动模块的完整移植路径与关键修改点注释可直接用于MT65xx平台Bring-up或性能调优显著提升拍照响应速度、降低图像噪点并增强弱光成像稳定性。 MT65xx平台这块板子在我手上躺了快两周一直卡在摄像头预览黑屏的问题上。最后翻出来一份名字特别长的驱动包MT65xx_GC032A_Driver_20170614_GC032A_GC032A_Drive才把问题彻底解决。趁热把整个移植和调试过程记下来免得下次换平台又从头踩一遍。GC032A是格科微GalaxyCore出品的一颗1/6.5英寸、30万像素级别的CMOS图像传感器最大输出640x48060fps单通道MIPI或者DVP接口都支持常见于低端功能机、门铃、老人机辅助摄像头、或者一些工业设备的次摄像头位置。MT65xx则是联发科当年主打中低端智能手机的SoC系列MT6572、MT6582、MT6589这些都算。把这两个凑一起就决定了这份驱动的工作场景在MTK Android平台的内核和HAL层里把GC032A这颗sensor正确点亮、出图、跑通预览。日期20170614说明这是一份2017年6月14日发布的驱动版本从路径里重复出现两次GC032A可以判断这应该是从某个完整的MTK工程里导出时打包脚本把rootdir和subdir两个路径字段拼在了一起。这种文件名在MTK驱动流出的包里非常常见不用觉得奇怪。文章后面会按我实际处理的顺序来写先拆解驱动包结构理清MTK camera驱动的整体框架然后逐段分析GC032A驱动核心代码的套路包括上电时序、I2C初始化序列、MIPI参数配置这些关键点接着就是完整的移植步骤从拷贝文件到编译烧录跑通最后是调试过程中遇到的经典问题比如进预览黑屏、颜色偏绿、帧率不对、以及MTK平台最常见的“sensor ID读不到”问题。1. 驱动包整体解构与MTK Camera框架梳理1.1 先从文件名读出项目背景MT65xx_GC032A_Driver_20170614_GC032A_GC032A_Drive这一串字符本质上透露了三个信息目标平台MT65xx系列也就是MT6572/MT6582这一代的联发科应用处理器目标sensorGC032A格科微低端国产sensor在当年出货量极大代码版本日期20170614也就是2017年6月14日左右的版本基线为什么日期重要因为MTK的camera驱动框架在2016年前后经历了一次比较大的调整。早期版本KK、L之前用的是cfg_setting_imgsensor.c这个老框架sensor的参数全部固化在一个大结构体里修改起来要通过CFG_IMG_SENSOR_GC032A这类宏来开关。到了MAndroid 6.0和NAndroid 7.0之后框架逐步变成了imgsensor独立目录的方式每个sensor一个文件夹内部包含xxx_mipi_raw.c、xxx_setting.c这类文件。20170614这个版本基本处于N这个时代驱动结构已经比较规范了。实际解压之后也和我的判断一致驱动包主要包含kernel和hal两个层面的代码。1.2 驱动包内部文件清单与作用标准的MTK GC032A驱动包打开后一般能看到下面这些关键文件kernel/drivers/misc/mediatek/imgsensor/src/mt6572/GC032A_mipi_raw.csensor主驱动文件包含了sensor的ID读取、初始化寄存器序列、曝光增益控制、预览/拍照切换等核心逻辑kernel/drivers/misc/mediatek/imgsensor/src/mt6572/GC032Amipiraw_Sensor.c部分版本会把sensor操作函数集单独拆出来这个文件会被上层调用kernel/drivers/misc/mediatek/imgsensor/inc/GC032Amipiraw_Sensor.h结构体、枚举、宏定义和常量声明hal/mediatek/camera/platform/mt6572/imgsensor/GC032A_mipi_raw.hHAL层对sensor的控制头文件如果包里有kd_imgsensor.c或kd_imgsensor.h的修改补丁那说明需要把GC032A注册进MTK的sensor列表里这部分在4.4和5.0以前的版本很常见。这里有一个比较坑的地方不同平台下的文件名后缀不一样有的叫GC032A_mipi_raw.c有的叫GC032A_mipi.c还有直接叫GC032A.c的。不能只看文件名就判断能不能用一定要打开文件看它头部注释里写的适用平台。1.3 MTK Sensor驱动整体框架MTK的camera驱动从底层往上分为三层Kernel层sensor驱动直接和硬件寄存器打交道负责通过I2C读写sensor内部的寄存器配置分辨率、帧率、曝光等参数。MTK通过imgsensor中间层抽象了不同sensor的差异每个sensor只需要实现固定的操作接口包括SensorInit、SensorOpen、SensorGetInfo、SensorGetResolution、SensorFeatureControl等。HAL层负责MTK Camera HAL和kernel层之间的交互主要工作是控制sensor的上电时序、MCLK时钟、复位脚的拉高拉低同时把上层下发的3A参数转换成sensor寄存器写入。底层驱动层包括GPIO、I2C、电源管理相关的代码sensor驱动本身运行在kernel空间通过i2c_transfer和sensor通信。刚开始写MTK camera驱动的人最容易绕晕的点在于sensor驱动里不仅仅有寄存器表格还包含了一套状态机。MTK的imgsensor框架用一个MSDK_SENSOR_INFO_STRUCT来记录sensor当前的工作状态包括sensor当前工作在预览模式还是拍照模式、当前分辨率是多少、是否已经上电等。切换分辨率、切换模组时都必须按照这个状态机走如果某个状态没更新到位跑起来就会出现各种诡异问题。2. 核心细节解析上电时序、I2C参数与初始化序列2.1 GC032A硬件特性与上电时序GC032A这颗sensor本身属于非常典型的国产低成本CMOS供电电压是AVDD2.8V、DOVDD1.8V、DVDD1.5V部分模组厂会把DVDD和DOVDD并在一起简化成两路供电甚至一路供电。这不是sensor本身的要求模组厂在软板上做了LDO合并驱动代码里不能用固定三路供电的写法。上电时序方面GC032A的 datasheet里明确要求先给AVDD和DOVDD上电然后等至少1ms再拉高PWDN或者叫RESET引脚之后MCLK时钟要稳定输出再过1ms左右才能通过I2C访问sensor。如果时序不对最典型的症状是I2C读ID失败或者读出来是0xFF、0x00这种非法值。在MTK平台上这个上电时序不是写在sensor驱动文件里的而是在HAL层的kd_sensorlist.c和camera_tool_custom.cpp里配置的。每个sensor对应一个kdCISensor结构体里面列出了sensor的上电顺序用POWER_ON、POWER_OFF、MCLK_ON这些宏依次排列。如果发现GC032A上电后ID读不到优先去查这个上电顺序是否和模组实际供电方式一致。2.2 sensor ID读取机制GC032A的sensor ID寄存器地址是0xF0默认值应该是0x9d。MTK的sensor驱动在SensorOpen阶段会调用GC032A_read_cmos_sensor连续读多个寄存器然后和GC032A_SENSOR_ID这个宏比较。对不上就返回ERROR上层会认为这颗sensor不存在然后走sensor_enumeration流程跳过去。这里有个容易被忽略的点老的MTK平台sensor ID读不到时日志里只会打一行kdCISensor2_Open id mismatch之类的信息并不会告诉你期望值和实际值。所以如果遇到ID为0的情况先用i2c工具直接在板上读一下0xF0地址的返回值确认sensor本身是活的再回头查驱动里定义的值对不对这个顺序不能反。我遇到过一种情况同一个GC032A模组在某个批次的板上ID正常在另一个批次板上ID变成0x03。后来查出来是MIPI的data lane和clock lane在软板上接反了。MIPI物理层对调不会烧sensor但会让sensor内部的寄存器映射错乱表现出来就是ID不对。这种问题只能通过飞线或者改layout解决。2.3 初始化寄存器序列的构成思路打开GC032A_mipi_raw.c最显眼的就是一个超长的数组GC032A_init_setting_30fps。这个数组里每一行是sensor_addr, sensor_value由MTK的宏{0xXX, 0xXX}包裹最后用{0xFF, 0xFF}结束。这个初始化序列看起来像一份神秘配方但实际上是可以归类理解的一堆寄存器段落。大致包含这几个部分0xF0~0xF3段sensor的系统控制寄存器设置sensor工作在normal模式还是standby模式以及是否开启内部LDO0x03~0x12段曝光和增益相关寄存器包括曝光行数、增益档位、是否开启自动曝光0x20~0x4F段分辨率输出窗口设置包括水平/垂直有效像素起始位置、输出宽度高度0x50~0x80段增益、白平衡、色彩矩阵相关0x82以后MIPI接口参数、输出格式、帧率控制结尾的0xFE通常是sensor的commit/latch寄存器写入后前面的配置才生效如果只是想点亮模组直接把这个数组完整写进去就行。但如果是做定制比如想改输出分辨率、改帧率、改翻转方向就必须定位到对应的寄存器位置不能直接在数组尾部追加否则大部分版本不会生效因为0xFE已经commit了。GC032A还有一个特点它的初始化序列分成GC032A_init_setting_30fps和GC032A_init_setting_25fps两套。当平台需要切换PAL/NTSC制式或者模组在不同场景下需要不同帧率时驱动会做切换。MTK框架里通过GC032A_setting_30fps和GC032A_setting_25fps这两个SENSOR_DRAMINFO结构体来管理这两套序列。实际项目里这两套序列的内容差异通常只在帧率相关寄存器上。2.4 曝光和增益的控制套路GC032A的曝光控制是典型的rolling shutter方式通过0x03曝光时间高字节、0x04曝光时间低字节来设置曝光行数。增益方面则分成模拟增益和数字增益分别对应不同的寄存器段。MTK的3A流程会通过SensorFeatureControl下发曝光和增益值sensor驱动里的GC032A_set_sensor_exposure函数负责把它们换算成具体的寄存器值然后写入。这里有一个非常重要的换算关系GC032A的行时间line length不是固定的而是和PCLK、MCLK、分辨率都相关。驱动里通常有一行注释说明当前配置下每行是多少微秒。比如我的板上MCLK是24MHz当前分辨率640x480line length是某个固定值那么一行的曝光时间就是像素时钟除以行长度。当曝光值超过最大行数时sensor会进入“跳过帧”模式也就是隔几行才曝光一行这样能延长最长曝光时间但帧率会降。常见表现是暗光环境下预览帧率从30fps掉到15fps甚至7fps这不是bug而是sensor的极限工作状态。3. 实操过程一份MT65xx GC032A驱动的完整移植记录3.1 移植前的环境确认我这次的目标平台是MT6572Android 7.0N系统。拿到驱动包之后第一步不是拷贝代码而是确认当前工程里有没有已经注册过其他sensor会不会和GC032A冲突。MTK平台同时支持多个sensor通过kd_imgsensor_list维护一个列表每个sensor在列表里的索引就是它的sensor id。GC032A的默认索引在kd_imgsensor_list里通常是7或者8具体看平台代码。打开kernel/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_list.h能看到一串类似GC032A_SENSOR_ID的宏定义。这个值的范围从1到16不等每个新sensor要占一个唯一的ID。如果包里的GC032A_SENSOR_ID和头文件里已有的宏冲突了一定要改掉否则系统在枚举sensor时会上报错误。确认无误后把整个GC032A_mipi_raw.c拷贝到kernel/drivers/misc/mediatek/imgsensor/src/mt6572/目录下把对应的.h文件拷贝到kernel/drivers/misc/mediatek/imgsensor/inc/目录下。3.2 修改配置文件MTK的sensor驱动不是拷贝过去就能编译的必须手动把新sensor加进编译系统。需要修改的文件主要是以下几个kernel/drivers/misc/mediatek/imgsensor/src/mt6572/Makefile这个文件里有一个obj-y xxx.o的列表。要在这里加上obj-y GC032A_mipi_raw.o。注意MTK的Makefile里经常用CONFIG_MTK_IMGSENSOR_GC032A这种宏来控制是否需要把某个sensor编译进去。如果默认没开这个宏需要去对应的Kconfig或者defconfig里打开否则Makefile里的规则不会生效。kernel/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_list.h在sensor列表里加上#include GC032A_mipi_raw.h和#define GC032A_SENSOR_ID 0xXX。HAL层alps/mediatek/custom/mt6572/hal/imgsensor/src/下的cfg_setting_imgsensor.c这个文件是MTK老版本HAL层sensor枚举的配置文件需要在这个结构体数组里注册GC032A的entry包括sensor名字、I2C地址、sensor输出格式等。在N版本上部分项目的这个文件已经被kd_sensorlist.c取代具体看代码里实际使用的是哪个。kernel/drivers/misc/mediatek/imgsensor/src/mt6572/kd_sensorlist.c注册GC032A的kdCISensor结构体里面指定SensorInit函数入口、I2C地址和sensor的访问方式。MTK老用户应该知道每次改完sensor列表必须把mediatek/custom/common/kernel/imgsensor/inc下的kd_camera_typedef.h里对应的宏同步改掉否则会出现编译过了但运行时不识别的情况。3.3 编译和烧录模块编译命令是MTK平台特有的不同版本略有差异。N版本上通常是在工程根目录下执行./mk -o TARGET_BUILD_VARIANTuserdebug mt6572 new或者单独编译kernel模块。如果只想编kernel和bootimage可以用./mk mt6572 kernel bootimage这种形式。这里提醒一下MTK的编译系统对大小写敏感文件名和Makefile里的.o名字必须完全一致。我踩过一次坑GC032A的文件名在makefile里被写成了小写g开头的GC032A_mipi_raw.o编译系统在Linux下找不到对应的.o文件报了一个很不起眼的链接错误排查了很久。烧录时一般只需要烧bootimage和kernel不用每次烧全量包。不过我自己的经验是第一次点亮camera时最好烧全量避免其他分区版本不一致影响摄像头链路。3.4 运行时验证烧完开机后通过adb shell进入系统查看/sys/devices/platform/mt_i2c.0/i2c-0/0-003c/之类的i2c设备节点是否存在确认sensor的I2C地址枚举正常。GC032A的I2C地址通常是0x217位地址换算成8位读写地址就是0x42/0x43。在MTK驱动里sensor的I2C地址在HAL层配置成0x21但驱动里i2c传输时使用的地址是左移一位后的值。如果这个地址不对I2C通信直接失败。之后再打开camera app看预览画面是否正常输出。如果黑屏立刻抓取kernel log确认sensor_id是否匹配再确认sensor是否已经初始化完成。4. 常见问题与排查技巧实录4.1 问题一进camera黑屏log里找不到sensor ID这个是最常见的问题原因多种多样。按我自己的排查顺序第一步确认MCLK有没有输出。MTK的MCLK由主控芯片直接供给sensor通常在mt_set_gpio_mode里配置。如果GPIO模式没配对MCLK就出不来用示波器量sensor端的MCLK引脚应该能看到一个稳定的24MHz左右的方波。第二步确认sensor的上电时序。用示波器量AVDD、DOVDD、DVDD三个电源轨的上电顺序以及PWDN/RESET引脚的时序。GC032A要求电源稳定后至少等1ms再拉高PWDN如果时序反了sensor内部寄存器会处于不确定状态。第三步确认I2C通信正常。在MTK平台上有时候用示波器同时看SDA和SCL确认sensor有ACK回包。如果I2C没ACK大概率是I2C地址配置错了或者sensor供电有问题。4.2 问题二预览画面颜色偏绿或偏紫画面颜色不对先排除sensor输出的色彩格式和数据线接法问题。GC032A的MIPI接口支持RAW8、RAW10两种输出。MTK平台的sensor驱动里SENSOR_OUTPUT_FORMAT这个宏决定了HAL层按照什么格式处理sensor数据。如果sensor输出的是RAW10驱动里却配置成RAW8画面就会出现明显的绿色色偏因为高两位数据被截断了。另外很多GC032A模组的MIPI lane顺序和标准的参考设计不一样。lane mapping不对时画面会出现明显的条纹或者颜色异常。处理方式是检查HAL层的lane配置是否和模组实际走线一致。4.3 问题三预览卡顿帧率达不到30fps帧率达不到目标优先检查初始化序列里是否配置了正确的帧率。GC032A同时有30fps和25fps两套初始化序列如果没有正确切换就会出现使用25fps序列跑30fps的情况这会导致sensor的实际输出帧率只有标称的5/6预览就会卡。另一种可能MIPI的lane数配置错了。GC032A的MIPI接口支持1-lane和2-lane两种模式。如果模组实际出图用的是2-lane驱动里只配了1-lane带宽不够帧率会直接减半。4.4 问题四sensor能出图但拍照出来的照片曝光不对照片曝光不对多半是曝光时间换算出的寄存器值和sensor的实际行时间不匹配。MTK的3A算法会持续向sensor发送曝光增益指令但如果驱动里的sensor_max_line_length、sensor_min_line_length这些参数配置不对3A算法算出的曝光值就落在错误的区间画面要么过曝要么欠曝。调试这个问题的快捷方法关掉3A直接在驱动里写死一组曝光增益寄存器值看画面亮度是否正常。如果写死之后正常说明问题出在3A和sensor驱动参数匹配上而不是sensor本身有问题。4.5 问题五驱动编译报错找不到头文件MTK的sensor驱动对头文件路径依赖很重。GC032A_mipi_raw.c的头部通常会include一串路径比如#include kd_camera_typedef.h、#include kd_imgsensor.h、#include kd_imgsensor_define.h。如果这些头文件的路径在编译环境里没被包含编译就会报错。一个非常隐蔽的坑是从别的工程拷贝驱动文件时把imgsensor的inc目录整个覆盖了导致新工程里某些头文件版本不对编译不报错但运行出错。所以拷贝驱动时我只拷贝新增文件不碰工程原有的公共头文件。4.6 调试日志的开启技巧MTK平台的sensor驱动log开关在kd_imgsensor.h里通过#define DEBUG和#define VDBG这两个宏控制。默认关闭需要手动打开编译后重新烧录。打开后sensor的每次I2C读写操作都会打印在kernel log里虽然刷屏很严重但调试寄存器问题非常有用。内核级的printk在默认的kernel log level下可能看不到需要先通过echo 8 /proc/sys/kernel/printk把控制台级别提高。5. 从MTK驱动到通用嵌入式平台的移植思路5.1 驱动逻辑的跨平台通用性写这份驱动移植记录的时候我顺手在STM32上跑了一个类似的GC032A裸机驱动那感受完全不同。MTK框架下我们是在一个高度集成、高度抽象的系统里调用sensor所有复杂的上电和GPIO操作都被封装好了。而在STM32上GPIO操作、MCLK生成、I2C时序、MIPI接收每一件事都得自己手动控制。虽然平台不同但GC032A驱动的核心逻辑完全一致上电时序要严格遵循datasheetI2C读写寄存器要通过地址和数据两个字节完成初始化序列要一条条执行。所以如果你的项目不是MTK平台也不用从头写把MTK驱动里的GC032A_init_setting_30fps数组原封不动拿过来再根据新平台的I2C接口封装一下读写函数基本上就能跑起来。5.2 裸机平台需要额外处理的细节在STM32平台上移植GC032A最大的坑是MCLK精度和幅值。GC032A的MCLK要求6MHz~27MHz之间推荐24MHz时钟抖动不能太差。STM32的定时器输出PWM虽然能产生24MHz但抖动偏大可能影响sensor内部PLL的稳定性。更稳妥的做法是用外部有源晶振单独生成24MHz时钟供sensor使用。另外DVP接口的PCLK同步也是裸机平台的难点。GC032A在DVP模式下输出PCLK、VSYNC、HSYNC和8位数据线。MCU需要用外部中断捕捉VSYNC和HSYNC再配合DMA把PCLK边缘的数据搬进内存。如果PCLK频率超过MCU的处理能力画面就会出现撕裂。5.3 一个比较小众的调试技巧用逻辑分析仪抓I2C不管是MTK还是STM32平台如果I2C通信时好时坏别急着改代码先用逻辑分析仪抓一次I2C波形。GC032A的I2C从地址是0x21读写操作时第一个字节是0x42或0x43。如果抓到的波形里地址字节和预期不符说明代码里I2C地址左移右移的处理有误。MTK驱动里有一种情况HAL层配置的是7位地址0x21但底层I2C驱动内部又做了左移最终发送到总线上的地址变成了0x84。这种地址处理的两层逻辑很容易出错逻辑分析仪是最直接的排查手段。6. 关于这份驱动包的最终评价与使用建议GC032A是一个非常成熟的sensorMTK的驱动代码也早已在千万级出货量的产品上验证过。如果你的项目正好是MT6572/MT6582这类老平台这颗驱动基本上就是拿来即用的。关于20170614这个版本我个人判断它是基于Android 7.0N的某个正式量产版本导出的比早先的4.4/5.0版本改动主要集中在MIPI参数适配和初始化序列微调上。如果你手里的工程是Android 5.0或5.1直接拿这个包可能会遇到一些API差异比如kdSetClockDiv、kdCISensorPipeEnable这类函数的参数定义有变化。这种问题的解决办法不是去改sensor驱动而是对照新老版本的kd_imgsensor.h差异把公共头文件同步过来。最后再分享一个小技巧MTK驱动包里的gc032a_mipi_raw.c文件顶部通常会有一段注释记录了这颗sensor在哪个平台、哪个项目上验证过以及sensor的MCLK频率是多少。拿驱动前先看这段注释能少走很多弯路。我这次就是因为注释里写的是24MHz MCLK和我板上的实际配置一致省去了很多排查时间。如果需要把GC032A用在新的非MTK平台比如全志、瑞芯微或者一些MCU平台这份MTK驱动里的初始化序列和寄存器说明依然有非常高的参考价值。sensor本身的寄存器定义是固定的变的只是主控平台的I2C/GPIO/MIPI接口封装方式。把MTK驱动里的初始化序列完整移植过去再根据新平台的接口规范改写底层的读写函数一般都能在半天内点亮出图。本文还有配套的精品资源点击获取
返回列表