多sensor功能实现及代码流程
1. 硬件说明¶
1.1. 硬件图说明¶
图 1-1:硬件实物图
如上图,Pudding 系列板子有两路4 lane MIPI RX:
-
mipi0
可以作一路4 lane MIPI RX,也可以分为两路 2 lane 的MIPI RX:
-
mipi00
-
mipi01
-
mipi1
-
注意:当mipi0分成两路2 lane MIPI RX的时候,kernel dts需要更改为infinity6e-ssc012b-s01a-2+2mipi.dts或者infinity6e-ssc013a-s0a1-2+2mipi.dts
1.2. 多sensor 的使用场景¶
-
双sensor接两路4 lane sensor ,其中一路接如上图mipi0,另一路接如图 mipi1;
-
双sensor接两路2 lane sensor,其中一路接如图mipi00,另一路接mipi01;
-
三sensor 接两路 2 lane sensor + 一路4 lane sensor,其中一路接如图mipi00 ,一路接mipi01,一路接 mipi1。
2. 流程图说明¶
2.1. SNR PAD与VIF流程图¶
图 2-1:SNR与VIF流程图
SNR PAD0 对应mipi0(当mipi0作1路4 lane mipi 使用的时候)/mipi00(当mipi0 分成两路2 lane mipi 使用的时候)
SNR PAD1 对应mipi1
SNR PAD2 对应mipi01 (当mipi0 分成两路2 lane mipi 使用的时候)
多sensor连接方式:
-
双sensor 接两路4 lane sensor,其中一路接SNR PAD0 另一路接SNR PAD1;分别通过mipi0 和mipi1 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD1->VIF DEV2->VIF Channel 8。
-
双sensor 接两路2 lane sensor,其中一路接SNR PAD0, 另一路接SNR PAD2;分别通过mipi00 和mipi01 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD2->VIF DEV1->VIF Channel 4。
-
三sensor 接两路2 lane sensor,其中一路接pad0 一路接pad2 一路接pad3;分别通过mipi00 、mipi01、mipi1 连接VIF,因此SNR PAD0->VIF DEV0->VIF Channel 0; SNR PAD2->VIF DEV1->VIF Channel 4; SNR PAD1->VIF DEV2->VIF Channel 8
2.2. 多sensor流程图¶
图 2-2:4lane+4lane双sensor流程图
-
接入两路sensor;把两路sensor采集到的raw数据,通过mipi0/1协议传送到VIF device 0/2;
-
VIF 与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF2 连VPE Chn1;
-
ISP 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,经过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。
图 2-3:2lane+2lane双sensor流程图
-
接入两路sensor;把两路sensor采集到的raw数据,通过mipi00/01协议传送到vif device 0/1。
-
VIF与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF1连VPE Chn1。
-
ISP 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。
图 2-4:2lane+2lane+4lane 3sensor流程图
-
接入三路sensor;把三路sensor采集到的raw数据,通过mipi00/01/1协议传送到vif device 0 / 1 /2
-
VIF与VPE Chn之间的bind mode选择frame mode或者unbind 方式,VIF0 连VPE Chn0,VIF1连VPE Chn1,VIF2连VPE Chn2;
-
Isp 处理完后的数据,会通过WDMA把数据传送到各个VPE input port,过crop、scale等操作,最终输出到VPE out port,对应的VPE out port 可以接DIVP或者VENC;当然,如果遇到DIVP的scale性能不够等问题,可以考虑DIVP后级连上DIVP。
3. DEMO CODE¶
3.1. Demo code 编译及执行¶
以Pudding接IMX405+IMX274为例,其中IMX405接pad0,IMX274插pad1
在/customer/demo.sh
脚本(系统启动后会启动)中配置,insmod ko:
insmod /config/modules/4.9.84/imx415_MIPI.ko chmap=1 insmod /config/modules/4.9.84/imx274_MIPI.ko chmap=2
其中chmap 的二进制位表示sensor 对应接入的pad ,如上IMX405 接pad0 chmap 为二进制01,值为1,IMX274 接pad1 ,二进制为10,值为2。
将编译生成的demo prog_dualsensor cp 到customer 目录下,执行./prog_dualsensor 1 1 0
。Demo code位于:sdk\verify\mi_demo\source\dualsensor
3.2. Demo code 分析¶
-
调用ST_StreamInit 分别创建每个sensor 出流通道
-
VIF 创建
ST_VIF_PortInfo_T stVifPortInfoInfo; memset(&stVifPortInfoInfo, 0, sizeof(ST_VIF_PortInfo_T)); stVifPortInfoInfo.u32RectX = stSnrPlane0Info.stCapRect.u16X; stVifPortInfoInfo.u32RectY = stSnrPlane0Info.stCapRect.u16Y; stVifPortInfoInfo.u32RectWidth = u32CapWidth; stVifPortInfoInfo.u32RectHeight = u32CapHeight; stVifPortInfoInfo.u32DestWidth = u32CapWidth; stVifPortInfoInfo.u32DestHeight = u32CapHeight; stVifPortInfoInfo.eFrameRate = eFrameRate; stVifPortInfoInfo.ePixFormat = ePixFormat;//E_MI_SYS_PIXEL_FRAME_RGB_BAYER_12BPP_GR; STCHECKRESULT(ST_Vif_CreatePort(vifChn, 0, &stVifPortInfoInfo)); STCHECKRESULT(ST_Vif_StartPort(0, vifChn, 0));
-
VPE 创建红的eRunningMode需要设置为E_MI_VPE_RUN_CAM_MODE,是ISP 内部走frame mode,如果ISP 内部走的real time mode,ISP 硬件将不能分时复用,导致另外一路VIF数据得不到ISP处理。
/************************************************ Step3: init VPE (create one VPE) *************************************************/ ST_VPE_ChannelInfo_T stVpeChannelInfo; memset(&stVpeChannelInfo, 0, sizeof(ST_VPE_ChannelInfo_T)); stVpeChannelInfo.u16VpeMaxW = u32CapWidth; stVpeChannelInfo.u16VpeMaxH = u32CapHeight; stVpeChannelInfo.u32X = 0; stVpeChannelInfo.u32Y = 0; stVpeChannelInfo.u16VpeCropW = 0; stVpeChannelInfo.u16VpeCropH = 0; stVpeChannelInfo.eRunningMode = E_MI_VPE_RUN_CAM_MODE; stVpeChannelInfo.eFormat = ePixFormat;//E_MI_SYS_PIXEL_FRAME_RGB_BAYER_12BPP_GR; stVpeChannelInfo.eHDRtype = eVpeHdrType; if(eSnrPad == E_MI_SNR_PAD_ID_0) stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR0; else if(eSnrPad == E_MI_SNR_PAD_ID_1) stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR1; else if(eSnrPad == E_MI_SNR_PAD_ID_2) stVpeChannelInfo.eBindSensorId = E_MI_VPE_SENSOR2; STCHECKRESULT(ST_Vpe_CreateChannel(vpechn, &stVpeChannelInfo)); STCHECKRESULT(ST_Vpe_StartChannel(vpechn));
-
VIF 与VPE之间的stBindInfo.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE;
/************************************************ Step1: bind VIF->VPE *************************************************/ ST_Sys_BindInfo_T stBindInfo; memset(&stBindInfo, 0x0, sizeof(ST_Sys_BindInfo_T)); stBindInfo.stSrcChnPort.eModId = E_MI_MODULE_ID_VIF; stBindInfo.stSrcChnPort.u32DevId = s32vifDev; stBindInfo.stSrcChnPort.u32ChnId = vifChn; stBindInfo.stSrcChnPort.u32PortId = 0; stBindInfo.stDstChnPort.eModId = E_MI_MODULE_ID_VPE; stBindInfo.stDstChnPort.u32DevId = 0; stBindInfo.stDstChnPort.u32ChnId = vpechn; stBindInfo.stDstChnPort.u32PortId = 0; stBindInfo.u32SrcFrmrate = 30; stBindInfo.u32DstFrmrate = 30; stBindInfo.eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE; STCHECKRESULT(ST_Sys_Bind(&stBindInfo));