Sensor移植指南¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 07/16/2024 |
1. 环境准备¶
开始Porting之前,请先确保Sensor的接线没有问题,MIPI Sensor接线可以参考这篇文档 SENSOR 使用参考,在不同CHIP上基本的原理也相同
首先需要确认需求,包含Sensor的分辨率,帧率,像素位宽,MIPI Lane数量,mclk 频率,将需求给到厂商,并让其提供数据手册与初始化表。
2. Sensor驱动程序移植的文件名规范¶
为了规范所有Sgs Sensor Driver 名称的命名,我们制定了Sgs Sensor Driver 移植规范,在移植Sensor driver时请遵循以下说明。
2.1. Sensor驱动名称规范¶
drv_ss_<Sensor Type>_<Sensor interface>_<others>.c
| 参数 | 说明 |
|---|---|
| Sensor Type | Sensor命名,例如 imx307、imx415。建议使用小写。 |
| Sensor interface | Sensor接口类型,例如:mipi、lvds,但parallel可以忽略不填写。建议使用小写。 |
| others | 如无其他补充,可忽略。建议使用小写。 |
3. Sensor移植相关硬件知识¶
本文档介绍了如何移植Sgs Sensor驱动,包括硬件基础知识、Sgs的软件控制Sensor API(sensor handle)、Sensor接口API(Sensor-IF)以及软件移植流程。本文档以imx415的Sensor驱动为例,您可以按照本文档中的说明逐步完成Sensor移植。
首先我们介绍一下硬件的相关知识以及相应的源代码,以便于大家更容易的理解。
3.1. Sensor电源顺序¶
检查Sensor数据表中的通电顺序规范。请遵循以下电源顺序 1.1V > 1.8V > 2.9V,这是 imx415 Sensor数据表的要求。

图 1:IMX415 Sensor电源顺序规范
表1:IMX415 Sensor电源序列时序表

3.1.1 对应源代码¶
可以通过Sensor驱动句柄初始化函数中的“handle->pCus_sensor_poweron”来控制Sensor上电和复位引脚,如果需要修改Sensor上电时序,请检查Sensor特性和硬件设计。
static int pCus_poweron(ms_cus_sensor *handle, u32 idx) {
ISensorIfAPI *sensor_if = &handle->sensor_if_api;
//Sensor上电顺序
sensor_if->PowerOff(idx, handle->pwdn_POLARITY); //Powerdn 拉低
sensor_if->Reset(idx, handle->reset_POLARITY); // Rst 拉低
sensor_if->SetIOPad(idx, handle->sif_bus, handle->interface_attr.attr_mipi.mipi_lane_num);
sensor_if->SetCSI_Clk(idx, CUS_CSI_CLK_216M);
sensor_if->SetCSI_Lane(idx, handle->interface_attr.attr_mipi.mipi_lane_num, ENABLE);
sensor_if->SetCSI_LongPacketType(idx, 0, 0x1C00, 0);
if (handle->interface_attr.attr_mipi.mipi_hdr_mode == CUS_HDR_MODE_SONY_DOL)
sensor_if->SetCSI_hdr_mode(idx, handle->interface_attr.attr_mipi.mipi_hdr_mode, 1);
sensor_if->PowerOff(idx, !handle->pwdn_POLARITY);
//Sensor板 PWDN 启用,1.8V 和 2.9V 需要 30ms 后拉高
SENSOR_MSLEEP(31);
sensor_if->Reset(idx, !handle->reset_POLARITY);
SENSOR_UDELAY(1);
sensor_if->MCLK(idx, 1, handle->mclk);
SENSOR_DMSG("Sensor Power On finished\n");
return SUCCESS;
}
注意:
以下是 Sgs Sensor板电源电路原理图。上电后,1.1V、1.8V、2.9V 电源将被拉高。首先是 1.1V,然后是 1.8V 和 2.9V,您可以使用示波器在Sensor板上测量它。

图 2:IMX415 Sensor电源电路
3.2. Sensor I2C 从机地址检查¶
Sgs SoC 需要通过 I2C 与Sensor通信,请先检查Sensor I2C 从机地址。
表 2:IMX415 Sensor从机 ID 表

注意:
检查 I2C 从机模式选项的Sensor板原理图。

