MIPI CSI
概述
-
CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。
-
物理层支持HS(High Speed)和LP(Low Power)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。
-
图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。
ComboDevAttr结构体
表 1 ComboDevAttr结构体介绍
名称 | 描述 |
---|---|
devno | 设备号 |
inputMode | 输入模式:MIPI/LVDS/SUBSLVDS/HISPI/DC |
dataRate | Mipi Rx,SLVS输入速率 |
imgRect | MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应) |
MIPIAttr | Mipi设备属性 |
lvdsAttr | LVDS/SubLVDS/HiSPi设备属性 |
ExtDataType结构体
表 2 ExtDataType结构体介绍
名称 | 描述 |
---|---|
devno | 设备号 |
num | sensor号 |
extDataBitWidth | 图片的位深 |
extDataType | 定义YUV和原始数据格式以及位深度 |
接口说明
表 3 MIPI CSI API接口功能介绍
功能分类 | 接口名 |
---|---|
获取/释放MIPI CSI控制器操作句柄 | MipiCsiOpen:获取MIPI CSI控制器操作句柄 MipiCsiClose:释放MIPI CSI控制器操作句柄 |
MIPI CSI相应配置 | MipiCsiSetComboDevAttr:设置MIPI,CMOS或者LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等 MipiCsiSetExtDataType(可选):设置YUV和RAW数据格式和位深 MipiCsiSetHsMode:设置MIPI RX的Lane分布。根据硬件连接的形式选择具体的mode MipiCsiSetPhyCmvmode:设置共模电压模式 |
复位/撤销复位Sensor | MipiCsiResetSensor:复位Sensor MipiCsiUnresetSensor:撤销复位Sensor |
复位/撤销复位MIPI RX | MipiCsiResetRx:复位MIPI RX。不同的s32WorkingViNum有不同的enSnsType MipiCsiUnresetRx:撤销复位MIPI RX |
使能/关闭MIPI的时钟 | MipiCsiEnableClock:使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用MIPI还是LVDS MipiCsiDisableClock:关闭MIPI设备的时钟 |
使能/禁用MIPI上的Sensor时钟 | MipiCsiEnableSensorClock:使能MIPI上的Sensor时钟 MipiCsiDisableSensorClock:关闭Sensor的时钟 |
使用指导
使用流程
使用MIPI CSI的一般流程如图2所示。
获取MIPI CSI控制器操作句柄
在进行MIPI CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。
DevHandle MipiCsiOpen(uint8_t id);
表 4 MipiCsiOpen的参数和返回值描述
参数 | 参数描述 |
---|---|
id | MIPI CSI通道ID |
返回值 | 返回值描述 |
NULL | 获取失败 |
设备句柄 | 获取到指令通道的控制器操作句柄,类型为DevHandle |
假设系统中的MIPI CSI通道为0,获取该通道控制器操作句柄的示例如下:
DevHandle MipiCsiHandle = NULL; /* 设备句柄 */
id = 0; /* MIPI CSI通道ID */
/* 获取控制器操作句柄 */
MipiCsiHandle = MipiCsiOpen(id);
if (MipiCsiHandle == NULL) {
HDF_LOGE("MipiCsiOpen: failed\n");
return;
}
MIPI CSI相应配置
-
写入MIPI CSI配置
int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr);
表 5 MipiCsiSetComboDevAttr的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
pAttr | MIPI CSI相应配置结构体指针 |
返回值 | 返回值描述 |
0 | 设置成功 |
负数 | 设置失败 |
```c
int32_t ret;
struct ComboDevAttr attr;
/* 当前配置如下 */
(void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
attr.devno = 0; /* 设备0 */
attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */
attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */
attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */
attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */
attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */
attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */
/* 写入配置数据 */
ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
设置YUV和RAW数据格式和位深
int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType);
表 6 MipiCsiSetExtDataType的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
dataType | 定义YUV和原始数据格式以及位深度 |
返回值 | 返回值描述 |
0 | 设置成功 |
负数 | 设置失败 |
```c
int32_t ret;
struct ExtDataType dataType;
/* 配置YUV和RAW数据格式和位深参数 */
dataType.devno = 0; /* 设备0 */
dataType.num = 0; /* sensor 0 */
dataType.extDataBitWidth[0] = 12; /* 位深数组元素0 */
dataType.extDataBitWidth[1] = 12; /* 位深数组元素1 */
dataType.extDataBitWidth[2] = 12; /* 位深数组元素2 */
dataType.extDataType[0] = 0x39; /* 定义YUV和原始数据格式以及位深度元素0 */
dataType.extDataType[1] = 0x39; /* 定义YUV和原始数据格式以及位深度元素1 */
dataType.extDataType[2] = 0x39; /* 定义YUV和原始数据格式以及位深度元素2 */
/* 设置YUV和RAW数据格式和位深 */
ret = MipiCsiSetExtDataType(MipiCsiHandle, &dataType);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetExtDataType fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
设置MIPI RX的Lane分布
int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode);
表 7 MipiCsiSetHsMode的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
laneDivideMode | lane模式参数 |
返回值 | 返回值描述 |
0 | 设置成功 |
负数 | 设置失败 |
```c
int32_t ret;
enum LaneDivideMode mode;
/* lane模式参数为0 */
mode = LANE_DIVIDE_MODE_0;
/* 设置MIPI RX的 Lane分布 */
ret = MipiCsiSetHsMode(MipiCsiHandle, mode);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
设置共模电压模式
int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode);
表 8 MipiCsiSetPhyCmvmode的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
cmvMode | 共模电压模式参数 |
devno | 设备编号 |
返回值 | 返回值描述 |
0 | 设置成功 |
负数 | 设置失败 |
```c
int32_t ret;
enum PhyCmvMode mode;
uint8_t devno;
/* 共模电压模式参数为0 */
mode = PHY_CMV_GE1200MV;
/* 设备编号为0 */
devno = 0;
/* 设置共模电压模式 */
ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret);
return -1;
}
```
复位/撤销复位Sensor
-
复位Sensor
int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource);
表 9 MipiCsiResetSensor的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 |
返回值 | 返回值描述 |
0 | 复位成功 |
负数 | 复位失败 |
```c
int32_t ret;
uint8_t snsResetSource;
/* 传感器复位信号线号为0 */
snsResetSource = 0;
/* 复位sensor */
ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
撤销复位Sensor
int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource);
表 10 MipiCsiUnresetSensor的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 |
返回值 | 返回值描述 |
0 | 撤销复位成功 |
负数 | 撤销复位失败 |
```c
int32_t ret;
uint8_t snsResetSource;
/* 传感器撤销复位信号线号为0 */
snsResetSource = 0;
/* 撤销复位sensor */
ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret);
return -1;
}
```
复位/撤销复位MIPI RX
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
comboDev | MIPI RX或LVDS通路序号 |
返回值 | 返回值描述 |
0 | 复位成功 |
负数 | 复位失败 |
```c
int32_t ret;
uint8_t comboDev;
/* 通路序号为0 */
comboDev = 0;
/* 复位MIPI RX */
ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
撤销复位MIPI RX
int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev);
表 12 MipiCsiUnresetRx的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
comboDev | MIPI RX或LVDS通路序号 |
返回值 | 返回值描述 |
0 | 撤销复位成功 |
负数 | 撤销复位失败 |
```c
int32_t ret;
uint8_t comboDev;
/* 通路序号为0 */
comboDev = 0;
/* 撤销复位MIPI RX */
ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret);
return -1;
}
```
使能/关闭MIPI的时钟
-
使能MIPI的时钟
int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev);
表 13 MipiCsiEnableClock的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
comboDev | 通路序号 |
返回值 | 返回值描述 |
0 | 使能成功 |
负数 | 使能失败 |
```c
int32_t ret;
uint8_t comboDev;
/* 通路序号为0 */
comboDev = 0;
/* 使能MIPI的时钟 */
ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
关闭MIPI的时钟
int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev);
表 14 MipiCsiDisableClock的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
comboDev | 通路序号 |
返回值 | 返回值描述 |
0 | 关闭成功 |
负数 | 关闭失败 |
```c
int32_t ret;
uint8_t comboDev;
/* 通路序号为0 */
comboDev = 0;
/* 关闭MIPI的时钟 */
ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret);
return -1;
}
```
使能/关闭MIPI上的Sensor时钟
-
使能MIPI上的Sensor时钟
int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource);
表 15 MipiCsiEnableSensorClock的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 |
返回值 | 返回值描述 |
0 | 使能成功 |
负数 | 使能失败 |
```c
int32_t ret;
uint8_t snsClkSource;
/* 传感器的时钟信号线号为0 */
snsClkSource = 0;
/* 使能MIPI上的sensor时钟 */
ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret);
return -1;
}
```
-
关闭MIPI上的Sensor时钟
int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource);
表 16 MipiCsiDisableSensorClock的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | 控制器操作句柄 |
snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 |
返回值 | 返回值描述 |
0 | 关闭成功 |
负数 | 关闭失败 |
```c
int32_t ret;
uint8_t snsClkSource;
/* 传感器的时钟信号线号为0 */
snsClkSource = 0;
/* 关闭MIPI上的Sensor时钟 */
ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret);
return -1;
}
```
释放MIPI CSI控制器操作句柄
MIPI CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示:
void MipiCsiClose(DevHandle handle);
该函数会释放掉由MipiCsiOpen申请的资源。
表 17 MipiCsiClose的参数和返回值描述
参数 | 参数描述 |
---|---|
handle | MIPI CSI控制器操作句柄 |
MipiCsiClose(MIPIHandle); /* 释放掉MIPI CSI控制器操作句柄 */
使用实例
MIPI CSI完整的使用示例如下所示:
#include "hdf.h"
#include "MIPI_csi_if.h"
void PalMipiCsiTestSample(void)
{
uint8_t id;
int32_t ret;
uint8_t comboDev;
uint8_t snsClkSource;
uint8_t devno;
enum LaneDivideMode mode;
enum PhyCmvMode mode;
struct ComboDevAttr attr;
struct ExtDataType dataType;
DevHandle MipiCsiHandle = NULL;
/* 控制器ID号 */
id = 0;
/* 获取控制器操作句柄 */
MipiCsiHandle = MipiCsiOpen(id);
if (MipiCsiHandle == NULL) {
HDF_LOGE("MipiCsiOpen: failed!\n");
return;
}
/* lane模式参数为0 */
mode = LANE_DIVIDE_MODE_0;
/* 设置MIPI RX的 Lane分布 */
ret = MipiCsiSetHsMode(MipiCsiHandle, mode);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret);
return;
}
/* 通路序号为0 */
comboDev = 0;
/* 使能MIPI的时钟 */
ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret);
return;
}
/* 复位MIPI RX */
ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret);
return;
}
/* 传感器的时钟信号线号为0 */
snsClkSource = 0;
/* 使能MIPI上的sensor时钟 */
ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret);
return;
}
/* 复位sensor */
ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret);
return;
}
/* MIPI参数配置如下 */
(void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
attr.devno = 0; /* 设备0 */
attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */
attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */
attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */
attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */
attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */
attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */
/* 写入配置数据 */
ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret);
return;
}
/* 共模电压模式参数为0 */
mode = PHY_CMV_GE1200MV;
/* 设备编号为0 */
devno = 0;
/* 设置共模电压模式 */
ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret);
return;
}
/* 通路序号为0 */
comboDev = 0;
/* 撤销复位MIPI RX */
ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret);
return;
}
/* 关闭MIPI的时钟 */
ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret);
return;
}
/* 传感器撤销复位信号线号为0 */
snsResetSource = 0;
/* 撤销复位sensor */
ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret);
return;
}
/* 关闭MIPI上的sensor时钟 */
ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
if (ret != 0) {
HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret);
return;
}
/* 释放MIPI DSI设备句柄 */
MipiCsiClose(MipiCsiHandle);
}