海思ISP代码执行流程

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线程中处理事务。

你可能感兴趣的:(Hi3518EV300)