图 3:IMX415 Sensor板 I2C 从机模式
3.2.1 对应源代码¶
Sensor驱动I2C设置中宏定义
////////////////////////////////////
// I2C Info //
////////////////////////////////////
#define SENSOR_I2C_ADDR 0x34 //I2C slave address
#define SENSOR_I2C_SPEED 300000 //I2C speed, 60000~320000
#define SENSOR_I2C_LEGACY I2C_NORMAL_MODE
#define SENSOR_I2C_FMT I2C_FMT_A16D8 //CUS_I2C_FMT_A8D8,
CUS_I2C_FMT_A8D16,
CUS_I2C_FMT_A16D8,
CUS_I2C_FMT_A16D16
注意: I2C 控制接口的Sensor IF 位于handle初始函数中
handle->i2c_cfg.mode = SENSOR_I2C_LEGACY; //(CUS_ISP_I2C_MODE) FALSE;
handle->i2c_cfg.fmt = SENSOR_I2C_FMT; //CUS_I2C_FMT_A16D8;
handle->i2c_cfg.address = SENSOR_I2C_ADDR; //0x34;
handle->i2c_cfg.speed = SENSOR_I2C_SPEED; //未实现,请配置dts或 sysdesc
3.3. Sensor MCLK 支持¶
每个Sensor可以支持不同的MCLK,我们可以提供的MCLK列表如下,您可以从Sensor供应商提供的初始化设置中找到Sensor对应的MCLK,宏定义中的Sensor MCLK设置
////////////////////////////////////
// MCLK Info //
////////////////////////////////////
/******* Support MCLK List *******
* CUS_CMU_CLK_27MHZ / CUS_CMU_CLK_21P6MHZ / CUS_CMU_CLK_12MHZ,
* CUS_CMU_CLK_5P4MHZ / CUS_CMU_CLK_36MHZ / CUS_CMU_CLK_54MHZ,
* CUS_CMU_CLK_43P2MHZ / CUS_CMU_CLK_61P7MHZ / CUS_CMU_CLK_72MHZ,
* CUS_CMU_CLK_48MHZ / CUS_CMU_CLK_24MHZ / CUS_CMU_CLK_37P125MHZ,
******End of Support MCLK List*******/
#define Preview_MCLK_SPEED CUS_CMU_CLK_27MHZ
3.3.1 对应源代码¶
在handle初始函数中的Sensor MCLK 控制接口:
////////////////////////////////////
// set mclk //
// please check pCus_poweron //
////////////////////////////////////
sensor_if->MCLK(idx , ENABLE, UseParaMclk(SENSOR_DRV_PARAM_MCLK()));
4. Sensor移植相关软件控制¶
在介绍了硬件相关知识和相应的源代码之后,这部分我们将介绍Sgs的软件控制API(Sensor handle)和Sensor接口API(Sensor-IF)。
4.1. Sensor驱动支持模式定义¶
Sgs Sensor驱动可以提供多种注册Sensor支持的行为模式,下面我们将针对这些注册Sensor支持的行为模式进行讲解,您可以在路径中查看更多宏定义的详细信息:
driver/SensorDriver/drv/inc/drv_sensor_common.h
4.1.1 pure linear、parallel sensor和2-frame HDR的宏定义¶
#define SENSOR_DRV_ENTRY_IMPL_END_EX (Name, LinearEntry, HdrSefEntry,
HdrLefEntry, PrivateDataType)
表 3:Sensor驱动程序“SENSOR_DRV_ENTRY_IMPL_END_EX”定义
| 参数 | 描述 |
|---|---|
| Name | Sensor名称及支持模式 |
| LinearEntry | Sensor线性模式handle初始函数 |
| HdrSefEntry | Sensor HDR 短曝光handle初始函数 |
| HdrLefEntry | Sensor HDR 长曝光handle初始函数 |
| PrivateDataType | Sensor私有数据类型 |
4.1.2 3-frame HDR的宏定义¶
#define SENSOR_DRV_ENTRY_IMPL_END_EX2 (Name, LinearEntry, HdrSefEntry,
HdrLefEntry, HdrMefEntry,
PrivateDataType)
表4:Sensor驱动程序“SENSOR_DRV_ENTRY_IMPL_END_EX2”定义
| 参数 | 描述 |
|---|---|
| Name | Sensor名称及支持模式 |
| LinearEntry | Sensor线性模式handle初始函数 |
| HdrSefEntry | Sensor HDR 短曝光handle初始函数 |
| HdrLefEntry | Sensor HDR 长曝光handle初始函数 |
| HdrMefEntry | Sensor HDR 中曝光handle初始函数 |
| PrivateDataType | Sensor私有数据类型 |
例如IMX415 sensor支持线性及2-frame HDR模式,可参考IMX415 sensor驱动,将其填入“SENSOR_DRV_ENTRY_IMPL_END_EX”定义中。
SENSOR_DRV_ENTRY_IMPL_END_EX( IMX415_HDR,
cus_camsensor_init_handle,
cus_camsensor_init_handle_hdr_dol_sef,
cus_camsensor_init_handle_hdr_dol_lef,
imx415_params
);
4.2. Sensor驱动handle函数介绍¶
接下来我们在 linear 和 HDR handle初始函数中对 handle API 进行介绍和讲解,我们可以通过 handle API 来控制、设置或者读取 sensor 的任意状态,这里以 imx415 的 sensor 驱动为例,大家可以按照本文档中的说明,逐步完成 linear 和 HDR 模式的 sensor 移植。
4.2.1 Sensor型号ID API的handle¶
设置Sensor名称和模式信息
表 5:handle的型号名称API列表
| 参数 | 描述 | 注意 |
|---|---|---|
| handle ->strSensorStreamName | 为 libcamera 用户注册设置Sensor模型 | MIPI: IMX415_MIPI PARALLEL: IMX323_PARL HDR: IMX415_MIPI_HDR_SEF, IMX415_MIPI_HDR_LEF |
4.2.2 I2C的handle¶
设置 I2C 硬件以进行配置
表 6:handle的I2C配置列表
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->i2c_cfg.mode | 注册 I2C 模式 | I2C_NORMAL_MODE /Sensor驱动程序只能使用 I2C_NORMAL_MODE/ I2C_LEGACY_MODE /请勿使用/ |
| handle->i2c_cfg.fmt | 注册设置 I2C 地址位和数据长度的格式。 | I2C_FMT_A8D8, I2C_FMT_A16D8, I2C_FMT_A8D16, I2C_FMT_A16D16, I2C_FMT_END /保留/ /Ex I2C_FMT_A16D8 表示 16 位地址、8 位数据/ |
| handle->i2c_cfg.address | 注册设置Sensor I2C 从机地址,Sgs SoC 支持 8 位从机地址 | 从Sensor数据表检查 |
| handle->i2c_cfg.speed | 注册设置Sensor最大 I2C 速度(未使用) | 通过 dts 或 sysdesc 进行 I2C 速度配置 |
4.2.3 Sensor解析能力处理¶
设置Sensor支持并实现输出图像信息。
表 7:Sensor解析能力列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->video_res_supported.num_res | 注册设置Sensor支持分辨率 | |
| handle->video_res_supported.ulcur_res | 注册设置Sensor当前分辨率 | 默认值:0 |
| handle->video_res_supported.res[n].u16width | 注册设置Sensor支持宽度 | |
| handle->video_res_supported.res[n].u16height | 注册设置Sensor支持高度 | |
| handle->video_res_supported.res[n].u16max_fps | 注册设置Sensor支持预览最大fps | |
| handle->video_res_supported.res[n].u16min_fps | 注册设置Sensor支持预览最低fps | |
| handle->video_res_supported.res[n].u16crop_start_x | 注册设置 VIF 裁剪Sensor输出图像 X 的起点 | |
| handle->video_res_supported.res[n].u16crop_start_y | 注册设置 VIF 裁剪Sensor输出图像 Y 的起点 | |
| handle->video_res_supported.res[n].u16OutputWidth | 注册设置VIF输出有效像素 | |
| handle->video_res_supported.res[n].u16OutputHeight | 注册设置 VIF 输出有效线 | |
| handle->video_res_supported.res[n].strResDesc | 注册设置Sensor分辨率和fps字符串 | CamOsStrncpy(handle->video_res_supported.res[i].strResDesc, “1920x1080@30fps”, CamOsStrlen(1920x1080@30fps)); |
| handle->video_res_supported.res[n].u16MinFrameLengthLine | 注册获取Sensor每行的最小帧长度 | |
| handle->video_res_supported.res[n].u16RowTime | 注册获取Sensor每行的时间 | |
| handle->video_res_supported.res[n].u16PixelSize | 注册获取线的Sensor像素大小 |
4.2.4 Sensor信息处理¶
设置Sensor信息以进行配置
表 8:Sensor信息接口注册列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->sif_bus | 注册设置Sensor接口总线类型 | SENSOR_IFBUS_TYPE CUS_SENIF_BUS_PARL = 0, /Sensor数据总线为 parallel/ CUS_SENIF_BUS_MIPI = 1, /*Sensor数据总线为 mipi */ CUS_SENIF_BUS_BT601 = 2, CUS_SENIF_BUS_BT656 = 3, CUS_SENIF_BUS_BT1120 = 4, |
| handle->data_prec | 注册设置Sensor输出原始数据精度 | SENSOR_DATAPREC CUS_DATAPRECISION_8 = 0, /原始数据精度8位/ CUS_DATAPRECISION_10 = 1, /原始数据精度10位/ CUS_DATAPRECISION_16 = 2, /原始数据精度16位/ CUS_DATAPRECISION_12 = 3, /原始数据精度12位/ CUS_DATAPRECISION_14 = 4, /原始数据精度14位/ |
| handle->bayer_id | 注册设置Sensor bayer起始id | SENSOR_BAYERID CUS_BAYER_RG = 0、 CUS_BAYER_GR、 CUS_BAYER_BG、 CUS_BAYER_GB、 |
| handle->RGBIR_id | 注册设置Sensor RGB-IR起始id 如果 不是 RGB-IR Sensor,请设置*CUS_RGBIR_NONE* |
SENSOR_RGBIRID CUS_RGBIR_NONE = 0, CUS_RGBIR_R0 = 1, CUS_RGBIR_G0 = 2, CUS_RGBIR_B0 = 3, CUS_RGBIR_G1 = 4, CUS_RGBIR_G2 = 5, CUS_RGBIR_I0 = 6, CUS_RGBIR_G3 = 7, CUS_RGBIR_I1 = 8 |
| handle->snr_pad_mode | 注册Sensor主从模式 | CUS_SENSOR_MASTER_MODE = 0, CUS_SENSOR_SLAVE_MODE = 1, |
4.2.5 mipi 信息handle¶
设置 mipi 以进行配置
表9:mipi Sensor接口注册列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->interface_attr.attr_mipi.mipi_lane_num | 注册设置 MIPI 通道数 | 默认值:4 |
| handle->interface_attr.attr_mipi.mipi_data_format | 注册设置MIPI数据格式 | CUS_SEN_INPUT_FORMAT_YUV422, CUS_SEN_INPUT_FORMAT_RGB, |
| handle->interface_attr.attr_mipi.mipi_yuv_order | 注册设置MIPI yuv 顺序 | 仅适用于 yuv Sensor |
| handle->interface_attr.attr_mipi.mipi_hdr_mode | 注册设置MIPI HDR 模式 | CUS_HDR_MODE_NONE /无 HDR/ CUS_HDR_MODE_SONY_DOL /索尼标准线信息输出/ CUS_HDR_MODE_DCG /双增益 HDR/ CUS_HDR_MODE_EMBEEDED_RAW8 /嵌入式 8bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW10 /嵌入式 10bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW12 /嵌入式 12bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW14 /嵌入式 14bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW16 /嵌入式 16bit HDR/ CUS_HDR_MODE_COMP /压缩 HDR/ CUS_HDR_MODE_LI /行交错 HDR/ CUS_HDR_MODE_COMP_VS /压缩 HDR + very short/ CUS_HDR_MODE_VC /虚拟通道模式/ CUS_HDR_MODE_MAX 注意: 在旧版的CUS_HDR_MODE_DCG 代表通过虚拟通道传输的HDR,在新版的架构下更名为CUS_HDR_MODE_VC。 |
| handle->interface_attr.attr_mipi.mipi_hdr_virtual_channel_num | 注册设置HDR虚拟通道数根据各个sensor VC模式头文件定义 | 例如imx415: 长曝光帧数: 0 短曝光帧数: 1 |
| handle->interface_attr.attr_mipi.mipi_hdr_fusion_type | 注册设置 HDR 融合类型 | CUS_HDR_FUSION_TYPE_NONE,(默认) CUS_HDR_FUSION_TYPE_2T1, CUS_HDR_FUSION_TYPE_3T1, |
4.2.6 Parallel信息handle¶
设置Parallel以进行配置
表 10:Parallel Sensor接口注册列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->interface_attr.attr_parallel.paral_data_format | 注册设置parallel sensor数据格式 | CUS_SEN_INPUT_FORMAT_YUV422, CUS_SEN_INPUT_FORMAT_RGB, |
| handle->interface_attr.attr_parallel. paral_yuv_order | 注册设置parallel sensor yuv 顺序 | 仅适用于 yuv sensor |
4.2.7 lvds 信息handle¶
设置 lvds 以进行配置
表11:lvds Sensor接口注册列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->interface_attr.attr_lvds.lvds_lane_num | 注册设置 LVDS 通道数 | 默认值:4 |
| handle->interface_attr.attr_lvds.lvds_data_format | 注册设置 LVDS 数据格式 | CUS_SEN_INPUT_FORMAT_YUV422, CUS_SEN_INPUT_FORMAT_RGB, |
| handle->interface_attr.attr_lvds.lvds_yuv_order | 注册设置 LVDS yuv 顺序 | 仅适用于 yuv Sensor |
| handle->interface_attr.attr_lvds.lvds_hsync_mode | 注册设置 HDR 虚拟通道 0 水平同步模式 | SENSOR_MIPI_HSYNC_MODE PACKET_HEADER_EDGE1 = 0, /数据包头边缘/ PACKET_HEADER_EDGE2 = 1, /行结束边缘/ PACKET_HEADER_EDGE3 = 2, /行起始边缘/ PACKET_FOOTER_EDGE = 3, /数据包尾部边缘/ |
| handle->interface_attr.attr_lvds.lvds_sampling_delay | 注册设置LVDS开始采样延迟 | BIT[7:0]: clk_skip_ns BIT[15:8]: data_skip_ns |
| handle->interface_attr.attr_ lvds.lvds_hdr_mode | 注册设置 LVDS HDR 模式 | CUS_HDR_MODE_NONE /无 HDR/ CUS_HDR_MODE_SONY_DOL /索尼标准线信息输出/ CUS_HDR_MODE_DCG /双增益 HDR/ CUS_HDR_MODE_EMBEEDED_RAW8 /嵌入式 8bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW10 /嵌入式 10bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW12 /嵌入式 12bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW14 /嵌入式 14bit HDR/ CUS_HDR_MODE_EMBEEDED_RAW16 /嵌入式 16bit HDR/ CUS_HDR_MODE_COMP /压缩 HDR/ CUS_HDR_MODE_LI /行交错 HDR/ CUS_HDR_MODE_COMP_VS /压缩 HDR + very short/ CUS_HDR_MODE_VC /虚拟通道模式/ CUS_HDR_MODE_MAX 注意: 在旧版的CUS_HDR_MODE_DCG 代表通过虚拟通道传输的HDR,在新版的架构下更名为CUS_HDR_MODE_VC。 |
| handle->interface_attr.attr_lvds.lvds_hdr_virtual_channel_num | 注册设置HDR虚拟通道数根据各个sensor VC模式头文件定义 | 长曝光帧数:0 短曝光帧数:1 |
4.2.8 Sensor接口注册功能点handle¶
表 12:Sensor控制注册功能点列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->pCus_sensor_poweron (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL Fill Up Sensor IF Info!!! 注册设置Sensor上电序列功能点。 |
函数引用: pCus_poweron |
| handle->pCus_sensor_poweroff (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor断电序列功能点。 |
函数引用: pCus_poweroff |
| handle->pCus_sensor_init (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS或FAIL 注册加载Sensor初始设置函数点。 |
|
| handle->pCus_sensor_post_init (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 设置并启用 SoC mipi csi 状态。 |
特殊情况如 SmartSens 产品 SC4236/SC2315 |
| handle->pCus_sensor_poweroff (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor断电序列功能点。 |
函数引用: pCus_poweroff |
| handle->pCus_sensor_suspend (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor暂停功能点。 |
|
| handle->pCus_sensor_resume (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor恢复功能点。 |
|
| handle->pCus_sensor_release (struct __ss_cus_sensor* handle) | 参数: 返回值:SUCCESS 或 FAIL 注册Sensor释放功能点。 |
函数引用: cus_camsensor_release_handle |
| handle->pCus_sensor_reopen (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor重新打开功能点。 |
需要移除,pCus_sensor_str resume 替换 |
| handle->pCus_sensor_streamon (struct __ss_cus_sensor* handle, u32 idx) | 参数: u32 idx:Sensor Pad 返回值:SUCCESS 或 FAIL 注册设置Sensor流开启功能点。 |
在Sensor早期初始化模式下,当 vif 设置 streamon 时可以调用该功能点。 |
| handle->pCus_sensor_GetVideoResNum(struct __ss_cus_sensor* handle, u32 *ulres_num) | 参数: u32 ulres_num:支持的分辨率列表号 返回值:SUCCESS或FAIL 注册获取Sensor支持的分辨率列表号 |
函数引用: pCus_GetVideoResNum |
| handle->pCus_sensor_GetVideoRes (struct __ss_cus_sensor* handle, u32 res_idx, cus_camsensor_res **res) | 参数: u32 res_idx:分辨率索引 cus_camsensor_res:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册获取Sensor支持分辨率列表信息函数点。 |
|
| handle->pCus_sensor_GetCurVideoRes (struct __ss_cus_sensor* handle, u32 res_idx, cus_camsensor_res **res) | 参数:u32 res_idx:分辨率索引 cus_camsensor_res:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册获取Sensor当前分辨率信息功能点。 |
|
| handle->pCus_sensor_GetCurVideoRes (struct __ss_cus_sensor* handle, u32 res_idx) | 参数: u32 res_idx:分辨率索引 返回值:SUCCESS 或 FAIL 注册设置Sensor分辨率索引功能点。 |
|
| handle->pCus_sensor_GetOrien(struct __ss_cus_sensor* handle, CUS_CAMSENSOR_ORIT *ori) | 参数: CUS_CAMSENSOR_ORIT:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册获取Sensor mirror-flip状态函数。 |
函数引用: pCus_GetOrien |
| handle->pCus_sensor_SetOrien(struct __ss_cus_sensor* handle, CUS_CAMSENSOR_ORIT ori) | 参数: CUS_CAMSENSOR_ORIT:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册设置Sensor mirror-flip状态函数。 |
函数引用: pCus_SetOrien |
| handle->pCus_sensor_AEStatusNotify(struct __ss_cus_sensor* handle, u32 idx, CUS_CAMERA_AE_STATUS_NOTIFY status) | 参数: u32 idx:Sensor Pad CUS_CAMERA_AE_STATUS_NOTIFY:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册在帧开始或帧结束时更新 AE 增益、快门和 fps 状态。 |
函数引用:pCus_AEStatusNotify 状态 0 为帧结束更新 状态 1 为帧开始更新 |
| handle->pCus_sensor_GetAEUSecs(struct __ss_cus_sensor* handle, u32 *us) | 参数: u32 *us:AE 快门时间 返回值:SUCCESS 或 FAIL 注册获取Sensor输出图像曝光时间。 |
函数引用:pCus_GetAEUSecs |
| handle->pCus_sensor_SetAEUSecs(struct __ss_cus_sensor* handle, u32 us) | 参数: u32 us:AE 快门时间 返回值:SUCCESS 或 FAIL 注册设置Sensor输出图像曝光时间。 |
函数引用:pCus_SetAEUSecs |
| handle->pCus_sensor_GetAEGain(struct __ss_cus_sensor* handle, u32 *gain) | 参数: u32 *gain:AE 增益 返回值:SUCCESS 或 FAIL 注册获取Sensor AE 增益。 |
函数引用: pCus_GetAEGain |
| handle->pCus_sensor_SetAEGain(struct __ss_cus_sensor* handle, u32 gain) | 参数: u32 gain:AE 增益 返回值:SUCCESS 或 FAIL 注册设置Sensor AE 增益。 |
函数引用: pCus_SetAEGain |
| handle->pCus_sensor_TryAEGain(struct __ss_cus_sensor* handle, u32 gain) | 参数: u32 gain:AE 增益 返回值:SUCCESS 或 FAIL 注册尝试获取Sensor AE 增益 |
|
| handle->pCus_sensor_TryAEShutter(struct __ss_cus_sensor* handle, u32 us) | 参数: u32 gain : AE shutter 返回值:SUCCESS 或 FAIL 注册尝试获取Sensor AE Shutter |
|
| handle->pCus_sensor_GetAEInfo(struct __ss_cus_sensor* handle, CUS_SENSOR_AE_INFO_t *info) | 参数: CUS_SENSOR_AE_INFO_t:请参考 drv_ss_cus_sensor.h 返回值:SUCCESS 或 FAIL 注册尝试获取Sensor AE(快门和增益)信息 |
|
| handle->pCus_sensor_GetFPS(struct __ss_cus_sensor* handle) | 参数: 返回值:Sensor fps 注册获取Sensor FPS 状态函数。 |
函数引用: pCus_GetFPS |
| handle->pCus_sensor_SetFPS(struct __ss_cus_sensor* handle, u32 fps) | 参数: u32 fps:Sensor fps 返回值:SUCCESS 或 FAIL 注册设置Sensor FPS 状态函数。 |
函数引用: pCus_SetFPS |
| handle->pCus_sensor_Get_ShutterGainShare(struct __ss_cus_sensor* handle, int eHDRType) | 参数: int eHDRType:Sensor fps 返回值:SUCCESS 或 FAIL 注册获取Sensor增益和快门状态函数。 |
CUS_HDR_MODE_NONE /无 HDR/ CUS_HDR_MODE_SONY_DOL /Sony 标准行信息输出/ CUS_HDR_MODE_DCG /双增益 HDR/ /嵌入式 16 位 HDR/ CUS_HDR_MODE_COMP /压缩 HDR/ CUS_HDR_MODE_LI /行交错 HDR/ CUS_HDR_MODE_COMP_VS /压缩 HDR + very short/ CUS_HDR_MODE_VC /虚拟通道模式/ CUS_HDR_MODE_MAX |
| handle->pCus_sensor_SetISPConverStatus(struct __ss_cus_sensor* handle, u8 bStatus) | 参数: u8 bStatus : Sensor AE 收敛状态 返回值:SUCCESS 或 FAIL 注册设置Sensor AE 收敛状态函数。 |
用于快速 AE 收敛模式,可通知 ISP 和 Sensor AE 收敛状态 |
4.2.9 从机Sensor handle¶
用户可以通过 struct _ms_cus_sensor::slave_mode_attr 设置Sensor handle变量来控制外部从机模式下的 hsync/vsync/trigger 信号时序
表 13:Sensor从机时序列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->slave_mode_attr.eSrcSck | 选择 Hsync 时钟源 | CUS_CMU_CLK_27MHZ, CUS_CMU_CLK_21P6MHZ, CUS_CMU_CLK_12MHZ, CUS_CMU_CLK_5P4MHZ, CUS_CMU_CLK_36MHZ, CUS_CMU_CLK_54MHZ, CUS_CMU_CLK_43P2MHZ, CUS_CMU_CLK_61P7MHZ, CUS_CMU_CLK_72MHZ, CUS_CMU_CLK_48MHZ, CUS_CMU_CLK_24MHZ, CUS_CMU_CLK_37P125MHZ*, |
| handle->slave_mode_attr.ePolHsync | Hsync 初始极性 | CUS_CLK_POL_POS, CUS_CLK_POL_NEG |
| handle->slave_mode_attr.ePolVsync | Vsync 初始极性 | CUS_CLK_POL_POS, CUS_CLK_POL_NEG |
| handle->slave_mode_attr.ePolXtrig | XTrig 初始极性 | CUS_CLK_POL_POS, CUS_CLK_POL_NEG |
| handle->slave_mode_attr.uHsyncStartT | Hsync 开始时间 = uHsyncStartT * 源时钟周期 | 范围 0 到 65535 |
| handle->slave_mode_attr.uHsyncEndT | Hsync 结束时间 = uHsyncEndT * 源时钟周期 | 范围 0 到 65535 |
| handle->slave_mode_attr.uHsyncPeriod | Hsync周期 = uHsyncPeriod * 源时钟周期 | 范围 0 到 65535 |
| handle->slave_mode_attr.uVsyncEndT | Vsync 低时序 = uVsyncEndT * Hsync 周期 | 范围 0 到 65535 |
| handle->slave_mode_attr.uVsyncPeriod | Vsync 周期 = uVsyncPeriod * Hsync 周期 | 范围 0 到 65535 |
| handle->slave_mode_attr.uXTrigEndT | XTrigger 低时序 = uXTrigEndT * 源时钟周期 | 范围 0 到 (2^32)-1 |
| handle->slave_mode_attr.uXTrigPeriod | XTrigger 周期 = uXtrigPeriod * 源时钟周期 | 范围 0 到 (2^32)-1 |
图4:从机模式下的Hsync时序
图 5:从机模式下的Vsync时序
4.2.10 自定义功能点handle¶
用户可以通过 struct _ms_cus_sensor::slave_mode_attr 设置Sensor handle变量来控制外部从机模式下的 hsync/vsync/trigger 信号时序
表 14:Sensor用户定义功能点handle列表
| 参数 | 描述 | 注意 |
|---|---|---|
| handle->pCus_sensor_CustDefineFunction(struct __ss_cus_sensor* handle, u32 cmd_id, void *param) | 参数: cmd_id:用户定义函数项 *param:用户定义函数参数 返回值:SUCCESS或FAIL 注册Sensor增益和快门状态函数。 |
请参考第5.7节 |
4.2.11 SensorIF 回调的handle¶
SENSOR_IF API用于连接Sensor驱动程序和VIF驱动程序,此回调控制在下面的处理控制函数中。
设置Sensor MCLK 配置
表 15:sensorif回调函数列表的handle
| 参数 | 描述 | 注意 |
|---|---|---|
| sensor_if->PowerOff(u32 idx, CUS_CLK_POL pol); | 参数: idx:Sensor Pad CUS_CLK_POL:拉高或拉低 设置 Sensor-IF PowerDown 是否拉高。 |
回调至 VIF司机 |
| sensor_if->Reset(u32 idx, CUS_CLK_POL pol); | 参数: idx:Sensor Pad CUS_CLK_POL:拉高或拉低 设置 Sensor-IF SW RESET 是否拉高。 |
回调至VIF 驱动程序 |
| sensor_if->MCLK(u32 idx , u8 bon_off, CUS_MCLK_FREQ mclk); | 参数: idx:Sensor Pad bon_off:启用或禁用 CUS_MCLK_FREQ:Sensor clk 注册设置 VIF 模块输出 MCLK 到Sensor用于 MI 查询!! |
主芯片支持 MCLK 列表为: CUS_CMU_CLK_27MHZ, CUS_CMU_CLK_21P6MHZ, CUS_CMU_CLK_12MHZ, CUS_CMU_CLK_5P4MHZ, CUS_CMU_CLK_36MHZ, CUS_CMU_CLK_54MHZ, CUS_CMU_CLK_43P2MHZ, CUS_CMU_CLK_61P7MHZ, CU S_CMU_CLK_72MHZ, CUS_CMU_CLK_48MHZ, CUS_CMU_CLK_24MHZ, CUS_CMU_CLK_37P125MHZ, CUS_CMU_CLK_LPLL_DIV1, CUS_CMU_CLK_LPLL_DIV2, CUS_CMU_CLK_LPLL_DIV4, CUS_CMU_CLK_LPLL_DIV8, |
| sensor_if->SetIOPad (u32 idx, CUS_SENIF_BUS ulSnrType, NULL) | 参数: idx:Sensor Pad CUS_SENIF_BUS:Sensor接口 用于 SENSOR-IF I/O 总线模式 |
回调至 VIF 驱动程序 |
| sensor_if->SetSkipFrame(u32 idx, u16 skip_num, u8 bon_off) | 参数: idx:Sensor Pad skip_num:跳过帧cnt bon_off:启用或禁用 跳过vif输出帧 |
回调至VIF驱动程序 |
4.2.12 MIPI CSI配置回调的handle¶
SENSOR_IF API 用于连接Sensor驱动程序和 MIPI CSI 驱动程序,此回调控制在下面的处理控制函数中。
表16:mipi csi回调函数列表
| 参数 | 描述 | 注意 |
|---|---|---|
| sensor_if->SetCSI_Clk (u32 idx, CUS_CSI_CLK clk) | 参数: idx:Sensor Pad CUS_CSI_CLK:Mipi clk 设置 MIPI 接口 MAC CLK |
回调至 CSI 驱动程序 |
| sensor_if->SetCSI_Lane(u32 idx, u16 num_lane, u8 bon_off) | 参数: idx:Sensor Pad num_lane:Mipi 通道号 bon_off:启用或禁用 设置 MIPI 接口数据通道 |
回调至 CSI 驱动程序 |
| sensor_if->SetCSI_hdr_mode(idx, CUS_HDR_MODE hdr_mode, u8 bon_off) | 参数: idx:Sensor Pad hdr_mode: bon_off:启用或禁用 设置 HDR 数据格式 |
回调到 CSI 驱动程序 CUS_HDR_MODE_NONE /无 HDR/ CUS_HDR_MODE_SONY_DOL /Sony 标准线信息输出/ CUS_HDR_MODE_DCG /双增益 HDR/ /嵌入式 16 位 HDR/ CUS_HDR_MODE_COMP /压缩 HDR/ CUS_HDR_MODE_LI /线交错 HDR/ CUS_HDR_MODE_COMP_VS /压缩 HDR + very short/ CUS_HDR_MODE_VC /虚拟通道模式/ CUS_HDR_MODE_MAX |
| sensor_if->SetCSI_LongPacketType(u32 idx, u16 dt0_15, u16 dt16_31, u16 u32_47) | 参数: idx:Sensor Pad 类型[15:0],[31:16],[47:32] 设置 MIPI 长数据包类型启用 |
回调至 CSI 驱动程序长数据包类型启用 [0]: Null [1]: blinking [2]: embedded [14]: YUV422_8B [26]: RAW8 [27]: RAW10 [28]: RAW12 [29]: RAW14 [30]: RAW16 [32]: UD1 [33]: UD2 [34]: UD3 [35]: UD4 [36]: UD5 [37]: UD6 [38]: UD7 [39]: UD8 |
| Sensor_if->SetCSI_yuv_order_swap(u32 idx, u8 swap) | 参数: idx:Sensor Pad swap:启用或禁用 设置 MIPI 输入 YUV422 数据顺序交换 |
回调至 CSI 驱动程序 |
4.2.13 Parallel极性回调handle¶
设置Parallel Sensor硬件信号极性
表 17:Parallel Sensor回调函数列表
| 参数 | 描述 | 注意 |
|---|---|---|
| Sensor_if-> SetVIF_ParPinPol(u32 idx, CUS_CLK_POL HsynPol, CUS_CLK_POL VsynPol) | 参数: u32 idx:Sensor Pad HsynPol:parallel sensor hsync 极性 VsynPol:parallel sensor vsync 极性 用于Sensor vysnc 和 hsync 极性配置 |
回调至 VIF 驱动程序 |
4.2.14 私有数据¶
本章介绍Sensor驱动私有数据,目的是记录Sensor的参数,不做任何修改。这里以imx415作为参考例子。
首先,Sgs Sensor驱动程序将在安装Sensor时配置存储库。
SENSOR_DRV_ENTRY_IMPL_END_EX( IMX415_HDR,
cus_camsensor_init_handle,
cus_camsensor_init_handle_hdr_dol_sef,
cus_camsensor_init_handle_hdr_dol_lef,
imx415_params
);
该内存根据sensor驱动来声明,以imx415为例:
typedef struct {
struct {
bool bVideoMode;
u16 res_idx;
CUS_CAMSENSOR_ORIT orit;
} res;
struct {
float sclk;
u32 hts;
u32 vts;
u32 us_per_line;
u32 final_us;
u32 final_gain;
u32 fps;
u32 preview_fps;
u32 expo_lines;
u32 expo_lef_us;
u32 expo_sef_us;
u32 expo_sef2_us;
} expo;
u32 min_shr1;
u32 min_rhs1;
u32 min_shr2;
u32 min_rhs2;
u32 min_shr0;
u32 max_shr0;
u32 fsc;
u32 skip_cnt;
I2C_ARRAY tVts_reg[3];
I2C_ARRAY tVts_reg_hdr[3];
I2C_ARRAY tExpo_reg[3];
I2C_ARRAY tSHR0_reg[3];
I2C_ARRAY tSHR1_reg[3];
I2C_ARRAY tRHS1_reg[3];
I2C_ARRAY tSHR2_reg[3];
I2C_ARRAY tRHS2_reg[3];
I2C_ARRAY tGain_reg[2];
I2C_ARRAY tGain_hdr_dol_lef_reg[2];
I2C_ARRAY tGain_hdr_dol_sef_reg[2];
I2C_ARRAY tGain_hdr_dol_sef2_reg[2];
bool dirty;
bool orien_dirty;
u8 snr_pad;
const I2C_ARRAY *pTable_linear;
const I2C_ARRAY *pTable_HDR;
u32 Init_Array_Size;
u32 Init_Vts;
u32 Line_Period;
u32 csi_clk;
u32 PowerOnOff;
CUS_CAMSENSOR_ORIT orient;
} imx415_params;
接下来我们在挂载Sensor寄存器函数时,将缓冲区配置为imx415_params:
int cus_camsensor_init_handle_linear(ss_cus_sensor* drv_handle)
{
ss_cus_sensor *handle = drv_handle;
imx415_params *params;
int res;
if (!handle) {
SENSOR_DMSG("[%s] not enough memory!\n", __FUNCTION__);
return FAIL;
}
SENSOR_DMSG("[%s]", __FUNCTION__);
////////////////////////////////////
// private data allocation & init //
////////////////////////////////////
if (handle->private_data == NULL) {
SENSOR_EMSG("[%s] Private data is empty!\n", __FUNCTION__);
return FAIL;
}
params = (imx415_params *)handle->private_data;
CamOsMemcpy(params->tVts_reg, vts_reg, sizeof(vts_reg));
CamOsMemcpy(params->tGain_reg, gain_reg, sizeof(gain_reg));
CamOsMemcpy(params->tExpo_reg, expo_reg, sizeof(expo_reg));
…
…
4.2.15 通用Sensor从机模式控制 API¶
使用通用从机模式函数 struct _ms_cus_sensor::sensor_if_api::SlaveModeCtrl 允许用户对信号时序控制进行更详细的设置。您可以在 drv_ms_cus_imx226_lvds.c 中找到示例代码和更多详细信息
| 控制 ID | 描述 | 注意 |
|---|---|---|
| CUS_SLAVE_MODE_CTRL_ID_INIT | 初始化 Hsync 和 Vsync | CUS_SLAVE_MODE_CTRL_ID_INIT |
| CUS_SLAVE_MODE_CTRL_ID_DEINIT | 释放并禁用 Hsync 和 Vsync | CUS_SLAVE_MODE_CTRL_ID_DEINIT |
| CUS_SLAVE_MODE_CTRL_ID_ENABLE_XVS | 立即启用或禁用 Vsync | CUS_SLAVE_MODE_CTRL_ID_ENABLE_XVS |
5. 软件移植流程¶
本章介绍软件移植Sensor驱动的过程。首先讲解如何初始化Sensor。然后描述Sensor驱动3A所需的信息以及控制3A将调用的函数。
5.1. Sensor驱动初始流程介绍¶

图 6:移植Sensor驱动程序流程
本文档按照上图的流程介绍了Sensor移植的初始过程。
5.1.1 设置Sensor信息¶
这些设置都是sensor的硬件信息,我们列出了必要的硬件信息,大家可以参考IMX415/IMX335 sensor驱动。
////////////////////////////////////
// Sensor-If Info //
////////////////////////////////////
//MIPI config begin.
#define SENSOR_MIPI_LANE_NUM (lane_num) //IMX335 Linear mode supports MIPI 2/4 Lane
#define SENSOR_MIPI_LANE_NUM_DOL (4) //(hdr_lane_num)//IMX335 DOL mode supports MIPI 4 Lane
#define SENSOR_IFBUS_TYPE CUS_SENIF_BUS_MIPI //CFG //CUS_SENIF_BUS_PARL, CUS_SENIF_BUS_MIPI
#define SENSOR_DATAPREC CUS_DATAPRECISION_10
#define SENSOR_DATAPREC_DOL CUS_DATAPRECISION_10
#define SENSOR_BAYERID CUS_BAYER_RG //0h: CUS_BAYER_RG, 1h: CUS_BAYER_GR, 2h: CUS_BAYER_BG, 3h: CUS_BAYER_GB
#define SENSOR_BAYERID_HDR_DOL CUS_BAYER_RG
#define SENSOR_RGBIRID CUS_RGBIR_NONE
CUS_ORIT_M1F1,
//#define SENSOR_YCORDER CUS_SEN_YCODR_YC //CUS_SEN_YCODR_YC, CUS_SEN_YCODR_CY
//#define long_packet_type_enable 0x00 //UD1~UD8 (user define)
////////////////////////////////////
// MCLK Info //
////////////////////////////////////
#define Preview_MCLK_SPEED CUS_CMU_CLK_27MHZ//CUS_CMU_CLK_37P125MHZ//CUS_CMU_CLK_27MHZ
#define Preview_MCLK_SPEED_HDR_DOL CUS_CMU_CLK_27MHZ
5.1.2 设置Sensor I2C¶
SoC主要通过I2C与Sensor进行通信,因此在将Sensor设置值发送给Sensor之前,需要先设置I2C。
请参阅本文档 第 1.2 章。
5.1.3 设置支持图片分辨率信息¶
需要填写Sensor提供商FAE提供的Sensor图片信息,包括预览尺寸、图片裁剪尺寸、站点等,我们将这些信息定义为全局变量。
////////////////////////////////////
// Image Info //
////////////////////////////////////
static struct { // LINEAR
// Modify it based on number of support resolution
enum {LINEAR_RES_1 = 0, LINEAR_RES_2, LINEAR_RES_3, LINEAR_RES_4, LINEAR_RES_5, LINEAR_RES_6, LINEAR_RES_7, LINEAR_RES_8, LINEAR_RES_END}mode;
// Sensor Output Image info
struct _senout{
s32 width, height, min_fps, max_fps;
}senout;
// VIF Get Image Info
struct _sensif{
s32 crop_start_X, crop_start_y, preview_w, preview_h;
}senif;
// Show resolution string
struct _senstr{
const char* strResDesc;
}senstr;
}imx415_mipi_linear[] = {
{LINEAR_RES_1, {3860, 2250, 3, 20}, {0, 0, 3840, 2160}, {"3840x2160@20fps"}},
{LINEAR_RES_2, {3096, 2190, 3, 30}, {0, 0, 3072, 2048}, {"3072x2048@30fps"}}, // Modify it
{LINEAR_RES_3, {3096, 1758, 3, 30}, {0, 0, 3072, 1728}, {"3072x1728@30fps"}}, // Modify it
{LINEAR_RES_4, {2616, 1974, 3, 30}, {0, 0, 2592, 1944}, {"2592x1944@30fps"}}, // Modify it
{LINEAR_RES_5, {2976, 1686, 3, 30}, {0, 0, 2944, 1656}, {"2944x1656@30fps"}}, // Modify it
{LINEAR_RES_6, {2592, 1470, 3, 30}, {0, 0, 2560, 1440}, {"2560x1440@30fps"}}, // Modify it
{LINEAR_RES_7, {1920, 1080, 3, 60}, {0, 0, 1920, 1080}, {"1920x1080@60fps"}}, // Modify it
{LINEAR_RES_8, {3864, 2192, 3, 30}, {0, 0, 3840, 2160}, {"3840x2160@30fps"}}, // Modify it
//{LINEAR_RES_9, {2616, 1974, 3, 25}, {0, 0, 2592, 1944}, {"2592x1944@25fps"}}, // Modify it
};
5.1.4 Sensor上电时序功能¶
请参考“handle->pCus_sensor_poweron”注册的函数。
5.1.5 Sensor初始化函数¶
这里是通过i2c设备对Sensor进行初始设置,首先读取Sensor设备的产品ID或者Sensor ID,确保使用了正确的Sensor。请参考“handle->pCus_sensor_init”注册的函数。
5.1.6 选择Sensor输出分辨率函数¶
MI 将获取Sensor驱动程序支持的图像分辨率信息,并选择Sensor的初始设置之一。
请参考“handle->pCus_sensor_SetVideoRes”注册的函数。
5.1.7 Sensor断电时序功能¶
请参考“handle->pCus_sensor_poweroff”注册的函数。
5.2. 实现Sensor控制功能¶
sensor驱动需要支持的功能有fps的调整、AE快门的调整、AE增益的调整以及mirror-flip功能的设置等,这需要根据各个sensor的特点来实现。
以下是我们控制Sensor实现的函数流程。相对的,我们还需要获取Sensor的信息,请参考下图:

图7:控制Sensor实现功能流程

图8:获取Sensor实现功能信息或状态
5.2.1 AE快门控制并获取AE快门信息¶
如何控制AE快门,请参考“handle->pCus_sensor_SetAEUSecs”注册的函数。
另外,ISP 算法或者 MI 需要获取 AE 快门信息,请参考“handle->pCus_sensor_GetAEInfo”注册的函数。
5.2.2 AE增益控制及获取AE增益信息¶
如何控制AE增益,请参考“handle->pCus_sensor_SetAEGain”注册的函数。
另外,ISP 算法或者 MI 需要获取 AE 增益信息,请参考“handle->pCus_sensor_GetAEInfo”注册的函数
更多详细信息请参考 5.2.6 和 5.2.7。
5.2.3 Sensor帧率控制并获取Sensor帧率信息¶
如何控制sensor输出帧率,请参考“handle->pCus_sensor_SetFPS”注册的函数。
另外MI需要获取sensor输出帧率信息,请参考“handle->pCus_sensor_GetFPS”注册的函数。
5.2.4 Sensor mirror-flip控制及获取Sensor mirror-flip信息¶
如何控制sensor图像镜像翻转,请参考“handle->pCus_sensor_SetOrien”注册的函数。
另外,MI需要获取Sensor图像镜像翻转信息,请参考“handle->pCus_sensor_GetOrien”注册的函数。
5.2.5 I2C执行时间控制¶
上面的AE快门、AE增益、sensor帧率和反光镜控制,希望大家可以同时通过I2C给sensor发送命令
因此我们将使用函数“handle->pCus_sensor_AEStatusNotify”来实现这一点
因此我们可以通过两个参数“CUS_FRAME_ACTIVE”和“CUS_FRAME_INACTIVE”来控制I2C向Sensor发送命令的时间。大部分Sensor都可以在帧开始时设置,因此可以选择参数“CUS_FRAME_ACTIVE”。

图 9:I2C 执行时间
注意:
如果移植Sensor无法找出导致图像异常的原因,可以直接在函数中调用返回成功。
5.2.6 Sensor AE 快门/增益延迟计数¶
如何设置“ae shutter delay” 和 “ae gain delay” 的“handle->pCus_sensor_GetAEInfo”,请参考本文档 第 4.3 章。
5.2.7 Sensor AE 快门/增益控制数字¶
“ae gain ctrl num” 和 “ae shutter ctrl num” 的“ handle->pCus_sensor_GetAEInfo” 表示可以控制 AE 流数量的 ISP
获取AE信息示例代码:
static int pCus_sensor_GetAEInfo(ss_cus_sensor *handle, CUS_SENSOR_AE_INFO_t *info)
{
imx415_params *params = (imx415_params *)handle->private_data;
info->u8AEGainDelay = SENSOR_GAIN_DELAY_FRAME_COUNT;
info->u8AEShutterDelay = SENSOR_SHUTTER_DELAY_FRAME_COUNT;
info->u8AEGainCtrlNum = SENSOR_GAIN_CTRL_NUM;
info->u8AEShutterCtrlNum = SENSOR_SHUTTER_CTRL_NUM;
info->u32AEGain_min = SENSOR_MIN_GAIN;
info->u32AEGain_max = SENSOR_MAX_GAIN;
info->u32AEShutter_min = params->Line_Period * 1;
info->u32AEShutter_max = 1000000000/handle->video_res_supported.res[handle->video_res_supported.ulcur_res].u16min_fps;
info->u32AEShutter_step = params->Line_Period;
return SUCCESS;
}
6. 补充¶
6.1. 安装Sensor Driver及参数介绍¶
Sgs Sensor驱动提供了几个安装参数,安装Sensor驱动时可以使用这些参数,具体参数及说明如下:
表 17:Sensor驱动安装参数
| 参数 | 描述 |
|---|---|
| chmap | 指定Sensor的 SoC Channel pad,以bitmap格式表示,Bit[0]代表sensor 0,Bit[1]代表sensor 1,依此类推。 |
| mclk | 指定Sensor mclk 信息 |
| lane_num | 指定 Sensor 线性模式 MIPI 通道数 |
| hdr_lane_num | 指定Sensor hdr 模式 MIPI 通道号 |
| i2c_slave_id | 指定Sensor i2c 从机 id |
例如:
insmod imx335_MIPI.ko chmap=1 lane_num=4 hdr_lane_num=4 i2c_slave_id=0x20
如果安装Sensor驱动时没有使用以上参数,则使用Sensor驱动中的默认值。
6.2. 验证快门和增益延迟¶
如果要验证Sensor AE 增益/快门延迟,可以使用 apitool,同样按照下面的步骤逐步控制Sensor AE 增益/快门功能。
步骤 1. 您需要先执行 prog_vif_isp_ut 进程
/customer # ./prog_vif_isp_ut param_snr0.ini
步骤 2. 在 sdk 路径“project/tools/apitool”中打开 IQ 工具

步骤 3. 主机名是 EVB 的 IP 地址,检查后连接到 EVB

步骤 4. 选择 Macaron AE 选项,并将“ExposureMode”菜单表选择为 M_Mode

步骤 5. 调整“DebugLev”菜单并将 AE 调试级别从 0 设置为 64,然后您就可以检查控制台日志

检查控制台上显示的 AE 消息

步骤 6. 手动调整 AE Sensor增益或快门。同时,您可以观察控制台上显示的 AE 消息。

观察“CurYx10”的值从 308 变为 1436

我们通过ISP工具设置AE的增益后,会在下一帧生效,CurYx10代表的是前一帧的亮度信息,下图为示例,AE增益延时需要设置2。

图10:AE Y值响应时间
6.3. 验证快门和增益线性¶
移植完sensor AE gain/shutter功能后,如果想验证sensor AE gain/shutter功能是否正常,可以使用apitool,可以按照下面的步骤控制sensor AE gain/shutter功能。
步骤 1. 执行mixer
/customer # ./prog_vif_isp_ut param_snr0.ini
步骤 2. 在 sdk 路径“project/tools/apitool”中打开 IQ 工具

步骤 3. 主机名是 EVB 的 IP 地址,检查后连接到 EVB

步骤 4. 选择 Macaron AE 选项,并将“ExposureMode”菜单表选择为 M_Mode

步骤 5. 手动调整 AE Sensor增益和快门。同时,您可以通过 VLC 或调试消息观察图像变化。

IQ Tool 已定义 AE 设置的上限和下限,您可以根据需要进行调整。您可以参考曝光限制表。

6.4. 跳帧功能¶
目前已经实现的sensor驱动有imx307,可以参考imx307的sensor驱动,这里我简单讲一下skip frame功能的使用方法。
步骤 1. 在Sensor驱动程序的 Params 结构中添加一个变量“skip _cnt”
u32 max_rhs1;
u32 lef_shs2;
u32 skip_cnt;
bool dirty;
bool change;
I2C_ARRAY tVts_reg[3];
I2C_ARRAY tGain_reg[3];
I2C_ARRAY tExpo_reg[3];
I2C_ARRAY tShs2_reg[3];
I2C_ARRAY tRhs1_reg[3];
I2C_ARRAY tGain_hdr_dol_lef_reg[1];
I2C_ARRAY tGain_hdr_dol_sef_reg[1];
bool orien_dirty;
} imx307_params;
步骤2. 在需要跳帧的函数中设置跳帧的数量。
以imx307为例,在HDR模式下,高亮环境下改变fps(从10 fps到30 fps)可能会出现闪烁,因此请跳过1帧以避免闪烁。
if(params->expo.expo_lines > 2 * params->expo.vts - params->max_rhs1 -3){
vts = (params->expo.expo_lines + params->max_rhs1 + 3 + 1) / 2;
}else{
vts = params->expo.vts;
}
params->expo.vts = vts;
pCus_SetAEUSecsHDR_DOL_SEF1(handle, params->expo.expo_sef_us);
params->skip_cnt = 1;
return SUCCESS;
步骤 3. “AESStatusNotify” 函数中实际跳帧时间。请添加以下功能。SensorIF 将根据跳帧数和当前 fps 时间段计算设置 VIF 掩码禁用的时间。
if(params->skip_cnt){
sensor_if->SetSkipFrame(handle->snr_pad_group, params->expo.fps, params->skip_cnt);
params->skip_cnt = 0;
}
break;
default :
break;
}
return SUCCESS;
6.5. Sensor初始后功能(SmartSens 的特殊情况)¶
由于Smartsens sensor上电后先传输i2c cmd,有概率sensor的mipi csi和clock会被拉低,导致SoC mipi csi异常。

图 11:Smartsense Sensor信号
目前解决办法是改变sensor上电和sensor初始化的顺序,等sensor初始化完成后再使能SoC mipi csi即可解决这个问题,具体流程请参考如下:

图12:开机顺序流程变化
注意:
还有其他方法可以解决这个问题,请要求Sensor厂商提供 mipi csi非连续模式,可以解决由于mipi csi首帧接收状态异常导致mipi csi卡死的问题。
6.6. Parallel Sensor配置¶
Parallel Sensor 相较于 MIPI Sensor,需要确认信号极性与硬件 Pin 排列,下面将说明如何设定信号极性与硬件 Pin 排列。
6.6.1 Parallel Sensor信号极性¶
一般Parallel Sensor通常需要配置3种时钟信号
表 18:Parallel Sensor信号类型
| 信号名称 | 缩写 | 描述 |
|---|---|---|
| Vertical Sync | VSYNC | Frame Start (FS) |
| Horizontal Sync | HSYNC | Line Start (LS) |
| Pixel Clock | PCLK | Carry Pixel data |
Frame Start (FS) 信号在 VSYNC 的上升沿或下降沿生成。Line Start (LS) 信号在 HSYNC 的上升沿或下降沿生成,PCLK 内部进行 AND 运算以提供有效的像素时钟信号。VSYNC 和 HSYNC 可以是高电平有效或低电平有效。在每个有效的像素时钟沿,数据都会被锁存到 FIFO 中。

图 13:Parallel Sensor信号
我们在Sensor驱动程序中提供了 API 来配置Parallel Sensor vsync 和 hsync 极性。它需要根据Sensor初始化设置来配置极性。参考:
int (*SetVIF_ParPinPol) (u32 idx, CUS_CLK_POL HsyncPol, CUS_CLK_POL VsyncPol);
static int pCus_poweron(ss_cus_sensor *handle, u32 idx)
{
ISensorIfAPI *sensor_if = handle->sensor_if_api;
//Sensor power on sequence
sensor_if->PowerOff(idx, CUS_CLK_POL_NEG); // Powerdn Pull Low
sensor_if->Reset(idx, CUS_CLK_POL_NEG); // Rst Pull Low
sensor_if->SetVIF_ParPinPol(idx, CUS_CLK_POL_NEG); // Rst Pull Low
sensor_if->SetIOPad(idx, handle->sif_bus, CUS_CLK_POL_NEG, CUS_CLK_POL_NEG);
6.6.2 Parallel Sensor Pad布局¶
Parallel Sensor配置需要根据Sensor Pad的排列来确定Sensor格式,而不是使用Sensor数据精度
示例1(8-bit Sensors):
Parallel padmux模式提供2组设置,8-bit Sensors的布局如下:红框/蓝框/橙框。硬件上布局不同,则设置的sensor格式会有所不同。

图 14:8-bit Parallel Sensor布局
示例2(10-bit Sensors)
Parallel padmux 模式提供 2 组设置,10-bit Sensors 的布局如下:蓝色框/橙色框。硬件上布局不同,则设置的 Sensor 格式会有所不同。

图 15:10-bit Parallel Sensor布局
VIF 配置Sensor格式始终为 12 位,建议硬件parallel数据引脚按 MSB 方向排列。如果不是,那么我们在 DTS 文件中提供了 MSB 移位参数设置 “vif_sr0_par_msb_shift=shift_pin”
硬件限制:shift_pin 只能是 2/4/6
6.7. 客户功能¶
如果用户想为Sensor驱动实现定制化的函数或者获取Sensor的信息,Sgs Sensor驱动提供了寄存器功能点供客户根据自己的需求进行开发,客户可以利用这些函数自定义内容:

图 16:用户定义控制流
Sensor驱动程序中的用户定义实现:
#define CMDID_I2C_READ (0x01)
#define CMDID_I2C_WRITE (0x02)
static int pCus_sensor_CustDefineFunction(ss_cus_sensor* handle,u32 cmd_id, void *param) {
if(param == NULL || handle == NULL)
{
SENSOR_EMSG("param/handle data NULL \n");
return FAIL;
}
switch(cmd_id)
{
case CMDID_I2C_READ:
{
I2C_ARRAY *reg = (I2C_ARRAY *)param;
SensorReg_Read(reg->reg, ®->data);
SENSOR_EMSG("reg %x, read data %x \n", reg->reg, reg->data);
break;
}
case CMDID_I2C_WRITE:
{
I2C_ARRAY *reg = (I2C_ARRAY *)param;
SENSOR_EMSG("reg %x, write data %x \n", reg->reg, reg->data);
SensorReg_Write(reg->reg, reg->data);
break;
}
default:
SENSOR_EMSG("cmd id %d err \n", cmd_id);
break;
}
return SUCCESS;
}
7. 故障排除¶
7.1. SONY Sensor输出格式¶
Sony sensor输出的mipi格式有两种,分别是DOL或VC,Sgs的mipi csi会根据settings比较头文件来接收数据,所以请确认当前的sensor初始化设置。

7.2. VIF 状态¶
同时可以打开telnet,输入下面的cmd来确认VIF和ISP状态。
通常30fps意味着一帧周期为33.3ms。
/ # cat /proc/mi_modules/mi_vif/debug_hal/vif0/vif_ints
== VIF0 INTS @:58129759 ==
== VIF CH-0 ==
CH State: : WORKING
Interval(us) : 41672
FramePeriod(us) : 39057
VREF_FALLING : 691 @:58099735
LINE_CNT_0 : 0 @:0
LINE_CNT_1 : 0 @:0
TOTAL_PIX_CNT : 670 @:58097120
== VIF CH-1 ==
CH State: : WORKING
Interval(us) : 41670
FramePeriod(us) : 39041
VREF_FALLING : 691 @:58102994
LINE_CNT_0 : 0 @:0
LINE_CNT_1 : 0 @:0
TOTAL_PIX_CNT : 670 @:58100365
== VIF FIFO-0 ==
Aff State: : WORKING
AFF Count: : 0 @:0
== VIF FIFO-1 ==
Aff State: : WORKING
AFF Count: : 0 @:0
== VIF FIFO-2 ==
Aff State: : READY
AFF Count: : 0 @:0
== VIF FIFO-3 ==
Aff State: : READY
AFF Count: : 0 @:0
确认VIF设备接收到的Sensor信号信息
/ # cat /proc/mi_modules/mi_vif/debug_hal/vif0/vif_info
== VIF0 INFO @:49165780 ==
== VIF CH-0 ==
CH State:: WORKING
[vg:0 link:REAL_ISP]--[chn:0]--[afifo:1]--[pipe:1(1)]--[isp:1]--[end]
CH_EN: 1
SRC: MIPI0
INPUT_FMT: RGB
PIX_FMT: 10 bits
CROP_EN: 1
CROP_START_X: 0 - 3839
CROP_START_Y: 0 - 2159
PIXEL_CNT: 3840
LINE_CNT: 2160
TOTAL_PIXEL_CNT: 3864
TOTAL_LINE_CNT: 2192
== VIF CH-1 ==
CH State:: WORKING
[vg:0 link:REAL_ISP]--[chn:1]--[afifo:0]--[pipe:0(0)]--[isp:0]--[end]
CH_EN: 1
SRC: MIPI0
INPUT_FMT: RGB
PIX_FMT: 10 bits
CROP_EN: 1
CROP_START_X: 0 - 3839
CROP_START_Y: 0 - 2159
PIXEL_CNT: 3840
LINE_CNT: 2160
TOTAL_PIXEL_CNT: 3864
TOTAL_LINE_CNT: 2192
7.3. MIPI 状态¶
如果每帧一行或一个像素的传输速度太快,即便VIF能正常接收到图像数据,也不能保证ISP能立刻处理,从而导致isp fifo full。
/ # echo 0 0 > /proc/mi_modules/mi_sensor/debug_hal/csi_dbg_mask
/ # cat /proc/mi_modules/mi_sensor/debug_hal/csi_ints
注意:
echo “Sensor Pad” “mask_status” > /proc/mi_modules/mi_sensor/debug_hal/csi_dbg_mask
== MIPI pad0 err ints==
DT : 22569
PA_LENS : 0
PH_LENS : 0
ECC_ONEBIT : 0
FRAME_START : 0
FRAME_END : 0
ECC_TWOBIT : 0
CRC : 0
PA_WC_EQ0 : 0
RAW10_LENS : 0
CON_FE : 0
CON_FS : 0
LE : 0
LS : 0
OVERRUN : 0
== MIPI pad0 rtp ints==
LINE_NUM : 0
FRAME_NUM : 0
SHORT_PKT : 0
VC3_DONE : 0
VC2_DONE : 0
VC1_DONE : 0
VC0_DONE : 0
== MIPI pad1 err ints==
DT : 75
PA_LENS : 0
PH_LENS : 0
ECC_ONEBIT : 0
FRAME_START : 0
FRAME_END : 0
ECC_TWOBIT : 0
CRC : 0
PA_WC_EQ0 : 0
RAW10_LENS : 0
CON_FE : 0
CON_FS : 0
LE : 0
LS : 0
OVERRUN : 0
== MIPI pad1 rtp ints==
LINE_NUM : 0
FRAME_NUM : 0
SHORT_PKT : 0
VC3_DONE : 0
VC2_DONE : 0
VC1_DONE : 0
VC0_DONE : 0
== MIPI pad2 err ints==
DT : 0
PA_LENS : 0
PH_LENS : 0
ECC_ONEBIT : 0
FRAME_START : 0
FRAME_END : 0
ECC_TWOBIT : 0
CRC : 0
PA_WC_EQ0 : 0
RAW10_LENS : 0
CON_FE : 0
CON_FS : 0
LE : 0
LS : 0
OVERRUN : 0
== MIPI pad2 rtp ints==
LINE_NUM : 0
FRAME_NUM : 0
SHORT_PKT : 0
VC3_DONE : 0
VC2_DONE : 0
VC1_DONE : 0
VC0_DONE : 0
Mipi csi中断错误消息
- OVERRUN:lane 时钟域到 mpll 时钟域 asyn fifo 溢出
- LS:收到行结束但丢失行开始错误
- LE:收到行首但丢失行尾错误
- CON_FS: 两个共同的帧开始之间没有帧结束
- CON_FE: 两个连续帧结束之间没有帧开始
- RAW10_LENS: tie 0(未使用)
- PA_WC_EQ0: 数据包头中的有效载荷字数等于 0
- CRC:数据包有效载荷CRC校验结果错误
- ECC_TWOBIT:数据包头ECC校验结果有2-bit错误
- FRAME_END:帧起始数据包后没有帧结束数据包
- FRAME_START(硬件自动忽略):收到一个正常数据包,但之前没有帧起始包
- ECC_ONIVIT:数据包头ECC校验结果有1-bit错误
- PH_LENS:数据包头长度错误
- PA_LENS: 有效载荷长度错误比 wc 短
- DT:保留且不支持的数据类型