quickstart.c,mpi_isp_entry.c, mpi_isp.c
步骤1、配置MIPI
流程如下:重点参考《MIPI使用指南》API。
1.1、开始MIPI
s32Ret = QuickStart_StartMIPI(pstViConfig);
1.2、获取land_divide_mode
lane_divide_mode = SAMPLE_COMM_VI_GetMipiLaneDivideMode(pstViConfig);
1.3、设置 MIPI Rx 的 Lane 分布
s32Ret = SAMPLE_COMM_VI_SetMipiHsMode(lane_divide_mode);
1.4、打开 MIPI 设备的时钟
s32Ret = SAMPLE_COMM_VI_EnableMipiClock(pstViConfig);
1.5、复位 MIPI Rx。
s32Ret = SAMPLE_COMM_VI_ResetMipi(pstViConfig);
1.6、设置 MIPI设备属性。
s32Ret = SAMPLE_COMM_VI_SetMipiAttr(pstViConfig);
1.7、重启MIPI
s32Ret = SAMPLE_COMM_VI_UnresetMipi(pstViConfig);
1.8、设置MIPI寄存器
QuickStart_SetMIPIReg();
MIPI Rx 提供对接 sensor 时序的功能。提供 ioctl 接口,可用的命令如下:
1.1、HI_MIPI_SET_DEV_ATTR:设置 MIPI、SLVS 和并口设备属性。
1.2、HI_MIPI_SET_HS_MODE:设置 MIPI Rx 的 Lane 分布。
1.3、HI_MIPI_SET_PHY_CMVMODE:设置共模电压模式。
1.4、HI_MIPI_RESET_SENSOR:复位 sensor。
1.5、HI_MIPI_UNRESET_SENSOR:撤销复位 sensor。
1.6、HI_MIPI_RESET_MIPI:复位 MIPI Rx。
1.7、HI_MIPI_UNRESET_MIPI:撤销复位 MIPI Rx。
1.8、HI_MIPI_RESET_SLVS:复位 SLVS。
1.9、HI_MIPI_UNRESET_SLVS:撤销复位 SLVS。
1.10、HI_MIPI_ENABLE_MIPI_CLOCK:打开 MIPI 设备的时钟。
1.11、HI_MIPI_DISABLE_MIPI_CLOCK:关闭 MIPI 设备的时钟。
1.12、HI_MIPI_ENABLE_SLVS_CLOCK:打开 SLVS 设备的时钟。
1.13、HI_MIPI_DISABLE_SLVS_CLOCK:关闭 SLVS 设备的时钟。
1.14、HI_MIPI_ENABLE_SENSOR_CLOCK:打开 SENSOR 的时钟。
1.15、HI_MIPI_DISABLE_SENSOR_CLOCK:关闭 SENSOR 的时钟。
1.16、HI_MIPI_CLEAR:清除设备相关的配置。
步骤2、Sensor向3A算法 、ISP注册回调函数
2.1 Sensor向ISP注册回调函数: HI_S32 HI_MPI_ISP_SensorRegCallBack(ISP_DEV IspDev, SENSOR_ID SensorId,
ISP_SENSOR_REGISTER_S *pstRegister);
注意点:
1、SensorId 是 sensor 库中自定义的值,主要用于校对向 ISP 注册的 sensor 和向 3A 注
册的 sensor 是否为同一个 sensor。
2、ISP 通过 sensor 注册的一系列回调接口,获取差异化的初始化参数,并控制sensor。
3、示例
ISP_DEV IspDev = 0;
HI_S32 s32Ret;
ISP_SENSOR_REGISTER_S stIspRegister;
ISP_SENSOR_EXP_FUNC_S *pstSensorExpFunc = &stIspRegister.stSnsExp;
memset(pstSensorExpFunc, 0, sizeof(ISP_SENSOR_EXP_FUNC_S));
pstSensorExpFunc->pfn_cmos_sensor_init = sensor_init;
pstSensorExpFunc->pfn_cmos_get_isp_default = cmos_get_isp_default;
pstSensorExpFunc->pfn_cmos_get_isp_black_level = cmos_get_isp_black_level;
pstSensorExpFunc->pfn_cmos_set_pixel_detect = cmos_set_pixel_detect;
pstSensorExpFunc->pfn_cmos_set_wdr_mode = cmos_set_wdr_mode;
pstSensorExpFunc->pfn_cmos_get_wdr_attr = cmos_get_wdr_attr;
pstSensorExpFunc->pfn_cmos_get_sns_reg_info = cmos_get_sns_regs_info;
pstSensorExpFunc->pfn_cmos_get_sensor_max_resolution =
cmos_get_sensor_max_resolution;
pstSensorExpFunc->pfn_cmos_set_image_mode = cmos_set_image_mode;
s32Ret = HI_MPI_ISP_SensorRegCallBack(IspDev, IMX178_ID, &stIspRegister);
if (s32Ret)
{
printf("sensor register callback function failed!\n");
return s32Ret;
}
2.2 Sensor向3A算法注册回调函数:
2.2.1、HHI_S32 HI_MPI_AE_SensorRegCallBack(ISP_DEV IspDev, ALG_LIB_S *pstAeLib,
SENSOR_ID SensorId, AE_SENSOR_REGISTER_S *pstRegister);
示例:
ALG_LIB_S stLib;
AE_SENSOR_REGISTER_S stAeRegister;
AE_SENSOR_EXP_FUNC_S *pstExpFuncs = &stAeRegister.stSnsExp;
memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S));
pstExpFuncs->pfn_cmos_get_ae_default = cmos_get_ae_default;
pstExpFuncs->pfn_cmos_fps_set = cmos_fps_set;
pstExpFuncs->pfn_cmos_slow_framerate_set= cmos_slow_framerate_set;
pstExpFuncs->pfn_cmos_inttime_update = cmos_inttime_update;
pstExpFuncs->pfn_cmos_gains_update = cmos_gains_update;
pstExpFuncs->pfn_cmos_again_calc_table = cmos_again_calc_table;
pstExpFuncs->pfn_cmos_dgain_calc_table = cmos_dgain_calc_table;
pstExpFuncs->pfn_cmos_get_inttime_max = cmos_get_inttime_max;
ISP_DEV IspDev = 0;
stLib.s32Id = 0;
strcpy(stLib.acLibName, HI_AE_LIB_NAME);
s32Ret = HI_MPI_AE_SensorRegCallBack(IspDev, &stLib, IMX104_ID,
&stAeRegister);
if (s32Ret)
{
printf("sensor register callback function to ae lib failed!\n");
return s32Ret;
}
2.2.2、HI_S32 HI_MPI_AWB_SensorRegCallBack (ISP_DEV IspDev, ALG_LIB_S *pstAwbLib,
SENSOR_ID SensorId, AWB_SENSOR_REGISTER_S *pstRegister);
示例:
ALG_LIB_S stLib;
AWB_SENSOR_REGISTER_S stAwbRegister;
AWB_SENSOR_EXP_FUNC_S *pstExpFuncs = &stAwbRegister.stSnsExp;
memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S));
pstExpFuncs->pfn_cmos_get_awb_default = cmos_get_awb_default;
ISP_DEV IspDev = 0;
stLib.s32Id = 0;
strcpy(stLib.acLibName, HI_AWB_LIB_NAME);
s32Ret = HI_MPI_AWB_SensorRegCallBack(&stLib, IMX178_ID, &stAwbRegister);
if (s32Ret)
{
printf("sensor register callback function to awb lib failed!\n");
return s32Ret;
}
步骤3、3A算法向ISP注册回调函数
(AE,AWB,AF存在反注册函数,使用海思3A算法库,无需关心。自定义时需要注册这些回调函数)
HI_S32 HI_MPI_AE_Register(ISP_DEV IspDev, ALG_LIB_S *pstAeLib);
HI_S32 HI_MPI_AWB_Register(ISP_DEV IspDev, ALG_LIB_S *pstAwbLib);
AE:HI_S32 HI_MPI_ISP_AELibRegCallBack(ISP_DEV IspDev, ALG_LIB_S *pstAeLib,
ISP_AE_REGISTER_S *pstRegister);
注意点:
ISP 提供统一的 AE 算法库接口,初始化、运行、控制、销毁 AE 算法库。使用海思
AE 算法库时,不需要关注此接口;
示例:
ISP_AE_REGISTER_S stRegister;
HI_S32 s32Ret = HI_SUCCESS;
stRegister.stAeExpFunc.pfn_ae_init = AeInit;
stRegister.stAeExpFunc.pfn_ae_run = AeRun;
stRegister.stAeExpFunc.pfn_ae_ctrl = AeCtrl;
stRegister.stAeExpFunc.pfn_ae_exit = AeExit;
s32Ret = HI_MPI_ISP_AeLibRegCallBack(IspDev, pstAeLib, &stRegister);
if (HI_SUCCESS != s32Ret)
{
printf("Hi_ae register failed!\n");
}
AWB:HI_S32 HI_MPI_ISP_AWBLibRegCallBack(ISP_DEV IspDev, ALG_LIB_S *pstAwbLib,
ISP_AWB_REGISTER_S *pstRegister);
注意点:
ISP 提供统一的 AWB 算法库接口,初始化、运行、控制、销毁 AWB 算法库。使用海
思 AWB 算法库时,不需要关注此接口。
Register
pfn_awb_init
pfn_awb_run
pfn_awb_ctrl
pfn_awb_exit
AF:HI_S32 HI_MPI_ISP_AFLibRegCallBack(ISP_DEV IspDev, ALG_LIB_S *pstAfLib,
ISP_AF_REGISTER_S *pstRegister);
注意点:
ISP 提供统一的 AF 算法库接口,初始化、运行、控制、销毁 AF 算法库。使用海思 AF
算法库时,不需要关注此接口;
Register
pfn_af_init
pfn_af_run
pfn_af_ctrl
pfn_af_exit
步骤4、ISP外部寄存器初始化
HI_S32 HI_MPI_ISP_MemInit(ISP_DEV IspDev);
注意点:
1、外部寄存器初始化前需要确保 ko 已加载,sensor 向 ISP 注册了回调函数。
2、调用本接口后,才能调用 HI_MPI_ISP_SetWDRMode 和 HI_MPI_ISP_SetPubAttr
分别配置 WDR 模式和图像公共属性。
3、、不支持多进程,必须要与 sensor_register_callback、HI_MPI_AE_Register、
HI_MPI_AWB_Register、HI_MPI_ISP_Init、HI_MPI_ISP_Run、HI_MPI_ISP_Exit
接口在同一个进程调用。
4、不支持重复调用本接口。
5、推荐调用 HI_MPI_ISP_Exit 后,再调用本接口重新初始化。
6、Huawei LiteOS 没有内核模块加载概念,Linux load ko 过程对应 Huawei LiteOS
release/ko 下 sdk_init.c 中执行的相关过程。
步骤5、配置ISP的WDR模式
HI_S32 HI_MPI_ISP_SetWDRMode(ISP_DEV IspDev, const ISP_WDR_MODE_S
*pstWDRMode);
注意点
1、ISP 启动时,需要确保已调用 HI_MPI_ISP_MemInit 初始化 ISP 外部寄存器。
2、支持在 ISP 运行之后,调用本接口实现宽动态切换。
3、如果在相同的 WDR 模式之间切换时,请上层应用程序不要重新设置 MIPI 接口,
否则会导致采集不到图像。在相同的 WDR 模式之间进行切换时,建议上层应用
程序判断当前的 WDR 模式与要切换的 WDR 模式是否相同,如果相同,则可以直
接退出即可,不用进行切换。
步骤6、配置图像公共属性
HI_S32 HI_MPI_ISP_SetPubAttr(ISP_DEV IspDev, const ISP_PUB_ATTR_S
*pstPubAttr);
注意点:
1、图像属性即对应的 sensor 的采集属性。
2、ISP 启动时,需要确保已调用 HI_MPI_ISP_MemInit 初始化 ISP 外部寄存器。
3、支持在 ISP 运行之后,调用本接口实现动态分辨率和帧率切换。
4、调用本接口后 ISP 内的处理流程:a) ISP firmware 判断图像分辨率和帧率是否变
化,若都不变则直接返回;否则,ISP firmware 会调用 sensor cmos.c 里面的
cmos_set_image_mode 函数改变 sensor 模式;b) 若 sensor 模式改变(返回值为
0),则 ISP firmware 会调用 sensor_init 函数重新配置 sensor;c) ISP firmware 将帧
率信息传给海思 AE 库,并决定是否更改帧率。
5、若调用本接口实现动态分辨率和帧率切换时 sensor 模式发生了改变,请参照
sample 提供的切换流程操作(先停掉 Vi 设备,再切换,最后启动 Vi 设备)。另
外,动态分辨率和帧率切换时,切换的分辨率和帧率必须有一项要不同(即不能
切换到自己本身),否则,sensor 可能不会重新初始化而导致异常。
6、使用 Vi Dev 和 ISP 提供的裁剪功能时,需要注意:若裁剪后的分辨率和帧率,小
于另一组 sensor 模式的分辨率和帧率,则调用本接口会先切换到对应的 sensor 模
式。
7、用户可以更改 sensor cmos.c 里面的 cmos_set_image_mode 函数调整 sensor 模式切
换的顺序。如只提供了 5M30fps 和 1080P60fps 初始化序列的 sensor,若要运行
1080P30fps,可以从 5M30fps 裁剪得到,也可以从 1080P60fps 降帧得到,修改
cmos_set_image_mode 函数实现即可。
步骤7、初始化ISP
HI_S32 HI_MPI_ISP_Init(ISP_DEV IspDev);
注意点:
1、初始化前需要确保 ko 已加载,sensor 向 ISP 注册了回调函数。
2、初始化前需要确保已调用 HI_MPI_ISP_MemInit 初始化 ISP 外部寄存器。
3、初始化前需要确保已调用 HI_MPI_ISP_SetWDRMode 和 HI_MPI_ISP_SetPubAttr
分别配置 WDR 模式和图像公共属性。
4、不支持多进程,必须要与 sensor_register_callback、HI_MPI_AE_Register、
HI_MPI_AWB_Register、HI_MPI_ISP_MemInit、HI_MPI_ISP_Run、
HI_MPI_ISP_Exit 接口在同一个进程调用。
5、不支持重复调用本接口。
6、推荐调用 HI_MPI_ISP_Exit 后,再调用本接口重新初始化。
7、如果使能 JPEG DCF 功能,调用本接口前须调用 HI_MPI_VB_SetSupplementConf
(请参考《HiMPP IPC V2.0 媒体处理软件开发参考》的系统控制章节 2.2 小节),
将 stSupplementConf 配置为 VB_SUPPLEMENT_JPEG_MASK。
8、Huawei LiteOS 没内核模块加载概念,Linux load ko 过程对应 Huawei LiteOS
release/ko 下 sdk_init.c 中执行的相关过程
步骤8、运行ISP
HI_S32 HI_MPI_ISP_Run(ISP_DEV IspDev);
注意点
1、运行前需要确保 sensor 已经初始化,并且向 ISP 注册了回调函数。
2、运行前需要确保已调用 HI_MPI_ISP_Init 初始化 ISP。
3、不支持多进程,必须要与 sensor_register_callback、HI_MPI_AE_Register、
HI_MPI_AWB_Register、HI_MPI_ISP_MemInit、HI_MPI_ISP_Init、
HI_MPI_ISP_Exit 接口在同一个进程调用。
4、该接口是阻塞接口,建议用户采用实时线程处理
最终在QuickStart_ISP_Thread线程中处理事务。