AM62P: DSS safety issue

Part Number: AM62P
Other Parts Discussed in Thread: SYSCONFIG, UNIFLASH

Hi Expert,

In the dss_safety_test example,  it was found that the VP output shown in the logs is always true, regardless of whether the destructive code is removed or not.
So what appears on the UART terminal if we delete the code below?

" /* Corrupt frame to introduce data integrity error */
if(gLoopCount == DISP_FRAME_CORRUPT_NUM)
{
for(uint32_t count = 0; count < gDssConfigPipelineParams.inHeight[instCnt] * 

gDssConfigPipelineParams.pitch[instCnt][0]; count++)
{
*(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
}
}"

BR,

Biao

  • Hi,

    The assigned expert is out of office this week Please expect a response by early next week.

    Regards,
    Johnson

  • Hello,

    Looking forward to your reply, but please as soon as possible!

    Thanks.

  • Hi,
    Let me cross-check your UART observation at my end.

    Meanwhile, keeping aside the UART output, if you try reading the safety signature registers via CCS or some debugger, you should be able to observe a constant signature in that register (provided that the corruption code has been commented/removed).

    Were there any other changes from the default sysconfig/driver in your configuration?

  • Hello,

    Yes, I only removed the corruption-related code and made no other modifications.

    And we just want to know if it's normal. Actually, our instrument cluster needs to monitor more than four icons. Therefore, we would like the monitored regions to switch accordingly when changing between different screens. For example, in the first screen, we monitor four regions, and in the second screen, we monitor another set of four new regions. However, we're not sure if this is feasible—our actual testing shows that the VP (vision processing) result in the first set of logs always returns true, while the VP result in the second set of logs always returns false.

    Additionally, we’d also like to know whether it’s possible to use the R5 core solely for monitoring purposes, without handling any display-related tasks.

    Thanks.

     

  • Hi,
    Can you please elaborate more on your setup.
    You mentioned you are using 2 screens, which I assume are connected to 2 different VP (Video Ports) on DSS. In that case, Can you share what VPs/Display interfaces you are using/configuring?
    The content being streamed on both screens are the same or different? 
    There are 4 safety regions per video port, so if you are using 2 VPs, you can have separate safety regions for each.

    Additionally, we’d also like to know whether it’s possible to use the R5 core solely for monitoring purposes, without handling any display-related tasks.

    Let me get back to you on the feasibility of this, and UART output expectation by end of this week.

  • We're using a single VP, but as mentioned previously, our ultimate goal is that the R5 core dose not to handle any display output at all—it's only responsible for monitoring.

    We need to monitor more than 4 tell-tales, but the hardware limits us to only 4 safety regions per VP. To work around this, we’re considering a time-division (polling-based) switching approach:

    • In the first cycle, we display (or render) a group of 4 tell-tales and configure the first set of 4 safety regions to monitor them.
    • In the next cycle, we switch to a new group of 4 tell-tales and reconfigure the safety regions accordingly to monitor this new set.

    We’re not sure if this is clear enough—just imagine an instrument cluster that contains many tell-tales. Is this approach feasible?


    Let me get back to you on the feasibility of this, and UART output expectation by end of this week.

    Got it, thanks!

  • Hello,

    Today is the last day of the week – looking forward to your reply!

    Thanks.

  • Hi Wang,
    Thanks for your patience.

    In the dss_safety_test example,  it was found that the VP output shown in the logs is always true, regardless of whether the destructive code is removed or not.

    The DispApp_logSafetyCheckData() function which prints passed/failed firstly assumes that the the data corruption happened, and then reports if the corruption was detected or not, given that corruption was there. Moreover, it will check both Video Pipelines (VID[L]) and Video Port(VP) safety regions, and only if both were able to detect the error, only then Pass is shown. 
    Now if, you remove the corruption code, that means the output frames are always constant. In the VP safety regions, 2 are configured to check Freeze_Frames, and 2 are configured to check Data_Integrity. If there is no data corruption, the frames are anyhow constant and you'll see Freeze_Frame interrupts trigger as true. But, the Data_Integrity interrupt trigger becomes false in no corruption case (as is expected).
    You may check this code file (I added some register dump logs) which will help you observe register diff between corruption and no corruption case:

    /*
     *  Copyright (C) 2023 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file dss_safety_test.c
     *
     *  \brief DSS sample application that configures and tests DSS safety features
     *         (Freeze Frame Detect and Data Integrity Check).
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <stdio.h>
    #include <string.h>
    #include <drivers/dss.h>
    #include <drivers/fvid2.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <kernel/dpl/AddrTranslateP.h>
    #include "ti_drivers_open_close.h"
    #include "ti_drivers_config.h"
    #include "ti_board_open_close.h"
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* Number of frames */
    #define DISP_NUM_FRAMES_COUNT               ((uint32_t)100U)
    
    /* Max frame size based on resolution */
    #define DISP_FRAME_SIZE_MAX                 (3840U*1080U)
    
    /* Max pixel width */
    #define DISP_FRAME_PIXEL_WIDTH_MAX          (4U)
    
    /* Corrupt frame number */
    #define DISP_FRAME_CORRUPT_NUM              (70U)
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    typedef struct
    {
        uint32_t safetyInterupt;
        /**< Flag to check interupt received */
        uint32_t vpId;
        /**< Video Port Id */
        uint32_t pipeId;
        /**< Pipe Id */
        uint32_t frameCount;
        /**< Frame Count */
        uint32_t safetyCheckMode;
        /**< Mode of operation of the safety check module */
        Dss_DctrlVpSafetyCbData cbData;
        /**< Safety Error callback data to be returned to application */
    } Dss_safetyTestCbData;
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static void DispApp_init(Dss_Object *appObj);
    static void DispApp_deInit(Dss_Object *appObj);
    static void DispApp_create(Dss_Object *appObj);
    static void DispApp_delete(Dss_Object *appObj);
    static int32_t DispApp_configDctrl(Dss_Object *appObj);
    static int32_t DispApp_runTest(Dss_Object *appObj);
    static void DispApp_initPipelineParams(Dss_Object *appObj);
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj);
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData);
    static void DispApp_initDssParams(Dss_Object *appObj);
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData);
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData);
    static int32_t DispApp_logSafetyCheckData();
    
    extern void Disp_prepareFrameBuffer(uint32_t instCount,
                                uint32_t inDataFmt, \
                                uint32_t inWidth, \
                                uint32_t inHeight,\
                                uint32_t pitch, \
                                void* \
                                frameBuffer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE]);
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    uint32_t gStopProfileTime, gStartProfileTime;
    
    /*
     * Global frame buffers. Maximum frames per handle is considered 2 and first frame
     * is used for first pipeline instance and other is used for second pipeline instance.
     */
    uint8_t gFirstPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096)));
    uint8_t gSecondPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096))) ;
    
    /* Pointer to frame buffers per pipleline */
    void *gfirstPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    void *gsecondPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    
    static Dss_safetyTestCbData gSafetyCallbackDataVP[CONFIG_DSS_NUM_SAFETY_REGIONS];
    static Dss_safetyTestCbData gSafetyCallbackDataVID;
    static Dss_safetyTestCbData gSafetyCallbackDataVIDL;
    
    static volatile uint32_t gLoopCount;
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void DispApp_initFrames()
    {
        uint32_t instCnt = 0;
        uint32_t numPipes = gDssConfigPipelineParams.numTestPipes <= DSS_DISP_INST_MAX \
                            ? gDssConfigPipelineParams.numTestPipes : DSS_DISP_INST_MAX;
    
        for(instCnt = 0; instCnt < CONFIG_DSS_NUM_FRAMES_PER_PIPELINE; instCnt++)
        {
            gfirstPipeFrameBufferPointer[instCnt] = &gFirstPipelineFrameBuf[instCnt];
            gsecondPipeFrameBufferPointer[instCnt] = &gSecondPipelineFrameBuf[instCnt];
        }
    
        for(instCnt = 0U; instCnt< numPipes ; instCnt++)
        {
            if(instCnt == 0)
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gfirstPipeFrameBufferPointer);
            }
            else
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gsecondPipeFrameBufferPointer);
            }
        }
    }
    
    /*
     * DSS display test
     */
    void dss_safety_test_main(void *args)
    {
        int32_t retVal = SystemP_SUCCESS;
    
        /* Initialise frames */
        DispApp_initFrames();
    
        DispApp_init(&gDssObjects[CONFIG_DSS0]);
    
        DebugP_log("DSS display application started...\r\n");
    
        retVal = DispApp_runTest(&gDssObjects[CONFIG_DSS0]);
    
        DispApp_deInit(&gDssObjects[CONFIG_DSS0]);
    
        retVal = DispApp_logSafetyCheckData();
    
        if(SystemP_SUCCESS == retVal)
        {
            DebugP_log("DSS Safety Test Passed!!\r\n");
        }
        else
        {
            DebugP_log("DSS Safety Test Failed!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_init(Dss_Object *appObj)
    {
        int32_t         retVal = FVID2_SOK;
        Fvid2_InitPrms  initPrms;
    
        Fvid2InitPrms_init(&initPrms);
        retVal = Fvid2_init(&initPrms);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Fvid2 Init Failed!!!\r\n");
        }
    
        Dss_initParamsInit(&appObj->initParams);
    
        Dss_init(&appObj->initParams);
    
        if(FVID2_SOK == retVal)
        {
            /* Create DCTRL handle, used for common driver configuration */
            appObj->dctrlHandle = Fvid2_create(
                DSS_DCTRL_DRV_ID,
                DSS_DCTRL_INST_0,
                NULL,
                NULL,
                NULL);
            if(NULL == appObj->dctrlHandle)
            {
                DebugP_log("DCTRL Create Failed!!!\r\n");
            }
        }
    
        if(appObj->oldiParams != NULL)
        {
            Dss_setOLDITxPowerDown(appObj->oldiParams->oldiCfg.oldiMapType, TRUE);
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("DispApp_init() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_deInit(Dss_Object *appObj)
    {
        int32_t  retVal = FVID2_SOK;
    
        /* Delete DCTRL handle */
        retVal = Fvid2_delete(appObj->dctrlHandle, NULL);
        retVal += Dss_deInit();
        retVal += Fvid2_deInit(NULL);
        if(retVal != FVID2_SOK)
        {
             DebugP_log("DCTRL handle delete failed!!!\r\n");
        }
        else
        {
             DebugP_log("DispApp_deInit() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_runTest(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
        Fvid2_FrameList  frmList;
    
        /* Create driver */
        DispApp_create(appObj);
    
        DebugP_log("Starting display ... !!!\r\n");
        DebugP_log("Display in progress ... DO NOT HALT !!!\r\n");
    
        /* Start driver */
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
    
            retVal = Fvid2_start(instObj->drvHandle, NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Display Start Failed!!!\r\n");
                break;
            }
        }
    
        gStartProfileTime = (ClockP_getTimeUsec() / 1000U);
    
        while(gLoopCount++ < DISP_NUM_FRAMES_COUNT)
        {
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
                (void) SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
                retVal = Fvid2_dequeue(instObj->drvHandle,
                                       &frmList,
                                       0U,
                                       FVID2_TIMEOUT_NONE);
    
                /* Corrupt frame to introduce data integrity error */
    //            if(gLoopCount == DISP_FRAME_CORRUPT_NUM)
    //            {
    //                for(uint32_t count = 0; count < gDssConfigPipelineParams.inHeight[instCnt] * \
    //                gDssConfigPipelineParams.pitch[instCnt][0]; count++)
    //                {
    //                    *(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
    //                }
    //            }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
                    if(FVID2_SOK != retVal)
                    {
                        DebugP_log("Display Queue Failed!!!\r\n");
                        break;
                    }
                }
                else if (FVID2_EAGAIN == retVal)
                {
                    /* Do nothing as this is first callback */
                }
                else
                {
                    /* Error */
                    DebugP_log("Display Dequeue Failed!!!\r\n");
                    break;
                }
            }
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x302022a4)));
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x302062a4)));
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a090)));
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a094)));
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a098)));
            DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a09c)));
            DebugP_log("--------------------------------------------------------------------------------");
        }
    
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
            retVal  = Fvid2_stop(instObj->drvHandle, NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Display Stop Failed!!!\r\n");
                break;
            }
        }
    
        gStopProfileTime = (ClockP_getTimeUsec() / 1000U);
    
        if(FVID2_SOK == retVal)
        {
            /* Delete driver */
            DispApp_delete(appObj);
        }
    
        return (retVal != FVID2_SOK? SystemP_FAILURE:SystemP_SUCCESS);
    }
    
    static void DispApp_initDssParams(Dss_Object *appObj)
    {
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
    
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        globalDssParams = &appObj->globalDssParams;
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
    
        Dss_dctrlVpParamsInit(vpParams);
        Dss_dctrlAdvVpParamsInit(advVpParams);
        Dss_dctrlOverlayParamsInit(overlayParams);
        Dss_dctrlOverlayLayerParamsInit(layerParams);
        Dss_dctrlGlobalDssParamsInit(globalDssParams);
    
        /* Configure VP params */
        vpParams->vpId = gDssVpParams.vpId;
        vpParams->lcdOpTimingCfg.mInfo.standard = gDssVpParams.lcdOpTimingCfg.mInfo.standard;
        vpParams->lcdOpTimingCfg.mInfo.width = gDssVpParams.lcdOpTimingCfg.mInfo.width;
        vpParams->lcdOpTimingCfg.mInfo.height = gDssVpParams.lcdOpTimingCfg.mInfo.height;
        vpParams->lcdOpTimingCfg.mInfo.hFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.hBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.hSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.hSyncLen;
        vpParams->lcdOpTimingCfg.mInfo.vFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.vBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.vSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.vSyncLen;
    
        vpParams->lcdOpTimingCfg.dvoFormat = gDssVpParams.lcdOpTimingCfg.dvoFormat;
        vpParams->lcdOpTimingCfg.videoIfWidth = gDssVpParams.lcdOpTimingCfg.videoIfWidth;
    
        vpParams->lcdPolarityCfg.actVidPolarity =  gDssVpParams.lcdPolarityCfg.actVidPolarity;
        vpParams->lcdPolarityCfg.hsPolarity = gDssVpParams.lcdPolarityCfg.hsPolarity;
        vpParams->lcdPolarityCfg.vsPolarity = gDssVpParams.lcdPolarityCfg.vsPolarity;
        vpParams->lcdPolarityCfg.pixelClkPolarity = gDssVpParams.lcdPolarityCfg.pixelClkPolarity ;
    
        /* Configure VP Advance Params*/
        advVpParams->vpId = gDssAdvVpParams.vpId;
        advVpParams->lcdAdvSignalCfg.hVAlign = gDssAdvVpParams.lcdAdvSignalCfg.hVAlign;
        advVpParams->lcdAdvSignalCfg.hVClkControl = gDssAdvVpParams.lcdAdvSignalCfg.hVClkControl;
    
        /* Configure VP Safety Params */
        for(uint8_t count = 0; count < CSL_DSS_VP_SAFETY_REGION_MAX; count++)
        {
            Dss_dctrlVpSafetyChkParamsInit(vpSafetyParams + count);
        }
    
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            vpSafetyParams[count].vpId = gDssVpSafetyParams[count].vpId;
            vpSafetyParams[count].safetySignSeedVal = gDssVpSafetyParams[count].safetySignSeedVal;
            vpSafetyParams[count].regionSafetyChkCfg.regionId = gDssVpSafetyParams[count].regionSafetyChkCfg.regionId;
            vpSafetyParams[count].regionSafetyChkCfg.referenceSign = gDssVpSafetyParams[count].regionSafetyChkCfg.referenceSign;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
    
            vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback;
            vpSafetyParams[count].appData = &vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
        }
    
        /* Configure Overlay Params */
        overlayParams->overlayId =  gDssOverlayParams.overlayId;
        overlayParams->colorbarEnable =  gDssOverlayParams.colorbarEnable;
        overlayParams->overlayCfg.colorKeyEnable =  gDssOverlayParams.overlayCfg.colorKeyEnable;
        overlayParams->overlayCfg.colorKeySel =  gDssOverlayParams.overlayCfg.colorKeySel;
        overlayParams->overlayCfg.backGroundColor =  gDssOverlayParams.overlayCfg.backGroundColor;
    
        /* Configure Overlay Layer params */
        layerParams->overlayId = gDssOverlayLayerParams.overlayId;
        memcpy((void*)layerParams->pipeLayerNum, (void* )gDssOverlayLayerParams.pipeLayerNum, \
        sizeof(gDssOverlayLayerParams.pipeLayerNum));
    
    }
    
    static void DispApp_create(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        int32_t status = SystemP_SUCCESS;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
    
        /* Init VP, Overlay and Panel params */
        DispApp_initDssParams(appObj);
    
        /* Configure DSS pipeline params */
        DispApp_initPipelineParams(appObj);
    
        /* Config IOCTL for VP, Overlay and Panel */
        retVal = DispApp_configDctrl(appObj);
    
        if(retVal == FVID2_SOK)
        {
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
    
                status = SemaphoreP_constructBinary(&instObj->syncSem, 0);
                if(status != SystemP_SUCCESS)
                {
                    retVal = FVID2_EFAIL;
                }
    
                instObj->drvHandle = Fvid2_create(
                    DSS_DISP_DRV_ID,
                    instObj->instId,
                    &instObj->createParams,
                    &instObj->createStatus,
                    &instObj->cbParams);
    
                if((NULL == instObj->drvHandle) ||
                (instObj->createStatus.retVal != FVID2_SOK))
                {
                    DebugP_log("Display Create Failed!!!\r\n");
                    retVal = instObj->createStatus.retVal;
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_DSS_PARAMS,
                        &instObj->dispParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS,
                        &instObj->mflagParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Mflag Params IOCTL Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
                    {
                        retVal = Fvid2_control(
                            instObj->drvHandle,
                            IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS,
                            &instObj->safetyParams,
                            NULL);
                        if(retVal != FVID2_SOK)
                        {
                            DebugP_log("DSS Set Safety Params IOCTL Failed!!!\r\n");
                        }
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = DispApp_allocAndQueueFrames(appObj, instObj);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("Display Alloc and Queue Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("Display create complete!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_delete(Dss_Object *appObj)
    {
        int32_t retVal;
        uint32_t instCnt;
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlVpErrorStats *pErrorStats;
        Dss_InstObject *instObj;
        Dss_DispCurrentStatus currStatus;
        Fvid2_FrameList frmList;
    
        vpParams = &appObj->vpParams;
        pErrorStats = &appObj->errorStats;
    
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
    
            /* Check for DSS underflow errors */
            retVal = Fvid2_control(
                instObj->drvHandle,
                IOCTL_DSS_DISP_GET_CURRENT_STATUS,
                &currStatus,
                NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Failed to get Display Stats!!!\r\n");
            }
    
            /* Print Synclost errors */
            if(0U != currStatus.underflowCount)
            {
                GT_2trace(DssTrace, GT_ERR, "No of Underflows for Inst %d: %d\r\n", instCnt, currStatus.underflowCount);
            }
            else
            {
                DebugP_log("Underflow did not occur\r\n");
            }
    
            /* Dequeue all the request from the driver */
            while (1U)
            {
                retVal = Fvid2_dequeue(
                    instObj->drvHandle,
                    &frmList,
                    0U,
                    FVID2_TIMEOUT_NONE);
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
    
            retVal = Fvid2_delete(instObj->drvHandle, NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Delete Failed!!!\r\n");
                break;
            }
        }
    
        /* Check for DSS synclost errors */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_GET_VP_ERROR_STATS,
            pErrorStats,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Failed to get VP Stats!!!\r\n");
        }
    
        /* Print Synclost errors */
        if(0U != pErrorStats->syncLost)
        {
            GT_1trace(DssTrace, GT_ERR, "No of Sync Lost: %d\r\n", pErrorStats->syncLost);
        }
        else
        {
            DebugP_log("Sync Lost did not occur\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_CLEAR_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Clear Path Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_STOP_VP,
            vpParams,
            NULL);
    
        if(FVID2_SOK != retVal)
        {
            DebugP_log("VP Stop Failed!!!\r\n");
        }
    
        if(FVID2_SOK == retVal)
        {
             DebugP_log("Display delete complete!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj)
    {
        int32_t  retVal = FVID2_SOK;
        uint32_t frmId, numFrames;
        Fvid2_Frame *frm;
        Fvid2_FrameList frmList;
    
        Fvid2FrameList_init(&frmList);
        frm = instObj->frames;
        numFrames = instObj->numFrames;
        /* init memory pointer for 'numFrames'  */
        for(frmId=0U; frmId<numFrames; frmId++)
        {
            /* init Fvid2_Frame to 0's  */
            Fvid2Frame_init((Fvid2_Frame *)(frm + frmId));
            if(instObj->instId == gDssConfigPipelineParams.instId[0U])
            {
                frm[frmId].addr[0U] = (uint64_t)gfirstPipeFrameBufferPointer[frmId];
            }
            else
            {
                frm[frmId].addr[0U] = (uint64_t)gsecondPipeFrameBufferPointer[frmId];
            }
    
            frm[frmId].fid = FVID2_FID_FRAME;
            frm[frmId].appData = instObj;
    
            /* Set number of frame in frame list - one at a time */
            frmList.numFrames  = 1U;
            frmList.frames[0U] = &frm[frmId];
    
            /*
             * queue the frames in frmList
             * All allocate frames are queued here as an example.
             * In general atleast 2 frames per channel need to queued
             * before starting display,
             * else frame will get dropped until frames are queued
             */
            retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Queue Failed!!!\r\n");
                break;
            }
        }
    
        return (retVal);
    }
    
    static void DispApp_initPipelineParams(Dss_Object *appObj)
    {
        uint32_t instCnt = 0U, numPipes = 0U;
        Dss_DispParams *dispParams;
        Dss_InstObject *instObj;
    
        numPipes = gDssConfigPipelineParams.numTestPipes;
    
        for(instCnt=0U; instCnt<numPipes; instCnt++)
        {
            /* Initialize video pipes */
            instObj = &appObj->instObj[instCnt];
            instObj->instId = gDssConfigPipelineParams.instId[instCnt];
    
            Dss_dispCreateParamsInit(&instObj->createParams);
            Fvid2CbParams_init(&instObj->cbParams);
    
            instObj->cbParams.cbFxn = &DispApp_pipeCbFxn;
            instObj->cbParams.appData = instObj;
    
            dispParams = &instObj->dispParams;
            Dss_dispParamsInit(dispParams);
    
            dispParams->pipeCfg.pipeType = gDssConfigPipelineParams.pipeType[instCnt];
            dispParams->pipeCfg.inFmt.width = gDssConfigPipelineParams.inWidth[instCnt];
            dispParams->pipeCfg.inFmt.height = gDssConfigPipelineParams.inHeight[instCnt];
    
            for(uint32_t count = 0U; count < FVID2_MAX_PLANES; count++)
            {
                dispParams->pipeCfg.inFmt.pitch[count] =
                                            gDssConfigPipelineParams.pitch[instCnt][count];
            }
    
            dispParams->pipeCfg.inFmt.dataFormat =
                                            gDssConfigPipelineParams.inDataFmt[instCnt];
            dispParams->pipeCfg.inFmt.scanFormat =
                                            gDssConfigPipelineParams.inScanFmt[instCnt];
            dispParams->pipeCfg.outWidth = gDssConfigPipelineParams.outWidth[instCnt];
            dispParams->pipeCfg.outHeight = gDssConfigPipelineParams.outHeight[instCnt];
            dispParams->pipeCfg.scEnable = gDssConfigPipelineParams.scEnable[instCnt];
    
            dispParams->alphaCfg.globalAlpha =
                                    gDssConfigPipelineParams.globalAlpha[instCnt];
            dispParams->alphaCfg.preMultiplyAlpha =
                                    gDssConfigPipelineParams.preMultiplyAlpha[instCnt];
            dispParams->layerPos.startX = gDssConfigPipelineParams.posx[instCnt];
            dispParams->layerPos.startY = gDssConfigPipelineParams.posy[instCnt];
    
            Dss_dispPipeMflagParamsInit(&instObj->mflagParams);
    
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                Dss_dispPipeSafetyChkParamsInit(&instObj->safetyParams);
    
                instObj->safetyParams.safetySignSeedVal = gDssPipelineSafetyParams[instCnt].safetySignSeedVal;
                instObj->safetyParams.referenceSign = gDssPipelineSafetyParams[instCnt].referenceSign;
                instObj->safetyParams.safetyChkCfg.safetyChkEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkEnable;
                instObj->safetyParams.safetyChkCfg.safetyChkMode = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
                instObj->safetyParams.safetyChkCfg.seedSelectEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.seedSelectEnable;
                instObj->safetyParams.safetyChkCfg.thresholdValue = gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue;
                instObj->safetyParams.safetyChkCfg.frameSkip = gDssPipelineSafetyParams[instCnt].safetyChkCfg.frameSkip;
                instObj->safetyParams.safetyChkCfg.regionPos.startX = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startX;
                instObj->safetyParams.safetyChkCfg.regionPos.startY = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startY;
                instObj->safetyParams.safetyChkCfg.regionSize.width = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.width;
                instObj->safetyParams.safetyChkCfg.regionSize.height = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.height;
    
                instObj->safetyParams.safetyErrCbFxn = DispApp_pipelineSafetyErrCallback;
                instObj->safetyParams.appData = &gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
            }
        }
    }
    
    static int32_t DispApp_configDctrl(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
    
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlOldiParams *oldiParams;
    
        oldiParams = appObj->oldiParams;
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        globalDssParams= &appObj->globalDssParams;
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set Path IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_ADV_VP_PARAMS,
            advVpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Advance VP Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_PARAMS,
            vpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set VP Params IOCTL Failed!!!\r\n");
        }
    
        if (appObj->oldiParams != NULL)
        {
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_OLDI_PARAMS,
                oldiParams,
                NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set OLDI Params IOCTL Failed!!!\r\n");
            }
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
            overlayParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Overlay Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
            layerParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Layer Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
            globalDssParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Global DSS Params IOCTL Failed!!!\r\n");
        }
    
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
            vpSafetyParams + count,
            NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set Safety Params IOCTL Failed!!!\r\n");
                break;
            }
        }
    
        return (retVal);
    }
    
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData)
    {
        int32_t retVal  = FVID2_SOK;
        Dss_InstObject *instObj = (Dss_InstObject *) appData;
    
        GT_assert (DssTrace, (NULL != instObj));
        (void) SemaphoreP_post(&instObj->syncSem);
    
        return (retVal);
    }
    
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if(gSafetyCallbackDataVP[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
        {
            gSafetyCallbackDataVP[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVP[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVP[safetyCbData.regionId].frameCount = gLoopCount;
            gSafetyCallbackDataVP[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVP[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVP[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    
    }
    
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData)
    {
        if(Dss_dispIsVidInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVID.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVID.safetyInterupt = true;
                gSafetyCallbackDataVID.pipeId = pipeId;
                gSafetyCallbackDataVID.frameCount = gLoopCount;
                gSafetyCallbackDataVID.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVID.cbData.capturedSign = capturedSign;
            }
        }
        else if(Dss_dispIsVidLInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVIDL.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVIDL.safetyInterupt = true;
                gSafetyCallbackDataVIDL.pipeId = pipeId;
                gSafetyCallbackDataVIDL.frameCount = gLoopCount;
                gSafetyCallbackDataVIDL.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVIDL.cbData.capturedSign = capturedSign;
            }
        }
    
    }
    
    static int32_t DispApp_logSafetyCheckData()
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t count;
    
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            DebugP_log("****************************************************\r\n");
    
            DebugP_log("Safety Data Log Region : %d\r\n", gSafetyCallbackDataVP[count].cbData.regionId);
            DebugP_log("Safety Data VP ID: %s\r\n",gSafetyCallbackDataVP[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    
            if(gSafetyCallbackDataVP[count].safetyInterupt == true)
            {
                DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVP[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVP[count].frameCount < gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVP[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP[count].frameCount);
                DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP[count].cbData.capturedSign);
            }
            else
            {
                status = SystemP_FAILURE;
                DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
            }
    
        }
    
        for(uint32_t instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                if(Dss_dispIsVidInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VID1\r\n");
    
                    if(gSafetyCallbackDataVID.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVID.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVID.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVID.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
                else if(Dss_dispIsVidLInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VIDL1\r\n");
    
                    if(gSafetyCallbackDataVIDL.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVIDL.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVIDL.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVIDL.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
            }
        }
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x302022a4)));
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x302062a4)));
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a090)));
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a094)));
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a098)));
        DebugP_log("Log PRINT:  Value: %x----------\r\n", CSL_REG32_RD((uint32_t) AddrTranslateP_getLocalAddr(0x3020a09c)));
        return status;
    }
    

    We need to monitor more than 4 tell-tales, but the hardware limits us to only 4 safety regions per VP. To work around this, we’re considering a time-division (polling-based) switching approach

    Theoretically this is feasible, you will need to modify the safety region registers for each frame/screen and wait for next VSYNC to get safety interrupts (if any).

    Additionally, we’d also like to know whether it’s possible to use the R5 core solely for monitoring purposes, without handling any display-related tasks.

    We do not have any POC or example for this yet, but, theoretically, it is feasible. Do note that this will need lot of effort to develop and a significant software change which should be owned by the customer.

  • Hello,

    Thanks for your reply!!!

    The log of the code you provided is shown in the figure below. 

    without the data corruption.

    with the data corruption.

    For more than 4 regions to monitor, we have modified the code dss_display_share.c, but the result shows that the first group is always true while the second group is always false. Could you please help us figure out what the problem is and how to improve it?

    /*
     *  Copyright (C) 2023-24 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file dss_display_share.c
     *
     *  \brief DSS sample application that performs splash and share display with
     *         HLOS.
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <stdio.h>
    #include <string.h>
    #include <drivers/dss.h>
    #include <drivers/fvid2.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <kernel/dpl/TaskP.h>
    #include "ti_drivers_open_close.h"
    #include "ti_drivers_config.h"
    #include "ti_board_open_close.h"
    #include "dss_display_sample.h"
    #include "FreeRTOS.h"
    #include <drivers/device_manager/sciclient.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* Frame buffer region start and length are defined in the linker. Macros
     * maintained here refer to the same, to configure firewall for this region.
     * Incase of linker is updated, please update the base address and length.
     */
    #define DISP_FRAME_BUFFER_REGION_ADDRESS_START            (0x93500000ULL)
    /* Frame_buf_start + Frame_buf_length - 1U */
    #define DISP_FRAME_BUFFER_REGION_ADDRESS_END              (0x9B4fffffULL)
    
    
    /* Max frame size based on resolution */
    #define DISP_FRAME_SIZE_MAX                         (3840U*1080U)
    
    /* Max pixel width */
    #define DISP_FRAME_PIXEL_WIDTH_MAX                  (4U)
    
    /* X and Y position for splash image */
    #define DISP_SPLASH_IMAGE_XPOSTION                  760U
    #define DISP_SPLASH_IMAGE_YPOSTION                  550U
    
    /* Width and height of splash image */
    #define DISP_SPLASH_IMAGE_WIDTH                     400U
    #define DISP_SPLASH_IMAGE_HEIGHT                    100U
    
    /* X and Y position for cluster image */
    #define DISP_SHARE_IMAGE_XPOSTION                   610U
    #define DISP_SHARE_IMAGE_YPOSTION                   120U
    
    /* Width and height of cluster image */
    #define DISP_SHARE_IMAGE_WIDTH                      700U
    #define DISP_SHARE_IMAGE_HEIGHT                     105U
    
    /* Number of bytes per pixel */
    #define DISP_BYTES_PER_PIXEL                        4U
    
    /* Splash timeout in ticks */
    #define DISP_SPLASH_TIMEOUT_TICKS                   5000U
    
    /* Splash thread priority */
    #define TASK_PRI_SPLASH_THREAD                      (configMAX_PRIORITIES - 1U)
    /* Display share thread priority */
    #define TASK_PRI_SHARE_THREAD                       (configMAX_PRIORITIES - 1U)
    
    /* Display task size */
    #define DISPLAY_TASK_SIZE                           (4*1024U)
    
    /* Number of same frame before frame change for cluster image */
    #define DISPLAY_SHARE_THREAD_FRAME_SWAP_COUNT       (12U)
    
    /* Number frames elapsed to measure fps */
    #define DISPLAY_SHARE_THREAD_FPS_FRAME_COUNT        (300U)
    
    /***************************************新增****************/
    /* Corrupt frame number */
    #define DISP_FRAME_CORRUPT_NUM              (1000U)
    
    /* Number of frames */
    #define DISP_NUM_FRAMES_COUNT               ((uint32_t)2000U)
    
    #define CONFIG_DSS_NUM_SAFETY_REGIONS_TOTAL (8U)
    
    #define CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP (4U)
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /* None */
    typedef struct
    {
        uint32_t safetyInterupt;
        /**< Flag to check interupt received */
        uint32_t vpId;
        /**< Video Port Id */
        uint32_t pipeId;
        /**< Pipe Id */
        uint32_t frameCount;
        /**< Frame Count */
        uint32_t safetyCheckMode;
        /**< Mode of operation of the safety check module */
        Dss_DctrlVpSafetyCbData cbData;
        /**< Safety Error callback data to be returned to application */
    } Dss_safetyTestCbData;
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static void DispApp_init(Dss_Object *appObj);
    static void DispApp_deInit(Dss_Object *appObj);
    static void DispApp_create(Dss_Object *appObj);
    static void DispApp_delete(Dss_Object *appObj);
    static int32_t DispApp_configDctrl(Dss_Object *appObj);
    static int32_t DispApp_runTest(Dss_Object *appObj);
    static void DispApp_initPipelineParams(Dss_Object *appObj);
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj);
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData);
    static void DispApp_initDssParams(Dss_Object *appObj);
    static void DispApp_updateSplashFrameBuffer(void *frameBuf, uint32_t xpostion,
                                          uint32_t yposition, uint32_t width,
                                          uint32_t height, uint32_t bpp);
    static void DispApp_updateTelltaleFrameBuffer(void *frameBuf, uint32_t xpostion,
                                                  uint32_t yposition, uint32_t width,
                                                  uint32_t height, uint32_t bpp);
    static void DispApp_splashTimeoutCbFxn(ClockP_Object *obj, void *args);
    static void DispApp_initFrames(uint32_t frameLength);
    static void DispApp_fwlConfigureDssRegion(Dss_Object *appObj);
    static void DispApp_fwlFrameBufferRegion(void);
    
    
    /***************************************新增****************/
    static void DispApp_vpSafetyErrCallback_Group2(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData);
    static void DispApp_vpSafetyErrCallback_Group1(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData);
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData);
    static int32_t DispApp_logSafetyCheckData();
    
    static int32_t DispApp_configDctrlSafetyGroup(Dss_Object *appObj, uint32_t groupId);
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /* Globals to hold fps time */
    static uint32_t gStopProfileTime, gStartProfileTime, frameCount;
    
    /*
     * Global frame buffer. Maximum frames per handle is considered 2 and first frame
     * is used for first pipeline instance. DSS sharing use case only uses one pipeline.
     */
    uint8_t gFirstPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096)));
    
    /* Splash thread and display share thread stack */
    static uint8_t gDisplaySplashTaskStack[DISPLAY_TASK_SIZE] __attribute__((aligned(32)));
    static uint8_t gDisplayShareTaskStack[DISPLAY_TASK_SIZE] __attribute__((aligned(32)));
    
    /* Splash thread and display share thread handles */
    static TaskP_Object gDisplaySplashTask;
    static TaskP_Object gDisplayShareTask;
    
    /* Splash timeout semaphore */
    static SemaphoreP_Object gSplashTimeoutSem;
    
    /* Splash timeout clock object */
    static ClockP_Object gSplashClockObj;
    
    /***************************************新增****************/
    //static Dss_safetyTestCbData gSafetyCallbackDataVP[CONFIG_DSS_NUM_SAFETY_REGIONS];
    static Dss_safetyTestCbData gSafetyCallbackDataVPGroup1[4];
    static Dss_safetyTestCbData gSafetyCallbackDataVPGroup2[4];
    static Dss_safetyTestCbData gSafetyCallbackDataVIDL;
    
    static volatile uint32_t gLoopCount;
    static volatile uint32_t gLoopTime;
    
    //static volatile uint32_t gFlag = 0;
    
    /* [新增] Current active safety group - 跟踪当前活动组 */
    static volatile uint32_t gCurrentSafetyGroup = 0;
    
    /* DSS VP Safety Params */
    Dss_DctrlVpSafetyChkParams gDssVpSafetyParams_Group1[CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP] =
    {
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_0,
                .referenceSign = 0xC4EF1F47U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 40U,
                        .startY = 0U,
                    },
                    .regionSize = {
                        .width = 40U,
                        .height = 30U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_1,
                .referenceSign = 0xC4EF1E36U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 180U,
                        .startY = 100U,
                    },
                    .regionSize = {
                        .width = 80U,
                        .height = 60U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_2,
                .referenceSign = 0x709404A5U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1040U,
                        .startY = 840U,
                    },
                    .regionSize = {
                        .width = 40U,
                        .height = 20U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_3,
                .referenceSign = 0x2F469430U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1700U,
                        .startY = 920U,
                    },
                    .regionSize = {
                        .width = 60U,
                        .height = 40U,
                    }
                },
            },
        },
    };
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void dss_display_share_main(void *args)
    {
        int32_t retVal = FVID2_SOK;
    
        DispApp_fwlConfigureDssRegion(&gDssObjects[CONFIG_DSS0]);
        DispApp_fwlFrameBufferRegion();
    
        DispApp_init(&gDssObjects[CONFIG_DSS0]);
    
        DebugP_log("DSS display share application started...\r\n");
    
        retVal = DispApp_runTest(&gDssObjects[CONFIG_DSS0]);
    
        DispApp_logSafetyCheckData();
        if(FVID2_SOK == retVal)
        {
            DebugP_log("DSS display share Passed!!\r\n");
        }
        else
        {
            DebugP_log("DSS display share Failed!!\r\n");
        }
    
        return;
    }
    
    void DispApp_splashThread(void *args)
    {
        int32_t status = SystemP_SUCCESS;
        int32_t retVal = FVID2_SOK;
        Dss_InstObject *instObj;
        Dss_Object *appObj = (Dss_Object*)args;
        instObj = &appObj->instObj[0];
        Fvid2_FrameList  frmList;
        ClockP_Params clockParams;
        Dss_DispParams *dispParams;
    
        /* Create timer for splash thread timeout */
        ClockP_Params_init(&clockParams);
        clockParams.timeout = DISP_SPLASH_TIMEOUT_TICKS;
        clockParams.period = 0;
        clockParams.callback = DispApp_splashTimeoutCbFxn;
        clockParams.args = &gSplashTimeoutSem;
        status = ClockP_construct(&gSplashClockObj, &clockParams);
    
        if(status == SystemP_SUCCESS)
        {
            /* Initialise frames */
            DispApp_initFrames(DISP_SPLASH_IMAGE_WIDTH * DISP_SPLASH_IMAGE_HEIGHT * DISP_BYTES_PER_PIXEL);
    
            /* Update frame buffers for the pipeline before starting display */
            DispApp_updateSplashFrameBuffer((void*)&gFirstPipelineFrameBuf[0], 0, \
                                    0, DISP_SPLASH_IMAGE_WIDTH, \
                                    DISP_SPLASH_IMAGE_HEIGHT, DISP_BYTES_PER_PIXEL);
    
            DispApp_updateSplashFrameBuffer((void*)&gFirstPipelineFrameBuf[1], 0, \
                        0, DISP_SPLASH_IMAGE_WIDTH, \
                        DISP_SPLASH_IMAGE_HEIGHT, DISP_BYTES_PER_PIXEL);
    
            dispParams = &instObj->dispParams;
    
            /* Update input splash image frame length and width for DSS */
            dispParams->pipeCfg.inFmt.width = DISP_SPLASH_IMAGE_WIDTH;
            dispParams->pipeCfg.inFmt.height = DISP_SPLASH_IMAGE_HEIGHT;
            dispParams->pipeCfg.inFmt.pitch[0] =DISP_SPLASH_IMAGE_WIDTH * DISP_BYTES_PER_PIXEL;
            dispParams->pipeCfg.outWidth = DISP_SPLASH_IMAGE_WIDTH;
            dispParams->pipeCfg.outHeight = DISP_SPLASH_IMAGE_HEIGHT;
            dispParams->layerPos.startX = DISP_SPLASH_IMAGE_XPOSTION;
            dispParams->layerPos.startY = DISP_SPLASH_IMAGE_YPOSTION;
    
            /* Send IOCTL to set DSS pipeline parameters */
            retVal = Fvid2_control(
                    instObj->drvHandle,
                    IOCTL_DSS_DISP_SET_DSS_PARAMS,
                    &instObj->dispParams,
                    NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
            }
    //#if 0
             /* Start with Group 1 - 初始激活组0 */
            gCurrentSafetyGroup = 0U;
            DispApp_configDctrlSafetyGroup(appObj, gCurrentSafetyGroup);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Failed to configure safety group 0!!!\r\n");
                return;
            }
            DebugP_log("Safety Group 0 (Regions 0-3) activated\r\n");
    
    //#endif
            if(retVal == FVID2_SOK)
            {
                /* Start display driver */
                retVal = Fvid2_start(instObj->drvHandle, NULL);
            }
    
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Display Start Failed!!!\r\n");
            }
            else
            {
                /* Start splash thread timeout */
                ClockP_start(&gSplashClockObj);
            }
    
            if(retVal == FVID2_SOK)
            {
                while(true)
                {
                    gLoopTime++;
                    int32_t retVal = FVID2_SOK;
    
                    /* Pend for display frame queue sync sempahore */
                    SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
    
                    /* Dequeue diplayed frame */
                    retVal = Fvid2_dequeue(instObj->drvHandle,
                                            &frmList,
                                            0U,
                                            FVID2_TIMEOUT_NONE);
    
                    if(FVID2_SOK == retVal)
                    {
                        /* Update frame buffer for dequeued frame */
                        DispApp_updateSplashFrameBuffer((void*)frmList.frames[0]->addr[0], 0, \
                                                0, DISP_SPLASH_IMAGE_WIDTH, \
                                                DISP_SPLASH_IMAGE_HEIGHT, DISP_BYTES_PER_PIXEL);
    
                        if(gLoopTime == 100)
                        {
                            
                            for(uint32_t count = 0; count < DISP_SPLASH_IMAGE_HEIGHT * dispParams->pipeCfg.inFmt.pitch[0]; count++)
                            {
                                *(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
                            }
                        }
                        /* Queue the new frame buffer */
                        retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
                        if(FVID2_SOK != retVal)
                        {
                            DebugP_log("Display Queue Failed!!!\r\n");
                            break;
                        }
                    }
                    else if (FVID2_EAGAIN == retVal)
                    {
                        /* Do nothing as this is first callback */
                    }
                    else
                    {
                        /* Error */
                        DebugP_log("Display Dequeue Failed!!!\r\n");
                        break;
                    }
                }
            }
        }
        gCurrentSafetyGroup = 1U;
        TaskP_destruct(&gDisplaySplashTask);
    }
    
    void DispApp_displayShareThread(void *args)
    {
        int32_t retVal = FVID2_SOK;
        Dss_InstObject *instObj;
        Dss_Object *appObj = (Dss_Object*)args;
        instObj = &appObj->instObj[0];
        Fvid2_FrameList  frmList;
    
        SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
        DispApp_initFrames(gDssConfigPipelineParams.inHeight[0] * gDssConfigPipelineParams.pitch[0][0]);
    
        /* Reinitialise pipeline params for tell tales */
        DispApp_initPipelineParams(&gDssObjects[CONFIG_DSS0]);
    
        /* Send IOCTL to set DSS pipeline parameters */
        retVal = Fvid2_control(
            instObj->drvHandle,
            IOCTL_DSS_DISP_SET_DSS_PARAMS,
            &instObj->dispParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
        }
    //#if 0
        /* Start with Group 2 - 初始激活组1 */
        
        DispApp_configDctrlSafetyGroup(appObj, gCurrentSafetyGroup);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Failed to configure safety group 1!!!\r\n");
            return;
        }
        DebugP_log("Safety Group 1 (Regions 4-7) activated\r\n");
    //#endif
        gStartProfileTime = (ClockP_getTimeUsec() / 1000U);
    
        while(gLoopCount++ < DISP_NUM_FRAMES_COUNT)
        {
            int32_t retVal = FVID2_SOK;
    
            /* Pend for display frame queue sync sempahore */
            SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
    
            retVal = Fvid2_dequeue(instObj->drvHandle,
                                    &frmList,
                                    0U,
                                    FVID2_TIMEOUT_NONE);
    
            if(FVID2_SOK == retVal)
            {
                /* Update frame buffer for dequeued frame */
                DispApp_updateTelltaleFrameBuffer((void*)frmList.frames[0]->addr[0], DISP_SHARE_IMAGE_XPOSTION, \
                                        DISP_SHARE_IMAGE_YPOSTION, DISP_SHARE_IMAGE_WIDTH, \
                                        DISP_SHARE_IMAGE_HEIGHT, DISP_BYTES_PER_PIXEL);
    //#if 0
                if(gLoopCount == DISP_FRAME_CORRUPT_NUM)
                {
                    for(uint32_t count = 0; count < gDssConfigPipelineParams.inHeight[0] * \
                    gDssConfigPipelineParams.pitch[0][0]; count++)
                    {
                        *(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
                    }
                }
    //#endif
                /* Queue the new frame buffer */
                retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
                if(FVID2_SOK != retVal)
                {
                    DebugP_log("Display Queue Failed!!!\r\n");
                    break;
                }
            }
            else if (FVID2_EAGAIN == retVal)
            {
                /* Do nothing as this is first callback */
            }
            else
            {
                /* Error */
                DebugP_log("Display Dequeue Failed!!!\r\n");
                break;
            }
    
            if(frameCount == DISPLAY_SHARE_THREAD_FPS_FRAME_COUNT)
            {
                gStopProfileTime = (ClockP_getTimeUsec() / 1000U);
    
                DebugP_log("Number of elapsed frames = %d, elapsed msec = %d, fps = %0.2f\r\n",
                            DISPLAY_SHARE_THREAD_FPS_FRAME_COUNT,
                            gStopProfileTime - gStartProfileTime,
                            (float)((float)DISPLAY_SHARE_THREAD_FPS_FRAME_COUNT / ((gStopProfileTime - gStartProfileTime)/1000.0)));
    
                /* Reset frame count and measurement time */
                frameCount = 0;
                gStartProfileTime = (ClockP_getTimeUsec() / 1000U);
            }
            else
            {
                frameCount++;
            }
        }
    
        /* Incase of display failure, stop display driver */
        retVal  = Fvid2_stop(instObj->drvHandle, NULL);
    
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Display Stop Failed!!!\r\n");
        }
    
        if(FVID2_SOK == retVal)
        {
            /* Delete driver */
            DispApp_delete(appObj);
            DispApp_deInit(&gDssObjects[CONFIG_DSS0]);
        }
    
        TaskP_destruct(&gDisplayShareTask);
    }
    
    
    static void DispApp_init(Dss_Object *appObj)
    {
        int32_t         retVal = FVID2_SOK;
        Fvid2_InitPrms  initPrms;
    
        Fvid2InitPrms_init(&initPrms);
        retVal = Fvid2_init(&initPrms);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Fvid2 Init Failed!!!\r\n");
        }
    
        Dss_initParamsInit(&appObj->initParams);
    
        Dss_init(&appObj->initParams);
    
        if(FVID2_SOK == retVal)
        {
            /* Create DCTRL handle, used for common driver configuration */
            appObj->dctrlHandle = Fvid2_create(
                DSS_DCTRL_DRV_ID,
                DSS_DCTRL_INST_0,
                NULL,
                NULL,
                NULL);
            if(NULL == appObj->dctrlHandle)
            {
                DebugP_log("DCTRL Create Failed!!!\r\n");
            }
        }
    
        if(appObj->oldiParams != NULL)
        {
            Dss_setOLDITxPowerDown(appObj->oldiParams->oldiCfg.oldiMapType, TRUE);
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("DispApp_init() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_deInit(Dss_Object *appObj)
    {
        int32_t  retVal = FVID2_SOK;
    
        /* Delete DCTRL handle */
        retVal = Fvid2_delete(appObj->dctrlHandle, NULL);
        retVal += Dss_deInit();
        retVal += Fvid2_deInit(NULL);
        if(retVal != FVID2_SOK)
        {
             DebugP_log("DCTRL handle delete failed!!!\r\n");
        }
        else
        {
             DebugP_log("DispApp_deInit() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_runTest(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        int32_t status = SystemP_SUCCESS;
        Dss_InstObject *instObj;
        instObj = &appObj->instObj[0];
        TaskP_Params taskParams;
    
        /* Create driver */
        DispApp_create(appObj);
    
        DebugP_log("Starting display ... !!!\r\n");
        DebugP_log("Display in progress ... DO NOT HALT !!!\r\n");
    
        /* Create splash thread */
        TaskP_Params_init(&taskParams);
        taskParams.name = "DispApp_splashThread";
        taskParams.stackSize = DISPLAY_TASK_SIZE;
        taskParams.stack = &gDisplaySplashTaskStack[0];
        taskParams.priority = TASK_PRI_SPLASH_THREAD;
        taskParams.args = (void*)&gDssObjects[CONFIG_DSS0];
        taskParams.taskMain = DispApp_splashThread;
    
        status = TaskP_construct(&gDisplaySplashTask, &taskParams);
    
        status += SemaphoreP_constructBinary(&gSplashTimeoutSem, 0);
    
        if(status == SystemP_SUCCESS)
        {
            /* Pend for splash thread timeout */
            SemaphoreP_pend(&gSplashTimeoutSem, SystemP_WAIT_FOREVER);
            SemaphoreP_destruct(&gSplashTimeoutSem);
    
            /* Kill splash thread only when there is some frame queued in display driver */
            SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
            TaskP_destruct(&gDisplaySplashTask);
    
            if(status == SystemP_SUCCESS)
            {
                /* Create display share thread */
                TaskP_Params_init(&taskParams);
                taskParams.name = "DispApp_displayShareThread";
                taskParams.stackSize = DISPLAY_TASK_SIZE;
                taskParams.stack = &gDisplayShareTaskStack[0];
                taskParams.priority = TASK_PRI_SHARE_THREAD;
                taskParams.args = (void*)&gDssObjects[CONFIG_DSS0];
                taskParams.taskMain = DispApp_displayShareThread;
    
                status = TaskP_construct(&gDisplayShareTask, &taskParams);
    
                if(status == SystemP_FAILURE)
                {
                    DebugP_log("Display share task failed!!!\r\n");
                }
            }
    
        }
    
        if(status != SystemP_SUCCESS)
        {
            ClockP_destruct(&gSplashClockObj);
            SemaphoreP_destruct(&gSplashTimeoutSem);
            TaskP_destruct(&gDisplaySplashTask);
            TaskP_destruct(&gDisplayShareTask);
            DebugP_log("Display start failed!!!\r\n");
        }
    
        return retVal;
    }
    
    static void DispApp_initDssParams(Dss_Object *appObj)
    {
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        globalDssParams= &appObj->globalDssParams;
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        Dss_dctrlVpParamsInit(vpParams);
        Dss_dctrlAdvVpParamsInit(advVpParams);
        Dss_dctrlOverlayParamsInit(overlayParams);
        Dss_dctrlOverlayLayerParamsInit(layerParams);
        Dss_dctrlGlobalDssParamsInit(globalDssParams);
    
    
        /* Configure VP params */
        vpParams->vpId = gDssVpParams.vpId;
        vpParams->lcdOpTimingCfg.mInfo.standard = gDssVpParams.lcdOpTimingCfg.mInfo.standard;
        vpParams->lcdOpTimingCfg.mInfo.width = gDssVpParams.lcdOpTimingCfg.mInfo.width;
        vpParams->lcdOpTimingCfg.mInfo.height = gDssVpParams.lcdOpTimingCfg.mInfo.height;
        vpParams->lcdOpTimingCfg.mInfo.hFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.hBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.hSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.hSyncLen;
        vpParams->lcdOpTimingCfg.mInfo.vFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.vBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.vSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.vSyncLen;
    
        vpParams->lcdOpTimingCfg.dvoFormat = gDssVpParams.lcdOpTimingCfg.dvoFormat;
        vpParams->lcdOpTimingCfg.videoIfWidth = gDssVpParams.lcdOpTimingCfg.videoIfWidth;
    
        vpParams->lcdPolarityCfg.actVidPolarity =  gDssVpParams.lcdPolarityCfg.actVidPolarity;
        vpParams->lcdPolarityCfg.hsPolarity = gDssVpParams.lcdPolarityCfg.hsPolarity;
        vpParams->lcdPolarityCfg.vsPolarity = gDssVpParams.lcdPolarityCfg.vsPolarity;
        vpParams->lcdPolarityCfg.pixelClkPolarity = gDssVpParams.lcdPolarityCfg.pixelClkPolarity ;
    
        /* Configure VP Advance Params*/
        advVpParams->vpId = gDssAdvVpParams.vpId;
        advVpParams->lcdAdvSignalCfg.hVAlign = gDssAdvVpParams.lcdAdvSignalCfg.hVAlign;
        advVpParams->lcdAdvSignalCfg.hVClkControl = gDssAdvVpParams.lcdAdvSignalCfg.hVClkControl;
    
        /* Configure VP Safety Params */
        for(uint8_t count = 0; count < CSL_DSS_VP_SAFETY_REGION_MAX; count++)
        {
            Dss_dctrlVpSafetyChkParamsInit(vpSafetyParams + count);
        }
    
        /* Configure Overlay Params */
        overlayParams->overlayId =  gDssOverlayParams.overlayId;
        overlayParams->colorbarEnable =  gDssOverlayParams.colorbarEnable;
        overlayParams->overlayCfg.colorKeyEnable =  gDssOverlayParams.overlayCfg.colorKeyEnable;
        overlayParams->overlayCfg.colorKeySel =  gDssOverlayParams.overlayCfg.colorKeySel;
        overlayParams->overlayCfg.backGroundColor =  gDssOverlayParams.overlayCfg.backGroundColor;
    
        /* Configure Overlay Layer params */
        layerParams->overlayId = gDssOverlayLayerParams.overlayId;
        memcpy((void*)layerParams->pipeLayerNum, (void* )gDssOverlayLayerParams.pipeLayerNum, \
        sizeof(gDssOverlayLayerParams.pipeLayerNum));
    
    }
    
    static void DispApp_create(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        int32_t status = SystemP_SUCCESS;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
    
        /* Init VP, Overlay and Panel params */
        DispApp_initDssParams(appObj);
    
        /* Configure DSS pipeline params */
        DispApp_initPipelineParams(appObj);
    
        /* Config IOCTL for VP, Overlay and Panel */
        retVal = DispApp_configDctrl(appObj);
    
        if(retVal == FVID2_SOK)
        {
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
    
                status = SemaphoreP_constructBinary(&instObj->syncSem, 0);
                if(status != SystemP_SUCCESS)
                {
                    retVal = FVID2_EFAIL;
                }
    
                /* Create Display driver */
                instObj->drvHandle = Fvid2_create(
                    DSS_DISP_DRV_ID,
                    instObj->instId,
                    &instObj->createParams,
                    &instObj->createStatus,
                    &instObj->cbParams);
    
                if((NULL == instObj->drvHandle) ||
                (instObj->createStatus.retVal != FVID2_SOK))
                {
                    DebugP_log("Display Create Failed!!!\r\n");
                    retVal = instObj->createStatus.retVal;
                }
    
                /* Call display set params IOTCL */
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_DSS_PARAMS,
                        &instObj->dispParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
                    }
                }
    
                /* Call set mflag params IOTCL */
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS,
                        &instObj->mflagParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Mflag Params IOCTL Failed!!!\r\n");
                    }
                }
    
                 if(FVID2_SOK == retVal)
                {
                    if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
                    {
                        retVal = Fvid2_control(
                            instObj->drvHandle,
                            IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS,
                            &instObj->safetyParams,
                            NULL);
                        if(retVal != FVID2_SOK)
                        {
                            DebugP_log("DSS Set Safety Params IOCTL Failed!!!\r\n");
                        }
                    }
                }
    
                /* Allocate frame buffers to display driver */
                if(FVID2_SOK == retVal)
                {
                    retVal = DispApp_allocAndQueueFrames(appObj, instObj);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("Display Alloc and Queue Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("Display create complete!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_delete(Dss_Object *appObj)
    {
        int32_t retVal;
        uint32_t instCnt;
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlVpErrorStats *pErrorStats;
        Dss_InstObject *instObj;
        Dss_DispCurrentStatus currStatus;
        Fvid2_FrameList frmList;
    
        vpParams = &appObj->vpParams;
        pErrorStats = &appObj->errorStats;
    
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
    
            /* Check for DSS underflow errors */
            retVal = Fvid2_control(
                instObj->drvHandle,
                IOCTL_DSS_DISP_GET_CURRENT_STATUS,
                &currStatus,
                NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Failed to get Display Stats!!!\r\n");
            }
    
            /* Print Synclost errors */
            if(0U != currStatus.underflowCount)
            {
                GT_2trace(DssTrace, GT_ERR, "No of Underflows for Inst %d: %d\r\n", instCnt, currStatus.underflowCount);
            }
            else
            {
                DebugP_log("Underflow did not occur\r\n");
            }
    
            /* Dequeue all the request from the driver */
            while (1U)
            {
                retVal = Fvid2_dequeue(
                    instObj->drvHandle,
                    &frmList,
                    0U,
                    FVID2_TIMEOUT_NONE);
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
    
            retVal = Fvid2_delete(instObj->drvHandle, NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Delete Failed!!!\r\n");
                break;
            }
        }
    
        /* Check for DSS synclost errors */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_GET_VP_ERROR_STATS,
            pErrorStats,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Failed to get VP Stats!!!\r\n");
        }
    
        /* Print Synclost errors */
        if(0U != pErrorStats->syncLost)
        {
            GT_1trace(DssTrace, GT_ERR, "No of Sync Lost: %d\r\n", pErrorStats->syncLost);
        }
        else
        {
            DebugP_log("Sync Lost did not occur\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_CLEAR_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Clear Path Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_STOP_VP,
            vpParams,
            NULL);
    
        if(FVID2_SOK != retVal)
        {
            DebugP_log("VP Stop Failed!!!\r\n");
        }
    
        if(FVID2_SOK == retVal)
        {
             DebugP_log("Display delete complete!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj)
    {
        int32_t  retVal = FVID2_SOK;
        uint32_t frmId, numFrames;
        Fvid2_Frame *frm;
        Fvid2_FrameList frmList;
    
        Fvid2FrameList_init(&frmList);
        frm = instObj->frames;
        numFrames = instObj->numFrames;
        /* init memory pointer for 'numFrames'  */
        for(frmId=0U; frmId<numFrames; frmId++)
        {
            /* init Fvid2_Frame to 0's  */
            Fvid2Frame_init((Fvid2_Frame *)(frm + frmId));
            if(instObj->instId == gDssConfigPipelineParams.instId[0U])
            {
                frm[frmId].addr[0U] = (uint64_t)&gFirstPipelineFrameBuf[frmId];
            }
    
            frm[frmId].fid = FVID2_FID_FRAME;
            frm[frmId].appData = instObj;
    
            /* Set number of frame in frame list - one at a time */
            frmList.numFrames  = 1U;
            frmList.frames[0U] = &frm[frmId];
    
            /*
             * queue the frames in frmList
             * All allocate frames are queued here as an example.
             * In general atleast 2 frames per channel need to queued
             * before starting display,
             * else frame will get dropped until frames are queued
             */
            retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Queue Failed!!!\r\n");
                break;
            }
        }
    
        return (retVal);
    }
    
    static void DispApp_initPipelineParams(Dss_Object *appObj)
    {
        uint32_t instCnt = 0U, numPipes = 0U;
        Dss_DispParams *dispParams;
        Dss_InstObject *instObj;
    
        numPipes = gDssConfigPipelineParams.numTestPipes;
    
        for(instCnt=0U; instCnt<numPipes; instCnt++)
        {
            /* Initialize video pipes */
            instObj = &appObj->instObj[instCnt];
            instObj->instId = gDssConfigPipelineParams.instId[instCnt];
    
            Dss_dispCreateParamsInit(&instObj->createParams);
            Fvid2CbParams_init(&instObj->cbParams);
    
            instObj->cbParams.cbFxn = &DispApp_pipeCbFxn;
            instObj->cbParams.appData = instObj;
    
            dispParams = &instObj->dispParams;
            Dss_dispParamsInit(dispParams);
    
            dispParams->pipeCfg.pipeType = gDssConfigPipelineParams.pipeType[instCnt];
            dispParams->pipeCfg.inFmt.width = gDssConfigPipelineParams.inWidth[instCnt];
            dispParams->pipeCfg.inFmt.height = gDssConfigPipelineParams.inHeight[instCnt];
    
            for(uint32_t count = 0U; count < FVID2_MAX_PLANES; count++)
            {
                dispParams->pipeCfg.inFmt.pitch[count] =
                                            gDssConfigPipelineParams.pitch[instCnt][count];
            }
    
            dispParams->pipeCfg.inFmt.dataFormat =
                                            gDssConfigPipelineParams.inDataFmt[instCnt];
            dispParams->pipeCfg.inFmt.scanFormat =
                                            gDssConfigPipelineParams.inScanFmt[instCnt];
            dispParams->pipeCfg.outWidth = gDssConfigPipelineParams.outWidth[instCnt];
            dispParams->pipeCfg.outHeight = gDssConfigPipelineParams.outHeight[instCnt];
            dispParams->pipeCfg.scEnable = gDssConfigPipelineParams.scEnable[instCnt];
    
    #if(1U==DISP_APP_ENABLE_FLIP)
            dispParams->pipeCfg.flipType = FVID2_FLIP_TYPE_V;
    #endif
            dispParams->alphaCfg.globalAlpha =
                                    gDssConfigPipelineParams.globalAlpha[instCnt];
            dispParams->alphaCfg.preMultiplyAlpha =
                                    gDssConfigPipelineParams.preMultiplyAlpha[instCnt];
            dispParams->layerPos.startX = gDssConfigPipelineParams.posx[instCnt];
            dispParams->layerPos.startY = gDssConfigPipelineParams.posy[instCnt];
    
    #if(1U == DISP_APP_ENBALE_PIPE_CROP)
            dispParams->cropParams.cropEnable = TRUE;
            dispParams->cropParams.cropCfg.cropTop = 31;
            dispParams->cropParams.cropCfg.cropBottom = 31;
            dispParams->cropParams.cropCfg.cropLeft = 31;
            dispParams->cropParams.cropCfg.cropRight = 31;
    #endif
            Dss_dispPipeMflagParamsInit(&instObj->mflagParams);
    
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                Dss_dispPipeSafetyChkParamsInit(&instObj->safetyParams);
    
                instObj->safetyParams.safetySignSeedVal = gDssPipelineSafetyParams[instCnt].safetySignSeedVal;
                instObj->safetyParams.referenceSign = gDssPipelineSafetyParams[instCnt].referenceSign;
                instObj->safetyParams.safetyChkCfg.safetyChkEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkEnable;
                instObj->safetyParams.safetyChkCfg.safetyChkMode = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
                instObj->safetyParams.safetyChkCfg.seedSelectEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.seedSelectEnable;
                instObj->safetyParams.safetyChkCfg.thresholdValue = gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue;
                instObj->safetyParams.safetyChkCfg.frameSkip = gDssPipelineSafetyParams[instCnt].safetyChkCfg.frameSkip;
                instObj->safetyParams.safetyChkCfg.regionPos.startX = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startX;
                instObj->safetyParams.safetyChkCfg.regionPos.startY = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startY;
                instObj->safetyParams.safetyChkCfg.regionSize.width = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.width;
                instObj->safetyParams.safetyChkCfg.regionSize.height = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.height;
    
                instObj->safetyParams.safetyErrCbFxn = DispApp_pipelineSafetyErrCallback;
                instObj->safetyParams.appData = &gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
            }
        }
    }
    
    static int32_t DispApp_configDctrl(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
    
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlOldiParams *oldiParams;
        //Dss_DctrlVpSafetyChkParams *vpSafetyParams;
    
        oldiParams = appObj->oldiParams;
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        globalDssParams= &appObj->globalDssParams;
        //vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
    
        /* Call display set path IOCTL */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set Path IOCTL Failed!!!\r\n");
        }
    
        /* Call set advance VP params IOCTL */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_ADV_VP_PARAMS,
            advVpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Advance VP Params IOCTL Failed!!!\r\n");
        }
    
        /* Call set VP params IOCTL */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_PARAMS,
            vpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set VP Params IOCTL Failed!!!\r\n");
        }
    
        /* Call set OLDI params IOCTL */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_OLDI_PARAMS,
            oldiParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set OLDI Params IOCTL Failed!!!\r\n");
        }
    
        /* Call set OVERLAY params IOCTL */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
            overlayParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Overlay Params IOCTL Failed!!!\r\n");
        }
    
        /* Call set layer params IOCTL to set ZORDER */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
            layerParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Layer Params IOCTL Failed!!!\r\n");
        }
    
        /* Set the global dss params like CBA config */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
            globalDssParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Global DSS Params IOCTL Failed!!!\r\n");
        }
    
        return (retVal);
    }
    
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData)
    {
        int32_t retVal  = FVID2_SOK;
        Dss_InstObject *instObj = (Dss_InstObject *) appData;
    
        GT_assert (DssTrace, (NULL != instObj));
        (void) SemaphoreP_post(&instObj->syncSem);
    
        return (retVal);
    }
    
    static void DispApp_splashTimeoutCbFxn(ClockP_Object *obj, void *args)
    {
        SemaphoreP_Object *pSemObj = (SemaphoreP_Object *)args;
    
        SemaphoreP_post(pSemObj);
    }
    
    static void DispApp_updateSplashFrameBuffer(void *frameBuf, uint32_t xpostion, \
                                    uint32_t yposition, uint32_t width, \
                                    uint32_t height, uint32_t bpp)
    {
        uint32_t yDestPos = yposition;
        uint32_t ySrcPos = 0;
        uint32_t iCnt = 0;
        uint32_t jCnt = 0;
        volatile uint32_t *srcPtr = NULL;
        volatile uint32_t *destPtr = NULL;
        static uint8_t alphaBlendVal = 0xFFU;
    
        if (xpostion + width >= gDssVpParams.lcdOpTimingCfg.mInfo.width)
        {
            width = gDssVpParams.lcdOpTimingCfg.mInfo.width - xpostion;
        }
    
        if (yposition + height >= gDssVpParams.lcdOpTimingCfg.mInfo.height)
        {
            height = gDssVpParams.lcdOpTimingCfg.mInfo.height - yposition;
        }
    
        /* Update alpha blending value */
        alphaBlendVal = (alphaBlendVal != 0xFFU) ? alphaBlendVal + 1U : alphaBlendVal;
    
        /* Copy source image to frame buffer at desired location */
        while (ySrcPos <= height)
        {
            iCnt = yDestPos * bpp * width + xpostion * bpp;
            jCnt = ySrcPos * width * bpp;
            destPtr = (volatile uint32_t *)(frameBuf + iCnt);
            srcPtr = (volatile uint32_t *)&gFrameLogoData[jCnt];
    
            for (uint32_t count = 0; count < width; count++)
            {
                /* Current alpha update is for ARGB888 frame type.
                 * Changing frame type requires update to the below written logic to update
                 * alpha value in frame.
                 */
                *destPtr = (*srcPtr & 0xFFFFFF00) | ((uint32_t)alphaBlendVal  & 0x000000FF);
                destPtr++;
                srcPtr++;
            }
    
            CacheP_wb(frameBuf + iCnt, width * bpp, CacheP_TYPE_ALLD);
            yDestPos++;
            ySrcPos++;
        }
    }
    
    static void DispApp_updateTelltaleFrameBuffer(void *frameBuf, uint32_t xpostion, \
                                    uint32_t yposition, uint32_t width, \
                                    uint32_t height, uint32_t bpp)
    {
        uint32_t yDestPos = yposition;
        uint32_t ySrcPos = 0;
        uint32_t iCnt = 0;
        uint32_t jCnt = 0;
        volatile uint8_t *destPtr = NULL;
        volatile uint8_t* sourceframe = NULL;
        static uint8_t toggleFrameCnt = 0x0U;
        static uint8_t toggleFrame = true;
    
        if (xpostion + width >= gDssVpParams.lcdOpTimingCfg.mInfo.width)
        {
            width = gDssVpParams.lcdOpTimingCfg.mInfo.width - xpostion;
        }
    
        if (yposition + height >= gDssVpParams.lcdOpTimingCfg.mInfo.height)
        {
            height = gDssVpParams.lcdOpTimingCfg.mInfo.height - yposition;
        }
    
        /* Toggle between two frames while updating the frame buffer */
        if (toggleFrame == true)
        {
            toggleFrameCnt = (toggleFrameCnt != DISPLAY_SHARE_THREAD_FRAME_SWAP_COUNT) ? toggleFrameCnt + 1U : toggleFrameCnt;
            toggleFrame = (toggleFrameCnt != DISPLAY_SHARE_THREAD_FRAME_SWAP_COUNT) ? true : false;
            sourceframe = (volatile uint8_t *)&gFrameTellTaleData1[0];
        }
        else
        {
            toggleFrameCnt = (toggleFrameCnt != 0x0U) ? toggleFrameCnt - 1U : toggleFrameCnt;
            toggleFrame = (toggleFrameCnt != 0x0U) ? false : true;
            sourceframe = (volatile uint8_t *)&gFrameTellTaleData2[0];
        }
    
        /* Copy source image to frame buffer at desired location */
        while (ySrcPos <= height)
        {
            iCnt = yDestPos * bpp * gDssVpParams.lcdOpTimingCfg.mInfo.width + xpostion * bpp;
            jCnt = ySrcPos * width * bpp;
            destPtr = (volatile uint8_t *)(frameBuf + iCnt);
    
            memcpy((void*)destPtr, (void*)(sourceframe + jCnt), width * bpp);
            CacheP_wb((void*)destPtr, width * bpp, CacheP_TYPE_ALLD);
    
            yDestPos++;
            ySrcPos++;
        }
    }
    
    static void DispApp_initFrames(uint32_t frameLength)
    {
        /* Reset frame buffer */
        for(uint8_t numframes = 0 ; numframes < CONFIG_DSS_NUM_FRAMES_PER_PIPELINE; numframes++)
        {
            memset(&gFirstPipelineFrameBuf[numframes], 0x00, frameLength);
        }
    }
    
    static void DispApp_fwlConfigureDssRegion(Dss_Object *appObj)
    {
        int32_t status = SystemP_FAILURE;
        Dss_FirewallRegionConfig *fwlData = appObj->fwlConfig;
        /* Before configuring the DSS register region specific firewall region to
         * allow access to only DM and A core, configure the whole region covered by
         * the firewall to allow access to all cores as a background region. So that
         * the other regions (except the DSS specific regions) guarded by this
         * firewall will be accessible to all cores.
         */
        const struct tisci_msg_fwl_set_firewall_region_req fwl_set_req =
        {
            .fwl_id = fwlData->fwlRegionData[0U].fwlId,
            .region = 0,
            .n_permission_regs = 3,
            /*
             * The firewall control register layout is
             *  ---------------------------------------------------------------------------
             * |  31:10   |      9     |     8      |     7:5    |      4      |   3:0     |
             *  ---------------------------------------------------------------------------
             * | Reserved | Cache Mode | Background |  Reserved  | Lock Config |  Enable   |
             *  ---------------------------------------------------------------------------
             *
             * Enable = 0xA implies firewall is enabled. Any other value means not enabled
             *
             */
            .control = 0x30A, /* 0x3 - Firewall background region, Unlocked. 0xA - Enable Firewall */
            /*
             * The firewall permission register layout is
             *  ---------------------------------------------------------------------------
             * |  31:24   |    23:16   |  15:12     |   11:8     |   7:4      |   3:0      |
             *  ---------------------------------------------------------------------------
             * | Reserved |   Priv ID  | NSUSR-DCRW | NSPRI-DCRW | SUSER-DCRW | SPRIV-DCRW |
             *  ---------------------------------------------------------------------------
             *
             * PRIV_ID = 0xC3 implies all.
             * In each of the 4 nibbles from 15:0 the 4 bits means Debug, Cache,
             * Read, Write Access for Non-secure user, Non-secure Priv,
             * Secure user, Secure Priv respectively. To enable all access bits for
             * all users, we set each of these nibbles to 0b1111 = 0xF.
             * So 15:0 becomes 0xFFFF
             */
            .permissions[0] = 0xC3FFFF,
            .permissions[1] = 0xC3FFFF,
            .permissions[2] = 0xC3FFFF,
            .start_address  = 0X0,
            .end_address    = 0xFFFFFFFFU,
        };
        struct tisci_msg_fwl_set_firewall_region_resp fwl_set_resp = { 0 };
    
        status = Sciclient_firewallSetRegion(&fwl_set_req, &fwl_set_resp, \
                                             SystemP_TIMEOUT);
    
        if(SystemP_SUCCESS == status)
        {
            for(uint32_t region = 0U; region < appObj->fwlConfig->numFwlRegion && \
                status == SystemP_SUCCESS; region++)
            {
                /* Lock the region 1 firewall ownership to DM core, so that other cores
                 * cannot modify the below region 1 firewall configuration.
                 */
                const struct tisci_msg_fwl_change_owner_info_req fwl_owner_req =
                {
                    .fwl_id = fwlData->fwlRegionData[region].fwlId,
                    .region = region + 1U,
                    .owner_index = TISCI_HOST_ID_WKUP_0_R5_1,
                };
                struct tisci_msg_fwl_change_owner_info_resp fwl_owner_resp = { 0 };
                status = Sciclient_firewallChangeOwnerInfo(&fwl_owner_req, \
                                                           &fwl_owner_resp, \
                                                           SystemP_TIMEOUT);
                if(SystemP_SUCCESS == status)
                {
                    /*
                     * Lock DSS Config region by region based firewall only to DM
                     * core. Configure this as a foreground region. This will
                     * override the above config only for DSS region. So all other
                     * regions covered by the firewall can be accessed by other
                     * cores.
                     */
                    const struct tisci_msg_fwl_set_firewall_region_req fwl_set_req =
                    {
                        .fwl_id = fwlData->fwlRegionData[region].fwlId,
                        .region = region + 1U,
                        .n_permission_regs = 2U,
                        /* 0xA - Enable Firewall */
                        .control = 0xA,
                        /* PRIV_ID = 0xD4 implies DM R5 core, giving full access to
                         * to DM core.
                         */
                        .permissions[0] = 0xD4FFFF,
                        /* PRIV_ID = 0x01 implies A53 core, giving read access to
                         * a53 context.
                         */
                        .permissions[1] = 0x012222,
    
                        .start_address  = fwlData->fwlRegionData[region].startAddr,
                        .end_address    = fwlData->fwlRegionData[region].endAddr,
                    };
                    struct tisci_msg_fwl_set_firewall_region_resp fwl_set_resp = \
                                                                              { 0 };
    
                    status = Sciclient_firewallSetRegion(&fwl_set_req, \
                                                         &fwl_set_resp, \
                                                         SystemP_TIMEOUT);
                }
            }
    
        }
    
        if(status == SystemP_SUCCESS)
        {
            DebugP_log("Configure DSS region firewall... DONE !!!\r\n");
        }
        else
        {
            DebugP_logError("Configure DSS region firewall ... Failed !!!\r\n");
        }
    }
    
    static void DispApp_fwlFrameBufferRegion(void)
    {
        int32_t status = SystemP_FAILURE;
    
        /* Before configuring the DSS frame buffer region specific firewall region
         * to allow access to only DM core, configure the whole region covered by
         * the firewall to allow access to all cores as a background region. So that
         * the other regions (except the frame buffer region) guarded by this
         * firewall will be accessible to all cores.
         */
        const struct tisci_msg_fwl_set_firewall_region_req fwl_set_req =
        {
            .fwl_id = CSL_STD_FW_DDR32SS0_SDRAM_FW1_ID,
            .region = 0,
            .n_permission_regs = 3,
            /*
             * The firewall control register layout is
             *  ---------------------------------------------------------------------------
             * |  31:10   |      9     |     8      |     7:5    |      4      |   3:0     |
             *  ---------------------------------------------------------------------------
             * | Reserved | Cache Mode | Background |  Reserved  | Lock Config |  Enable   |
             *  ---------------------------------------------------------------------------
             *
             * Enable = 0xA implies firewall is enabled. Any other value means not enabled
             *
             */
            .control = 0x30A, /* 0x3 - Firewall background region, Unlocked. 0xA - Enable Firewall */
            /*
             * The firewall permission register layout is
             *  ---------------------------------------------------------------------------
             * |  31:24   |    23:16   |  15:12     |   11:8     |   7:4      |   3:0      |
             *  ---------------------------------------------------------------------------
             * | Reserved |   Priv ID  | NSUSR-DCRW | NSPRI-DCRW | SUSER-DCRW | SPRIV-DCRW |
             *  ---------------------------------------------------------------------------
             *
             * PRIV_ID = 0xC3 implies all.
             * In each of the 4 nibbles from 15:0 the 4 bits means Debug, Cache,
             * Read, Write Access for Non-secure user, Non-secure Priv,
             * Secure user, Secure Priv respectively. To enable all access bits for
             * all users, we set each of these nibbles to 0b1111 = 0xF.
             * So 15:0 becomes 0xFFFF
             */
            .permissions[0] = 0xC3FFFF,
            .permissions[1] = 0xC3FFFF,
            .permissions[2] = 0xC3FFFF,
            .start_address  = 0x0U,
            .end_address    = 0xFFFFFFFFFFFULL,
        };
        struct tisci_msg_fwl_set_firewall_region_resp fwl_set_resp = { 0 };
    
        status = Sciclient_firewallSetRegion(&fwl_set_req, &fwl_set_resp, \
                                             SystemP_TIMEOUT);
    
        if(SystemP_SUCCESS == status)
        {
    
            /* Lock the region 1 firewall ownership to DM core, so that other cores
             * cannot modify the below region 1 firewall configuration.
             */
            const struct tisci_msg_fwl_change_owner_info_req fwl_owner_req =
            {
                .fwl_id = CSL_STD_FW_DDR32SS0_SDRAM_FW1_ID,
                .region = 1U,
                .owner_index = TISCI_HOST_ID_WKUP_0_R5_1,
            };
            struct tisci_msg_fwl_change_owner_info_resp fwl_owner_resp = { 0 };
            status = Sciclient_firewallChangeOwnerInfo(&fwl_owner_req, \
                                                        &fwl_owner_resp, \
                                                        SystemP_TIMEOUT);
            if(SystemP_SUCCESS == status)
            {
                /*
                 * Lock DSS frame buffer region by region based firewall only to DM
                 * core. Configure this as a foreground region. This will
                 * override the above config only for DSS region. So all other
                 * regions covered by the firewall can be accessed by other
                 * cores.
                 */
                const struct tisci_msg_fwl_set_firewall_region_req fwl_set_req =
                {
                    .fwl_id = CSL_STD_FW_DDR32SS0_SDRAM_FW1_ID,
                    .region = 1U,
                    .n_permission_regs = 3U,
                    /* 0xA - Enable Firewall */
                    .control = 0xA,
                    /* PRIV_ID = 0xD4 implies DM R5 core, giving full access to
                     * to DM core. 0xC3 (everyone) is not given any access, and
                     * 0xAD (DSS0 priv ID) is given all access.
                     */
                    .permissions[0] = 0xD4FFFF,
                    .permissions[1] = 0xC30000,
                    .permissions[2] = 0xADFFFF,
                    .start_address  = DISP_FRAME_BUFFER_REGION_ADDRESS_START,
                    .end_address    = DISP_FRAME_BUFFER_REGION_ADDRESS_END,
    
                };
                struct tisci_msg_fwl_set_firewall_region_resp fwl_set_resp = \
                                                                            { 0 };
    
                status = Sciclient_firewallSetRegion(&fwl_set_req, \
                                                     &fwl_set_resp, \
                                                     SystemP_TIMEOUT);
            }
    
        }
    
        if(status == SystemP_SUCCESS)
        {
            DebugP_log("Configure DSS framebuffer region firewall... DONE !!!\r\n");
        }
        else
        {
            DebugP_logError("Configure DSS framebuffer region firewall ... Failed !!!\r\n");
        }
    }
    
    #if 0
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if(gSafetyCallbackDataVP[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
        {
            gSafetyCallbackDataVP[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVP[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVP[safetyCbData.regionId].frameCount = gLoopCount;
            gSafetyCallbackDataVP[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVP[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVP[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    
    }
    #endif
    static void DispApp_vpSafetyErrCallback_Group1(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if(gSafetyCallbackDataVPGroup1[safetyCbData.regionId].safetyInterupt != true)
        {
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].frameCount = gLoopTime;
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVPGroup1[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    
    }
    
    static void DispApp_vpSafetyErrCallback_Group2(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if(gSafetyCallbackDataVPGroup2[safetyCbData.regionId].safetyInterupt != true)
        {
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].frameCount = gLoopCount;
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVPGroup2[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    
    }
    
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData)
    {
        if(Dss_dispIsVidLInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVIDL.safetyInterupt != true)
            {
                gSafetyCallbackDataVIDL.safetyInterupt = true;
                gSafetyCallbackDataVIDL.pipeId = pipeId;
                gSafetyCallbackDataVIDL.frameCount = gLoopTime;
                gSafetyCallbackDataVIDL.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVIDL.cbData.capturedSign = capturedSign;
            }
        }
    
    }
    
    # if 0
    static int32_t DispApp_logSafetyCheckData()
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t count;
    
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            DebugP_log("****************************************************\r\n");
    
            DebugP_log("Safety Data Log Region : %d\r\n", gSafetyCallbackDataVP[count].cbData.regionId);
            DebugP_log("Safety Data VP ID: %s\r\n",gSafetyCallbackDataVP[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    
            if(gSafetyCallbackDataVP[count].safetyInterupt == true)
            {
                DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVP[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVP[count].frameCount < gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVP[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP[count].frameCount);
                DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP[count].cbData.capturedSign);
            }
            else
            {
                status = SystemP_FAILURE;
                DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
            }
    
        }
    
        for(uint32_t instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                if(Dss_dispIsVidInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VID1\r\n");
    
                    if(gSafetyCallbackDataVID.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVID.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVID.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVID.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
                else if(Dss_dispIsVidLInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VIDL1\r\n");
    
                    if(gSafetyCallbackDataVIDL.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVIDL.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVIDL.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVIDL.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
            }
        }
    
        return status;
    }
    #else
    /* [修改] 安全检查数据日志函数 - 支持两个组的日志输出 */
    static int32_t DispApp_logSafetyCheckData()
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t count;
        uint32_t detectedErrors = 0;
    
        DebugP_log("\r\n");
        DebugP_log("============== DSS Safety Test Results ==============\r\n");
        /* [修改] 更新总区域数量信息 */
        DebugP_log("Total safety regions monitored: %d in 2 groups\r\n", CONFIG_DSS_NUM_SAFETY_REGIONS_TOTAL);
    
        /* [新增] Log results for Group 1 (Regions 0-3) */
        DebugP_log("--- Safety Group 1 Results (Regions 0-3) ---\r\n");
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP; count++)
        {
            DebugP_log("****************************************************\r\n");
            /* [修改] 更新区域显示信息 */
            DebugP_log("Safety Data Log Region : %d (Global Region %d)\r\n", 
                       gSafetyCallbackDataVPGroup1[count].cbData.regionId,
                       gSafetyCallbackDataVPGroup1[count].cbData.regionId);
            DebugP_log("Safety Data VP ID: %s\r\n", 
                       gSafetyCallbackDataVPGroup1[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    
            if(gSafetyCallbackDataVPGroup1[count].safetyInterupt == true)
            {
                detectedErrors++;
                DebugP_log("Safety Check Interrupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVPGroup1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVPGroup1[count].frameCount < gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        DebugP_log("WARNING: Freeze detected earlier than threshold!\r\n");
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVPGroup1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVPGroup1[count].frameCount);
                DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVPGroup1[count].cbData.capturedSign);
                /* [修改] 使用正确的配置数组 */
                DebugP_log("Expected Signature: 0x%lX\r\n", gDssVpSafetyParams[count].regionSafetyChkCfg.referenceSign);
            }
            else
            {
                DebugP_log("Safety Check Interrupt Trigger: FALSE\r\n");
                DebugP_log("No safety errors detected in this region\r\n");
            }
        }
    
        /* [新增] Log results for Group 2 (Regions 4-7) */
        DebugP_log("--- Safety Group 2 Results (Regions 4-7) ---\r\n");
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP; count++)
        {
            DebugP_log("****************************************************\r\n");
            /* [修改] 更新区域显示信息,显示全局区域ID */
            DebugP_log("Safety Data Log Region : %d (Global Region %d)\r\n", 
                       gSafetyCallbackDataVPGroup2[count].cbData.regionId,
                       gSafetyCallbackDataVPGroup2[count].cbData.regionId + 4);
            DebugP_log("Safety Data VP ID: %s\r\n", 
                       gSafetyCallbackDataVPGroup2[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    
            if(gSafetyCallbackDataVPGroup2[count].safetyInterupt == true)
            {
                detectedErrors++;
                DebugP_log("Safety Check Interrupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVPGroup2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVPGroup2[count].frameCount < gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        DebugP_log("WARNING: Freeze detected earlier than threshold!\r\n");
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVPGroup2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVPGroup2[count].frameCount);
                DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVPGroup2[count].cbData.capturedSign);
                /* [修改] 使用Group 2的配置数组 */
                DebugP_log("Expected Signature: 0x%lX\r\n", gDssVpSafetyParams[count].regionSafetyChkCfg.referenceSign);
            }
            else
            {
                DebugP_log("Safety Check Interrupt Trigger: FALSE\r\n");
                DebugP_log("No safety errors detected in this region\r\n");
            }
        }
    
        /* Log pipeline safety results */
        for(uint32_t instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                if(Dss_dispIsVidLInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
                    DebugP_log("Safety Data Pipeline ID: VIDL1\r\n");
    
                    if(gSafetyCallbackDataVIDL.safetyInterupt == true)
                    {
                        detectedErrors++;
                        DebugP_log("Safety Check Interrupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVIDL.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                DebugP_log("WARNING: Freeze detected earlier than threshold!\r\n");
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVIDL.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVIDL.cbData.capturedSign);
                    }
                    else
                    {
                        DebugP_log("Safety Check Interrupt Trigger: FALSE\r\n");
                        DebugP_log("No safety errors detected in VIDL pipeline\r\n");
                    }
                }
            }
        }
    
        DebugP_log("****************************************************\r\n");
        DebugP_log("Total safety errors detected: %d\r\n", detectedErrors);
        DebugP_log("====================================================\r\n");
    
        return status;
    }
    #endif
    
    
    static int32_t DispApp_configDctrlSafetyGroup(Dss_Object *appObj, uint32_t groupId)
    {
        int32_t retVal = FVID2_SOK;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        memset(vpSafetyParams, 0, sizeof(Dss_DctrlVpSafetyChkParams) * CSL_DSS_VP_SAFETY_REGION_MAX);
        
        /* Select the active group parameters from pre-defined arrays */
        if(groupId == 0)
        {
    		 for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP; count++)
            {
                vpSafetyParams[count].vpId = gDssVpSafetyParams[count].vpId;
                vpSafetyParams[count].safetySignSeedVal = gDssVpSafetyParams[count].safetySignSeedVal;
                vpSafetyParams[count].regionSafetyChkCfg.regionId = gDssVpSafetyParams[count].regionSafetyChkCfg.regionId;
                vpSafetyParams[count].regionSafetyChkCfg.referenceSign = gDssVpSafetyParams[count].regionSafetyChkCfg.referenceSign;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
                vpSafetyParams[count].appData = &gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
                vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback_Group1;
                DebugP_log("tyw test 1 regionId %d\r\n", vpSafetyParams[count].regionSafetyChkCfg.regionId);
            }
        }
        else if(groupId == 1)
        {
             for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP; count++)
            {
                vpSafetyParams[count].vpId = gDssVpSafetyParams_Group1[count].vpId;
                vpSafetyParams[count].safetySignSeedVal = gDssVpSafetyParams_Group1[count].safetySignSeedVal;
                vpSafetyParams[count].regionSafetyChkCfg.regionId = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.regionId;
                vpSafetyParams[count].regionSafetyChkCfg.referenceSign = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.referenceSign;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
                vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
                vpSafetyParams[count].appData = &gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
                vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback_Group2;
                DebugP_log("tyw test 2 regionId %d\r\n", vpSafetyParams[count].regionSafetyChkCfg.regionId + 4);
            }
        }
      
        /* Configure the safety regions for the active group */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS_PER_GROUP; count++)
        {
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
                vpSafetyParams + count,
                NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set Safety Params IOCTL Failed for group %d region %d!!!\r\n", groupId, count);
                break;
            }
        }
    
        return retVal;
    }

     

    o note that this will need lot of effort to develop and a significant software change which should be owned by the customer.

    got it. But we anticipate that we may need to turn to you for advice on relevant issues fairly often. Some DSS attributes cannot be unchecked in SysConfig. This does not cause any effects, does it?

    Thank you very much for your time and support. We look forward to your prompt response.


    Best regard!

  • Hi,
    Code output at my end:
    Without corruption:

    --------------------------------------------------------------------------------
    Log PRINT:  Value: c9654f7e----------
    Log PRINT:  Value: f6ba4989----------
    Log PRINT:  Value: ccfa10e0----------
    Log PRINT:  Value: 7fe99f52----------
    Log PRINT:  Value: 709404a5----------
    Log PRINT:  Value: 2f469430----------
    --------------------------------------------------------------------------------
    Underflow did not occur
    Underflow did not occur
    Sync Lost did not occur
    Display delete complete!!
    DispApp_deInit() - DONE !!!
    ****************************************************
    Safety Data Log Region : 0
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 7
    Safety Data Captured Signature: 0xCCFA10E0
    ****************************************************
    Safety Data Log Region : 1
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 19
    Safety Data Captured Signature: 0x7FE99F52
    ****************************************************
    Safety Data Log Region : 0
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: FALSE
    ****************************************************
    Safety Data Log Region : 0
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: FALSE
    ****************************************************
    Safety Data Pipeline ID: VID1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 30
    Safety Data Captured Signature: 0xF6BA4989
    ****************************************************
    Safety Data Pipeline ID: VIDL1
    Safety Check Interupt Trigger: FALSE
    Log PRINT:  Value: c9654f7e----------
    Log PRINT:  Value: f6ba4989----------
    Log PRINT:  Value: fd1e140b----------
    Log PRINT:  Value: b7a6549a----------
    Log PRINT:  Value: c4ef1f47----------
    Log PRINT:  Value: fd86f36a----------
    DSS Safety Test Failed!!

    With corruption (default example):
    --------------------------------------------------------------------------------
    Log PRINT:  Value: c9654f7e----------
    Log PRINT:  Value: f6ba4989----------
    Log PRINT:  Value: f8ebdee8----------
    Log PRINT:  Value: 89dd3f5----------
    Log PRINT:  Value: 709404a5----------
    Log PRINT:  Value: 2f469430----------
    --------------------------------------------------------------------------------
    Underflow did not occur
    Underflow did not occur
    Sync Lost did not occur
    Display delete complete!!
    DispApp_deInit() - DONE !!!
    ****************************************************
    Safety Data Log Region : 0
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 7
    Safety Data Captured Signature: 0xCCFA10E0
    ****************************************************
    Safety Data Log Region : 1
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 19
    Safety Data Captured Signature: 0x7FE99F52
    ****************************************************
    Safety Data Log Region : 2
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: DATA_INTEGRITY
    Safety Data Frame count: 70
    Safety Data Captured Signature: 0x5576A020
    ****************************************************
    Safety Data Log Region : 3
    Safety Data VP ID: VP1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: DATA_INTEGRITY
    Safety Data Frame count: 70
    Safety Data Captured Signature: 0xCD822043
    ****************************************************
    Safety Data Pipeline ID: VID1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: FRAME_FREEZE_DETECT
    Safety Data Frame count: 30
    Safety Data Captured Signature: 0xF6BA4989
    ****************************************************
    Safety Data Pipeline ID: VIDL1
    Safety Check Interupt Trigger: TRUE
    Safety Check Mode: DATA_INTEGRITY
    Safety Data Frame count: 70
    Safety Data Captured Signature: 0xC948AD61
    Log PRINT:  Value: c948ad61----------
    Log PRINT:  Value: c948ad61----------
    Log PRINT:  Value: fd1e140b----------
    Log PRINT:  Value: b7a6549a----------
    Log PRINT:  Value: c4ef1f47----------
    Log PRINT:  Value: fd86f36a----------
    DSS Safety Test Failed!!

    PS: When you don't print logs in default case, you see tests passed, need to investigate this internally. Shouldn't cause any functional issues.

    Now, at your end, we need to check why you are seeing True even with no corruption. In my code, I am dumping all register values; in the continuous register dump, are you seeing register value changes (in without corruption case)?
    Is there any other task running at your end that could interfere with the framebuffer in this example?

    Some DSS attributes cannot be unchecked in SysConfig. This does not cause any effects, does it?

    Can you give an example?

  • Hello,

    There are no other tasks running. We have copied the code you provided above exactly as it is. And the value of the register is same.
    Let's drop the question, A new question: how to set the value of referenceSign,

    Can you give an example?

    In the ti_driver_config.c like "DSS VP Params", "DSS VP Advance Params", and so on. Because we only intend to use the monitor function, these are unnecessary, except for the "DSS VP Safety Params". Would this be the correct understanding?

    Could I just ask, have you been able to review my code for monitoring more than 4 regions? 

    Thanks!

  • Hi,

    how to set the value of referenceSign,

    Your image shows the correct location, you can change the reference signature through the SysConfig tool.

    In the ti_driver_config.c like "DSS VP Params", "DSS VP Advance Params", and so on. Because we only intend to use the monitor function, these are unnecessary, except for the "DSS VP Safety Params". Would this be the correct understanding?

    This question is actually what I meant when saying significant software changes will be needed. I see 2 ways you can go about this (none of those tested):

    1. You give the ownership of Video Port to R5 core all other entities (like pipelines and overlay manager) to A53 core. Now, the R5 core is responsible for setting up of "DSS VP Params", "DSS VP Advance Params", and so on and you'll probably need some IPC communication to synchronize between R5 and A53 core.

    2. All ownership of DSS entities including Video Port is with A53 (in which case A53 will be responsible for configuring values of VP safety regions and registers) while the R5 core subscribes the the safety interrupt and takes required action when such interrupt is received. In this case R5 won't configure DSS at all.

    Could I just ask, have you been able to review my code for monitoring more than 4 regions? 

    You're application is implementing a very custom usecase and we cannot provide code reviews for these.

    I have a few more questions about your target application:

    1. If you are time multiplexing the 4 safety regions among 8, suppose you are monitoring 1 quad of safety region, but the other quad actually hits a safety mismatch, won't you miss that safety interrupt?

    2. From your previous response, I understand you are using 1 VP, but didn't understand what you mean by having 2 'screens'? Are these screens like left half and right half on the same display? If so, why not have 2 separate VPs streaming these 2 screens? 

  • Hello

    Your image shows the correct location, you can change the reference signature through the SysConfig tool.

    Sorry for misleading you. I mean how to set the value of the referenceSign.

    If you are time multiplexing the 4 safety regions among 8, suppose you are monitoring 1 quad of safety region, but the other quad actually hits a safety mismatch, won't you miss that safety interrupt?

    I didn’t quite understand—could you please clarify further?

    From your previous response, I understand you are using 1 VP, but didn't understand what you mean by having 2 'screens'? Are these screens like left half and right half on the same display? If so, why not have 2 separate VPs streaming these 2 screens? 

    All content is displayed on this single screen: first, it display 4 tell-tales; after a period of time, it switches to display a different set of tell-tales, and more. All of them need to be monitor.

    Thanks.

  • Hi,

    Sorry for misleading you. I mean how to set the value of the referenceSign.

    Do you mean how to compute it? You may put in value 0 in the referenceSign, stream your frame, and then check the signature register value to obtain the reference signature for your tell-tale.

    All content is displayed on this single screen: first, it display 4 tell-tales; after a period of time, it switches to display a different set of tell-tales, and more. All of them need to be monitor.

    I didn’t quite understand—could you please clarify further?

    So after a period of time when you switch to the second screen with different set of tell-tales, you don't need to monitor the first set of tell-tales of the screen not being displayed?

  • Hello,

    For example, as shown in the figure below, there are 5 tell-tales, but the VP only supports a maximum of 4 regions. What should we do to monitor all of them? If multiple tell-tales are all included in a single region, how can we figure out which specific one has malfunctioned? Besides, not all tell-tales are arranged in such an orderly way.

    Do you have any good suggestions?

    So after a period of time when you switch to the second screen with different set of tell-tales, you don't need to monitor the first set of tell-tales of the screen not being displayed?

    No,Continuous monitoring is required, but it just needs to be implemented via polling. For example, as shown in the figure above, 5 regions are needed, which can be divided into two polling cycles: monitoring four regions in the first cycle and one region in the second cycle, and repeating this cycle continuously. Is this approach feasible?

  • Hi,
    Checking this internally, will get back within 2 days.

  • Hi,
    I have checked internally. A typical way would be to group tell-tales into single safety-region logically, such that you can check/take similar corrective action on all of those tell-tales present inside that region.

    For example, as shown in the figure above, 5 regions are needed, which can be divided into two polling cycles: monitoring four regions in the first cycle and one region in the second cycle, and repeating this cycle continuously. Is this approach feasible?

    Feasible, but not recommended. When you are streaming and computing signature on your second cycle (with one tell-tale), if any safety interrupt comes on the rest 4 tell tales which have not been configured in the current cycle, you'll miss those interrupts.

  • Hello,

    As mentioned above, how do we know which specific one it is? More importantly, it is difficult to group them together.

    Feasible, but not recommended. When you are streaming and computing signature on your second cycle (with one tell-tale), if any safety interrupt comes on the rest 4 tell tales which have not been configured in the current cycle, you'll miss those interrupts.

    Could you elaborate on the specific implementation approach?

    Thanks!

  • Hi,

    how do we know which specific one it is?

    You won't know, but when more than one tell-tales get clubbed in a single region, you will have to take the trigger a safety action for each of those tell tales as you would do when one of those is triggered.

    More importantly, it is difficult to group them together.

    It would be assumed that tell-tales being clubbed are present next to each other and can fit in a rectangular safety region.

    Could you elaborate on the specific implementation approach?

    Lets assume you are using 12 tell-tales => [T0, T1, T2, ..., T11]
    You have configured 4 VP regions such that [assume there is no tell-tale grouping]
    VP1 has [T0,T4,T8]
    VP2 has [T1,T5,T9]
    VP3 has [T2,T6,T10]
    VP4 has [T3,T7,T11]

    where, in cycle C1, you configure T0 at VP1, T1 at VP2, T2 at VP3, and T3 at VP4, and so on for further cycles C2 and C3.
    Now, the tell-tales T0,T1,T2,T3 will only get checked at the end of cycles C1, C4, C7 and so on.

    Suppose you are currently executing cycle C3, how will you detect any of the safety interrupts for tell-tales {T0, T1, .., T7} ?

    Hopefully this elaborates the safety issue in this approach.

  • Hello,

    You won't know, but when more than one tell-tales get clubbed in a single region, you will have to take the trigger a safety action for each of those tell tales as you would do when one of those is triggered.

    Got it, thanks!

    Hopefully this elaborates the safety issue in this approach.

    Yes, I understand the potential security risks involved. However, if I still want to  implement this method. Could you please share your thoughts on it?

    Best regards!

  • Hi,

    Could you please share your thoughts on it?

    Few things you may want to keep in mind while going with this approach:
    1. Please read the "DISPC Shadow Registers" section in TRM.
    2. You will essentially need 2 framebuffers, one that is streamed, and the other is updated for next frame stream. (This is the approach used in the MCU-SDK as well).
    3. While current frame (say F1) is streaming, and you are updating F2, you will also need to modify the corresponding shadow safety registers in accordance to the next frame and next set of tell-tales you need to monitor (this will not affect current computation).
    4. You set the gobit to tell hardware that next frame (F2) is ready.
    5. You wait for the next VSYNC interrupt (the one received after F2 has been streamed), and then you read the safety registers/interrupts for any issues detected during F2.

    6. Reiterating, we do not have an example for this.

  • Hello,

    Can we make modifications directly based on xx? Our current idea is to create a thread to achieve continuous switching. When is gobit enabled? Are there any functional interfaces, or do we need to set the register directly?

    Thanks!

  • Hi,

    based on xx

    What's xx?

    When is gobit enabled? Are there any functional interfaces, or do we need to set the register directly?

    Please refer the TRM for this info and the MCU+SDK examples for refernce usage. You'll find the usage of the function: Dss_dctrlDrvSetGoBit()

  • Hello,

    Sorry, the  xx is dss_safety_test.c. What are your opinions and suggestions on the method of creating a new thread to handle the switching and monitoring of safety regions?

    Please refer the TRM for this info and the MCU+SDK examples for refernce usage.

    Could you share the link.

    Thanks!

  • Hi,
    Not much to comment here, as long as you are able to synchronise your tasks/threads, you should be good.
    TRM: https://www.ti.com/lit/pdf/spruj83 
    MCUSDK: https://software-dl.ti.com/mcu-plus-sdk/esd/AM62PX/latest/exports/docs/api_guide_am62px/EXAMPLES_DRIVERS.html 

  • Hello,

    The tell-tales within the monitored region are continuously flashing. How should the reference seed be configured?
    For the A-core display and R-core monitoring scheme, do both sides need image data within the region?

    Thanks!

  • Whichever core has been assigned the ownership over VP (video port) will be writing the the register containing the reference seed.

  • Hello Expert,

    Got it,thnaks!

    /*
     *  Copyright (C) 2023 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file dss_safety_test.c
     *
     *  \brief DSS sample application that configures and tests DSS safety features
     *         (Freeze Frame Detect and Data Integrity Check).
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <stdio.h>
    #include <string.h>
    #include <drivers/dss.h>
    #include <drivers/fvid2.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include "ti_drivers_open_close.h"
    #include "ti_drivers_config.h"
    #include "ti_board_open_close.h"
    
    
    #include <kernel/dpl/TaskP.h>
    #include "ti_drivers_open_close.h"
    #include "ti_drivers_config.h"
    #include "ti_board_open_close.h"
    
    #include "FreeRTOS.h"
    #include "task.h"
    #include <drivers/device_manager/sciclient.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* Number of frames */
    #define DISP_NUM_FRAMES_COUNT               ((uint32_t)100U)
    
    /* Max frame size based on resolution */
    #define DISP_FRAME_SIZE_MAX                 (3840U*1080U)
    
    /* Max pixel width */
    #define DISP_FRAME_PIXEL_WIDTH_MAX          (4U)
    
    /* Corrupt frame number */
    #define DISP_FRAME_CORRUPT_NUM              (70U)
    
    /* 安全参数循环切换任务定义 */
    #define SAFETY_SWITCH_TASK_SIZE    (2048U)  /* 任务堆栈大小 */
    #define SAFETY_SWITCH_TASK_PRI     (4U)     /* 任务优先级 */
    
    /* 显示任务定义 */
    #define DISPLAY_TASK_SIZE          (4096U)  /* 任务堆栈大小 */
    #define DISPLAY_TASK_PRI           (3U)     /* 任务优先级 */
    
    #define SAFETY_SWITCH_FRAME_INTERVAL 30  // 每30帧切换一次
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    typedef struct
    {
        uint32_t safetyInterupt;
        /**< Flag to check interupt received */
        uint32_t vpId;
        /**< Video Port Id */
        uint32_t pipeId;
        /**< Pipe Id */
        uint32_t frameCount;
        /**< Frame Count */
        uint32_t safetyCheckMode;
        /**< Mode of operation of the safety check module */
    
         Dss_DctrlVpSafetyCbData cbData;
        /**< Safety Error callback data to be returned to application */
    
    } Dss_safetyTestCbData;
    
    /* 安全参数循环管理器结构体 */
    typedef struct {
        Dss_Object *dssAppObj;           /* DSS应用对象指针 */
        uint8_t currentGroup;            /* 当前激活的组(0或1) */
        uint32_t switchIntervalMs;       /* 切换间隔(毫秒) */
        volatile bool running;           /* 任务运行标志 */
        uint32_t switchCount;            /* 切换次数统计 */
    } SafetyParamCycleManager;
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static void DispApp_init(Dss_Object *appObj);
    static void DispApp_deInit(Dss_Object *appObj);
    static void DispApp_create(Dss_Object *appObj);
    static void DispApp_delete(Dss_Object *appObj);
    static int32_t DispApp_configDctrl(Dss_Object *appObj);
    static int32_t DispApp_runTest(Dss_Object *appObj);
    static void DispApp_initPipelineParams(Dss_Object *appObj);
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj);
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData);
    static void DispApp_initDssParams(Dss_Object *appObj);
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData);
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData);
    static int32_t DispApp_logSafetyCheckData();
    
    /* 新增函数声明 */
    static int32_t DispApp_switchSafetyParamsGroup(Dss_Object *appObj, uint8_t groupIdx);
    static void DispApp_safetyParamCycleThread(void *args);
    static void DispApp_displayTask(void *args);
    
    extern void Disp_prepareFrameBuffer(uint32_t instCount,
                                uint32_t inDataFmt, \
                                uint32_t inWidth, \
                                uint32_t inHeight,\
                                uint32_t pitch, \
                                void* \
                                frameBuffer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE]);
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    uint32_t gStopProfileTime, gStartProfileTime;
    
    /*
     * Global frame buffers. Maximum frames per handle is considered 2 and first frame
     * is used for first pipeline instance and other is used for second pipeline instance.
     */
    uint8_t gFirstPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096)));
    uint8_t gSecondPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096))) ;
    
    /* Pointer to frame buffers per pipleline */
    void *gfirstPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    void *gsecondPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    
    //static Dss_safetyTestCbData gSafetyCallbackDataVP[CONFIG_DSS_NUM_SAFETY_REGIONS];
    static Dss_safetyTestCbData gSafetyCallbackDataVID;
    static Dss_safetyTestCbData gSafetyCallbackDataVIDL;
    
    static Dss_safetyTestCbData gSafetyCallbackDataVP_G1[4];
    static Dss_safetyTestCbData gSafetyCallbackDataVP_G2[4];
    //static uint32_t gCurrentSafetyGroup = 0; /* 0 = Group 1, 1 = Group 2 */
    
    static volatile uint32_t gLoopCount = 0;
    
    static SemaphoreP_Object  gDisplaySafeSem;
    
    /* 任务堆栈和对象 */
    static uint8_t gSafetySwitchTaskStack[SAFETY_SWITCH_TASK_SIZE] __attribute__((aligned(32)));
    static TaskP_Object gSafetySwitchTask;
    static uint8_t gDisplayTaskStack[DISPLAY_TASK_SIZE] __attribute__((aligned(32)));
    static TaskP_Object gDisplayTask;
    static volatile bool gDisplayTaskRunning = false;
    
    static SafetyParamCycleManager gSafetyCycleMgr = {
        .dssAppObj = NULL,
        .currentGroup = 0,
        .switchIntervalMs = 1000,        /* 默认1秒切换一次 */
        .running = false,
        .switchCount = 0
    };
    
    /* DSS VP Safety Params Group 1 */
    Dss_DctrlVpSafetyChkParams gDssVpSafetyParams_Group1[CONFIG_DSS_NUM_SAFETY_REGIONS] =
    {
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_0,
                .referenceSign = 0xC4EF1F47U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 40U,
                        .startY = 0U,
                    },
                    .regionSize = {
                        .width = 40U,
                        .height = 30U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_1,
                .referenceSign = 0xC4EF1E36U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 180U,
                        .startY = 100U,
                    },
                    .regionSize = {
                        .width = 80U,
                        .height = 60U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_2,
                .referenceSign = 0x709404A5U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1040U,
                        .startY = 840U,
                    },
                    .regionSize = {
                        .width = 40U,
                        .height = 20U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_3,
                .referenceSign = 0x2F469430U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1700U,
                        .startY = 920U,
                    },
                    .regionSize = {
                        .width = 60U,
                        .height = 40U,
                    }
                },
            },
        },
    };
    
    /* DSS VP Safety Params Group 2 */
    Dss_DctrlVpSafetyChkParams gDssVpSafetyParams_Group2[CONFIG_DSS_NUM_SAFETY_REGIONS] =
    {
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_0,
                .referenceSign = 0xDEADBEEFU,  /* 不同的参考签名 */
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 60U,  /* 不同的位置 */
                        .startY = 20U,
                    },
                    .regionSize = {
                        .width = 50U,   /* 不同的大小 */
                        .height = 40U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_1,
                .referenceSign = 0xCAFEBABEU,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 200U,
                        .startY = 120U,
                    },
                    .regionSize = {
                        .width = 70U,
                        .height = 50U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_2,
                .referenceSign = 0x12345678U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1060U,
                        .startY = 860U,
                    },
                    .regionSize = {
                        .width = 50U,
                        .height = 30U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_3,
                .referenceSign = 0x87654321U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1720U,
                        .startY = 940U,
                    },
                    .regionSize = {
                        .width = 70U,
                        .height = 50U,
                    }
                },
            },
        },
    };
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void DispApp_initFrames()
    {
        uint32_t instCnt = 0;
        uint32_t numPipes = gDssConfigPipelineParams.numTestPipes <= DSS_DISP_INST_MAX \
                            ? gDssConfigPipelineParams.numTestPipes : DSS_DISP_INST_MAX;
    
        for(instCnt = 0; instCnt < CONFIG_DSS_NUM_FRAMES_PER_PIPELINE; instCnt++)
        {
            gfirstPipeFrameBufferPointer[instCnt] = &gFirstPipelineFrameBuf[instCnt];
            gsecondPipeFrameBufferPointer[instCnt] = &gSecondPipelineFrameBuf[instCnt];
        }
    
        for(instCnt = 0U; instCnt< numPipes ; instCnt++)
        {
            if(instCnt == 0)
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gfirstPipeFrameBufferPointer);
            }
            else
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gsecondPipeFrameBufferPointer);
            }
        }
    }
    
    /*
     * DSS display test
     */
    void dss_safety_test_main(void *args)
    {
        int32_t retVal = SystemP_SUCCESS;
    
        /* Initialise frames */
        DispApp_initFrames();
    
        DispApp_init(&gDssObjects[CONFIG_DSS0]);
    
        DebugP_log("DSS display application started...\r\n");
    
        retVal = DispApp_runTest(&gDssObjects[CONFIG_DSS0]);
    
        DispApp_deInit(&gDssObjects[CONFIG_DSS0]);
    
        retVal = DispApp_logSafetyCheckData();
    
        if(SystemP_SUCCESS == retVal)
        {
            DebugP_log("DSS Safety Test Passed!!\r\n");
        }
        else
        {
            DebugP_log("DSS Safety Test Failed!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_init(Dss_Object *appObj)
    {
        int32_t         retVal = FVID2_SOK;
        Fvid2_InitPrms  initPrms;
    
        Fvid2InitPrms_init(&initPrms);
        retVal = Fvid2_init(&initPrms);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Fvid2 Init Failed!!!\r\n");
        }
    
        Dss_initParamsInit(&appObj->initParams);
    
        Dss_init(&appObj->initParams);
    
        if(FVID2_SOK == retVal)
        {
            /* Create DCTRL handle, used for common driver configuration */
            appObj->dctrlHandle = Fvid2_create(
                DSS_DCTRL_DRV_ID,
                DSS_DCTRL_INST_0,
                NULL,
                NULL,
                NULL);
            if(NULL == appObj->dctrlHandle)
            {
                DebugP_log("DCTRL Create Failed!!!\r\n");
            }
        }
    
        if(appObj->oldiParams != NULL)
        {
            Dss_setOLDITxPowerDown(appObj->oldiParams->oldiCfg.oldiMapType, TRUE);
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("DispApp_init() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_deInit(Dss_Object *appObj)
    {
        int32_t  retVal = FVID2_SOK;
    
        /* Delete DCTRL handle */
        retVal = Fvid2_delete(appObj->dctrlHandle, NULL);
        retVal += Dss_deInit();
        retVal += Fvid2_deInit(NULL);
        if(retVal != FVID2_SOK)
        {
             DebugP_log("DCTRL handle delete failed!!!\r\n");
        }
        else
        {
             DebugP_log("DispApp_deInit() - DONE !!!\r\n");
        }
    
        return;
    }
    //Add
    /* Safety parameter cyclic switching task */
    static void DispApp_safetyParamCycleThread(void *args)
    {
        Dss_Object *appObj = (Dss_Object *)args;
        uint32_t lastFrameCount = 0;
        
        /* 任务主循环 */
        while(gSafetyCycleMgr.running)
        {
            /* 等待切换间隔 */
            vTaskDelay(17);
             #if 0
            if(!gSafetyCycleMgr.running) {
                break;
            }
            
            /* 计算下一个要切换的组 */
            uint8_t newGroup = (gSafetyCycleMgr.currentGroup + 1) % 2;
            
            DebugP_log("[SafetyCycleTask] Switching: Group %d -> Group %d (Count: %d)\r\n", 
                       gSafetyCycleMgr.currentGroup, newGroup, gSafetyCycleMgr.switchCount + 1);
            
            /* 确保显示不在关键操作中时切换 */
                SemaphoreP_pend(&gDisplaySafeSem, SystemP_WAIT_FOREVER);
                int32_t retVal = DispApp_switchSafetyParamsGroup(appObj, newGroup);
                SemaphoreP_post(&gDisplaySafeSem);
            if(retVal == FVID2_SOK) {
                /* 更新管理器状态 */
    
                gSafetyCycleMgr.currentGroup = newGroup;
                gSafetyCycleMgr.switchCount++;
            } else {
                DebugP_log("[SafetyCycleTask] Switch failed! Ret: %d\r\n", retVal);
            }
            #endif
             /* 检查是否达到切换帧数 */
            if(gLoopCount - lastFrameCount >= 10)
            {
                //uint8_t newGroup = (gSafetyCycleMgr.currentGroup + 1) % 2;
                uint8_t newGroup = 1;
                /* 确保显示不在关键操作中时切换 */
                SemaphoreP_pend(&gDisplaySafeSem, SystemP_WAIT_FOREVER);
                DispApp_switchSafetyParamsGroup(appObj, newGroup);
                SemaphoreP_post(&gDisplaySafeSem);
                
                gSafetyCycleMgr.currentGroup = newGroup;
                gSafetyCycleMgr.switchCount++;
                lastFrameCount = gLoopCount;
                
                DebugP_log("[Safety] Frame %d: Switched to Group %d\r\n", 
                           gLoopCount, newGroup);
            }
            
        }
        
        DebugP_log("[SafetyCycleTask] Exited\r\n");
    }
    //Add
    /* Display task */
    static void DispApp_displayTask(void *args)
    {
        Dss_Object *appObj = (Dss_Object *)args;
        int32_t retVal = FVID2_SOK;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
        Fvid2_FrameList  frmList;
        
        DebugP_log("[DisplayTask] Started\r\n");
         
        /* 启动显示驱动 */
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
            
            retVal = Fvid2_start(instObj->drvHandle, 0);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("[DisplayTask] Display Start Failed!!!\r\n");
                gDisplayTaskRunning = false;
                return;
            }
        }
        
        DebugP_log("[DisplayTask] Display started, running for %d frames\r\n", DISP_NUM_FRAMES_COUNT);
        gStartProfileTime = (ClockP_getTimeUsec() / 1000U);
        
        while(gDisplayTaskRunning && gLoopCount < DISP_NUM_FRAMES_COUNT)
        {
            /* 在帧处理前获取锁 */
            SemaphoreP_pend(&gDisplaySafeSem, SystemP_WAIT_FOREVER);
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
                
                /* 等待显示回调信号量 */
                (void) SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
                
                retVal = Fvid2_dequeue(instObj->drvHandle,
                                       &frmList,
                                       0U,
                                       FVID2_TIMEOUT_NONE);
                
                /* 在第70帧时引入数据完整性错误 */
                if(gLoopCount == DISP_FRAME_CORRUPT_NUM)
                {
                    DebugP_log("[DisplayTask] Frame %d: Injecting data corruption, Safety Group: %d\r\n", 
                               gLoopCount, gSafetyCycleMgr.currentGroup);
                    
                    for(uint32_t count = 0; count < gDssConfigPipelineParams.inHeight[instCnt] * \
                    gDssConfigPipelineParams.pitch[instCnt][0]; count++)
                    {
                        *(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
                    }
                }
                
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
                    if(FVID2_SOK != retVal)
                    {
                        DebugP_log("[DisplayTask] Queue Failed!!!\r\n");
                    }
                }
                else if (FVID2_EAGAIN == retVal)
                {
                    /* Do nothing as this is first callback */
                }
                else
                {
                    DebugP_log("[DisplayTask] Dequeue Failed!!!\r\n");
                }
            }
            /* 释放锁,允许安全参数切换 */
            SemaphoreP_post(&gDisplaySafeSem);
            /* 每10帧打印一次进度 */
            if(gLoopCount % 10 == 0) {
                DebugP_log("[DisplayTask] Frame: %d, Safety Group: %d\r\n", 
                           gLoopCount, gSafetyCycleMgr.currentGroup);
            }
            
            gLoopCount++;
        }
        
        gStopProfileTime = (ClockP_getTimeUsec() / 1000U);
        
        /* 停止显示驱动 */
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
            retVal  = Fvid2_stop(instObj->drvHandle, NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("[DisplayTask] Stop Failed!!!\r\n");
            }
        }
        if(FVID2_SOK == retVal)
        {
            /* Delete driver */
            DispApp_delete(appObj);
            DispApp_deInit(&gDssObjects[CONFIG_DSS0]);
        }
    
        TaskP_destruct(&gDisplayTask);
        DebugP_log("[DisplayTask] Completed, total frames: %d\r\n", gLoopCount);
        gDisplayTaskRunning = false;
    }
    
    static int32_t DispApp_runTest(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        TaskP_Params taskParams;
        int32_t status = SystemP_SUCCESS;
        /* 创建驱动 */
        DispApp_create(appObj);//这里配置了vp安全
        
        DebugP_log("Starting DSS safety test with dynamic parameter cycling...\r\n");
        DebugP_log("Safety parameters will cycle every %d ms\r\n", gSafetyCycleMgr.switchIntervalMs);
          /* 创建互斥信号量 */
        status = SemaphoreP_constructBinary(&gDisplaySafeSem, 1);  // 初始值为1
        if (status != SystemP_SUCCESS)
        {
            DebugP_log("Failed to create display safety semaphore!!!\r\n");
            return status;
        }
        /* 初始化安全参数循环管理器 */
        gSafetyCycleMgr.dssAppObj = appObj;
        gSafetyCycleMgr.running = true;
        gSafetyCycleMgr.switchCount = 0;
        gLoopCount = 0;  /* 重置帧计数器 */
    
        if (status != SystemP_SUCCESS)
        {
            DebugP_log("Failed to create exchange semaphore!!!\r\n");
            return status;
        }
        /* 创建安全参数循环切换任务 */
        TaskP_Params_init(&taskParams);
        taskParams.name = "SafetyParamCycle";
        taskParams.stackSize = SAFETY_SWITCH_TASK_SIZE;
        taskParams.stack = &gSafetySwitchTaskStack[0];
        taskParams.priority = SAFETY_SWITCH_TASK_PRI;
        taskParams.args = (void*)appObj;
        taskParams.taskMain = DispApp_safetyParamCycleThread;
        
        retVal = TaskP_construct(&gSafetySwitchTask, &taskParams);
        if(retVal != SystemP_SUCCESS) {
            DebugP_log("Failed to create safety parameter cycle task!!!\r\n");
            gSafetyCycleMgr.running = false;
        } else {
            DebugP_log("Safety parameter cycle task created successfully\r\n");
        }
        
        /* 创建显示任务 */
        gDisplayTaskRunning = true;
        TaskP_Params_init(&taskParams);
        taskParams.name = "DisplayTask";
        taskParams.stackSize = DISPLAY_TASK_SIZE;
        taskParams.stack = &gDisplayTaskStack[0];
        taskParams.priority = DISPLAY_TASK_PRI;
        taskParams.args = (void*)appObj;
        taskParams.taskMain = DispApp_displayTask;
        
        retVal = TaskP_construct(&gDisplayTask, &taskParams);
        if(retVal != SystemP_SUCCESS) {
            DebugP_log("Failed to create display task!!!\r\n");
            gDisplayTaskRunning = false;
        } else {
            DebugP_log("Display task created successfully\r\n");
        }
        
        /* 等待显示任务完成 */
        while(gDisplayTaskRunning) {
            vTaskDelay(100);  /* 每100ms检查一次 */
        }
        
        /* 停止安全参数切换任务 */
        gSafetyCycleMgr.running = false;
        vTaskDelay(200);  /* 给任务一点时间退出循环 */
        TaskP_destruct(&gSafetySwitchTask);
        
        DebugP_log("Test completed, total safety group switches: %d\r\n", 
                   gSafetyCycleMgr.switchCount);
        
        if(FVID2_SOK == retVal)
        {
            /* 删除驱动 */
            DispApp_delete(appObj);
        }
        
        return (retVal != FVID2_SOK? SystemP_FAILURE:SystemP_SUCCESS);
    }
    
    static void DispApp_initDssParams(Dss_Object *appObj)
    {
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
       // Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        globalDssParams = &appObj->globalDssParams;
        //vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        
        Dss_dctrlVpParamsInit(vpParams);
        Dss_dctrlAdvVpParamsInit(advVpParams);
        Dss_dctrlOverlayParamsInit(overlayParams);
        Dss_dctrlOverlayLayerParamsInit(layerParams);
        Dss_dctrlGlobalDssParamsInit(globalDssParams);
    	//Change
       #if 0 
        /* 初始化安全参数 */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            Dss_dctrlVpSafetyChkParamsInit(vpSafetyParams + count);
        }
    #endif  
        /* Configure VP params */
        vpParams->vpId = gDssVpParams.vpId;
        vpParams->lcdOpTimingCfg.mInfo.standard = gDssVpParams.lcdOpTimingCfg.mInfo.standard;
        vpParams->lcdOpTimingCfg.mInfo.width = gDssVpParams.lcdOpTimingCfg.mInfo.width;
        vpParams->lcdOpTimingCfg.mInfo.height = gDssVpParams.lcdOpTimingCfg.mInfo.height;
        vpParams->lcdOpTimingCfg.mInfo.hFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.hBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.hSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.hSyncLen;
        vpParams->lcdOpTimingCfg.mInfo.vFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.vBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.vSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.vSyncLen;
        
        vpParams->lcdOpTimingCfg.dvoFormat = gDssVpParams.lcdOpTimingCfg.dvoFormat;
        vpParams->lcdOpTimingCfg.videoIfWidth = gDssVpParams.lcdOpTimingCfg.videoIfWidth;
        
        vpParams->lcdPolarityCfg.actVidPolarity =  gDssVpParams.lcdPolarityCfg.actVidPolarity;
        vpParams->lcdPolarityCfg.hsPolarity = gDssVpParams.lcdPolarityCfg.hsPolarity;
        vpParams->lcdPolarityCfg.vsPolarity = gDssVpParams.lcdPolarityCfg.vsPolarity;
        vpParams->lcdPolarityCfg.pixelClkPolarity = gDssVpParams.lcdPolarityCfg.pixelClkPolarity ;
        
        /* Configure VP Advance Params*/
        advVpParams->vpId = gDssAdvVpParams.vpId;
        advVpParams->lcdAdvSignalCfg.hVAlign = gDssAdvVpParams.lcdAdvSignalCfg.hVAlign;
        advVpParams->lcdAdvSignalCfg.hVClkControl = gDssAdvVpParams.lcdAdvSignalCfg.hVClkControl;
    	//Change
      #if 0  
        /* 配置安全参数 - 只初始化第一组 */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            vpSafetyParams[count].vpId = gDssVpSafetyParams_Group1[count].vpId;
            vpSafetyParams[count].safetySignSeedVal = gDssVpSafetyParams_Group1[count].safetySignSeedVal;
            vpSafetyParams[count].regionSafetyChkCfg.regionId = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.regionId;
            vpSafetyParams[count].regionSafetyChkCfg.referenceSign = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.referenceSign;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
            
            vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback;
            vpSafetyParams[count].appData = &vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
        }
     #endif   
        /* Configure Overlay Params */
        overlayParams->overlayId =  gDssOverlayParams.overlayId;
        overlayParams->colorbarEnable =  gDssOverlayParams.colorbarEnable;
        overlayParams->overlayCfg.colorKeyEnable =  gDssOverlayParams.overlayCfg.colorKeyEnable;
        overlayParams->overlayCfg.colorKeySel =  gDssOverlayParams.overlayCfg.colorKeySel;
        overlayParams->overlayCfg.backGroundColor =  gDssOverlayParams.overlayCfg.backGroundColor;
        
        /* Configure Overlay Layer params */
        layerParams->overlayId = gDssOverlayLayerParams.overlayId;
        memcpy((void*)layerParams->pipeLayerNum, (void* )gDssOverlayLayerParams.pipeLayerNum, \
        sizeof(gDssOverlayLayerParams.pipeLayerNum));
    }
    
    static void DispApp_create(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        int32_t status = SystemP_SUCCESS;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
        
        /* Init VP, Overlay and Panel params */
        DispApp_initDssParams(appObj);
        
        /* Configure DSS pipeline params */
        DispApp_initPipelineParams(appObj);
        
        /* Config IOCTL for VP, Overlay and Panel */
        retVal = DispApp_configDctrl(appObj);
        
        if(retVal == FVID2_SOK)
        {
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
                
                status = SemaphoreP_constructBinary(&instObj->syncSem, 0);
                if(status != SystemP_SUCCESS)
                {
                    retVal = FVID2_EFAIL;
                }
                
                instObj->drvHandle = Fvid2_create(
                    DSS_DISP_DRV_ID,
                    instObj->instId,
                    &instObj->createParams,
                    &instObj->createStatus,
                    &instObj->cbParams);
                
                if((NULL == instObj->drvHandle) ||
                   (instObj->createStatus.retVal != FVID2_SOK))
                {
                    DebugP_log("Display Create Failed!!!\r\n");
                    retVal = instObj->createStatus.retVal;
                }
                
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_DSS_PARAMS,
                        &instObj->dispParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
                    }
                }
                
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS,
                        &instObj->mflagParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Mflag Params IOCTL Failed!!!\r\n");
                    }
                }
                
                if(FVID2_SOK == retVal)
                {
                    if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
                    {
                        retVal = Fvid2_control(
                            instObj->drvHandle,
                            IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS,
                            &instObj->safetyParams,
                            NULL);
                        if(retVal != FVID2_SOK)
                        {
                            DebugP_log("DSS Set Safety Params IOCTL Failed!!!\r\n");
                        }
                    }
                }
                
                if(FVID2_SOK == retVal)
                {
                    retVal = DispApp_allocAndQueueFrames(appObj, instObj);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("Display Alloc and Queue Failed!!!\r\n");
                    }
                }
                
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
        }
        
        if(FVID2_SOK == retVal)
        {
            DebugP_log("Display create complete!!\r\n");
        }
        
        return;
    }
    
    static void DispApp_delete(Dss_Object *appObj)
    {
        int32_t retVal;
        uint32_t instCnt;
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlVpErrorStats *pErrorStats;
        Dss_InstObject *instObj;
        Dss_DispCurrentStatus currStatus;
        Fvid2_FrameList frmList;
        
        vpParams = &appObj->vpParams;
        pErrorStats = &appObj->errorStats;
        
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
            
            /* Check for DSS underflow errors */
            retVal = Fvid2_control(
                instObj->drvHandle,
                IOCTL_DSS_DISP_GET_CURRENT_STATUS,
                &currStatus,
                NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Failed to get Display Stats!!!\r\n");
            }
            
            /* Print Synclost errors */
            if(0U != currStatus.underflowCount)
            {
                GT_2trace(DssTrace, GT_ERR, "No of Underflows for Inst %d: %d\r\n", instCnt, currStatus.underflowCount);
            }
            else
            {
                DebugP_log("Underflow did not occur\r\n");
            }
            
            /* Dequeue all the request from the driver */
            while (1U)
            {
                retVal = Fvid2_dequeue(
                    instObj->drvHandle,
                    &frmList,
                    0U,
                    FVID2_TIMEOUT_NONE);
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
            
            retVal = Fvid2_delete(instObj->drvHandle, NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Delete Failed!!!\r\n");
                break;
            }
        }
        
        /* Check for DSS synclost errors */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_GET_VP_ERROR_STATS,
            pErrorStats,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Failed to get VP Stats!!!\r\n");
        }
        
        /* Print Synclost errors */
        if(0U != pErrorStats->syncLost)
        {
            GT_1trace(DssTrace, GT_ERR, "No of Sync Lost: %d\r\n", pErrorStats->syncLost);
        }
        else
        {
            DebugP_log("Sync Lost did not occur\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_CLEAR_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Clear Path Failed!!!\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_STOP_VP,
            vpParams,
            NULL);
        
        if(FVID2_SOK != retVal)
        {
            DebugP_log("VP Stop Failed!!!\r\n");
        }
        
        if(FVID2_SOK == retVal)
        {
            DebugP_log("Display delete complete!!\r\n");
        }
        
        return;
    }
    
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj)
    {
        int32_t  retVal = FVID2_SOK;
        uint32_t frmId, numFrames;
        Fvid2_Frame *frm;
        Fvid2_FrameList frmList;
        
        Fvid2FrameList_init(&frmList);
        frm = instObj->frames;
        numFrames = instObj->numFrames;
        /* init memory pointer for 'numFrames'  */
        for(frmId=0U; frmId<numFrames; frmId++)
        {
            /* init Fvid2_Frame to 0's  */
            Fvid2Frame_init((Fvid2_Frame *)(frm + frmId));
            if(instObj->instId == gDssConfigPipelineParams.instId[0U])
            {
                frm[frmId].addr[0U] = (uint64_t)gfirstPipeFrameBufferPointer[frmId];
            }
            else
            {
                frm[frmId].addr[0U] = (uint64_t)gsecondPipeFrameBufferPointer[frmId];
            }
            
            frm[frmId].fid = FVID2_FID_FRAME;
            frm[frmId].appData = instObj;
            
            /* Set number of frame in frame list - one at a time */
            frmList.numFrames  = 1U;
            frmList.frames[0U] = &frm[frmId];
            
            /*
             * queue the frames in frmList
             * All allocate frames are queued here as an example.
             * In general atleast 2 frames per channel need to queued
             * before starting display,
             * else frame will get dropped until frames are queued
             */
            retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Queue Failed!!!\r\n");
                break;
            }
        }
        
        return (retVal);
    }
    
    static void DispApp_initPipelineParams(Dss_Object *appObj)
    {
        uint32_t instCnt = 0U, numPipes = 0U;
        Dss_DispParams *dispParams;
        Dss_InstObject *instObj;
        
        numPipes = gDssConfigPipelineParams.numTestPipes;
        
        for(instCnt=0U; instCnt<numPipes; instCnt++)
        {
            /* Initialize video pipes */
            instObj = &appObj->instObj[instCnt];
            instObj->instId = gDssConfigPipelineParams.instId[instCnt];
            
            Dss_dispCreateParamsInit(&instObj->createParams);
            Fvid2CbParams_init(&instObj->cbParams);
            
            instObj->cbParams.cbFxn = &DispApp_pipeCbFxn;
            instObj->cbParams.appData = instObj;
            
            dispParams = &instObj->dispParams;
            Dss_dispParamsInit(dispParams);
            
            dispParams->pipeCfg.pipeType = gDssConfigPipelineParams.pipeType[instCnt];
            dispParams->pipeCfg.inFmt.width = gDssConfigPipelineParams.inWidth[instCnt];
            dispParams->pipeCfg.inFmt.height = gDssConfigPipelineParams.inHeight[instCnt];
            
            for(uint32_t count = 0U; count < FVID2_MAX_PLANES; count++)
            {
                dispParams->pipeCfg.inFmt.pitch[count] =
                gDssConfigPipelineParams.pitch[instCnt][count];
            }
            
            dispParams->pipeCfg.inFmt.dataFormat =
            gDssConfigPipelineParams.inDataFmt[instCnt];
            dispParams->pipeCfg.inFmt.scanFormat =
            gDssConfigPipelineParams.inScanFmt[instCnt];
            dispParams->pipeCfg.outWidth = gDssConfigPipelineParams.outWidth[instCnt];
            dispParams->pipeCfg.outHeight = gDssConfigPipelineParams.outHeight[instCnt];
            dispParams->pipeCfg.scEnable = gDssConfigPipelineParams.scEnable[instCnt];
            
            dispParams->alphaCfg.globalAlpha =
            gDssConfigPipelineParams.globalAlpha[instCnt];
            dispParams->alphaCfg.preMultiplyAlpha =
            gDssConfigPipelineParams.preMultiplyAlpha[instCnt];
            dispParams->layerPos.startX = gDssConfigPipelineParams.posx[instCnt];
            dispParams->layerPos.startY = gDssConfigPipelineParams.posy[instCnt];
            
            Dss_dispPipeMflagParamsInit(&instObj->mflagParams);
            
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                Dss_dispPipeSafetyChkParamsInit(&instObj->safetyParams);
                
                instObj->safetyParams.safetySignSeedVal = gDssPipelineSafetyParams[instCnt].safetySignSeedVal;
                instObj->safetyParams.referenceSign = gDssPipelineSafetyParams[instCnt].referenceSign;
                instObj->safetyParams.safetyChkCfg.safetyChkEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkEnable;
                instObj->safetyParams.safetyChkCfg.safetyChkMode = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
                instObj->safetyParams.safetyChkCfg.seedSelectEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.seedSelectEnable;
                instObj->safetyParams.safetyChkCfg.thresholdValue = gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue;
                instObj->safetyParams.safetyChkCfg.frameSkip = gDssPipelineSafetyParams[instCnt].safetyChkCfg.frameSkip;
                instObj->safetyParams.safetyChkCfg.regionPos.startX = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startX;
                instObj->safetyParams.safetyChkCfg.regionPos.startY = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startY;
                instObj->safetyParams.safetyChkCfg.regionSize.width = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.width;
                instObj->safetyParams.safetyChkCfg.regionSize.height = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.height;
                
                instObj->safetyParams.safetyErrCbFxn = DispApp_pipelineSafetyErrCallback;
                instObj->safetyParams.appData = &gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
            }
        }
    }
    
    static int32_t DispApp_configDctrl(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlOldiParams *oldiParams;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        
        oldiParams = appObj->oldiParams;
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        globalDssParams= &appObj->globalDssParams;
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set Path IOCTL Failed!!!\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_ADV_VP_PARAMS,
            advVpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Advance VP Params IOCTL Failed!!!\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_PARAMS,
            vpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set VP Params IOCTL Failed!!!\r\n");
        }
        
        if (appObj->oldiParams != NULL)
        {
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_OLDI_PARAMS,
                oldiParams,
                NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set OLDI Params IOCTL Failed!!!\r\n");
            }
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
            overlayParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Overlay Params IOCTL Failed!!!\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
            layerParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Layer Params IOCTL Failed!!!\r\n");
        }
        
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
            globalDssParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Global DSS Params IOCTL Failed!!!\r\n");
        }
        
        /* 配置安全参数 */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
                vpSafetyParams + count,
                NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set Safety Params IOCTL Failed!!!\r\n");
                break;
            }
        }
        
        return (retVal);
    }
    
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData)
    {
        int32_t retVal  = FVID2_SOK;
        Dss_InstObject *instObj = (Dss_InstObject *) appData;
        
        GT_assert (DssTrace, (NULL != instObj));
        
        /* 添加调试日志 */
        static uint32_t callbackCount = 0;
        callbackCount++;
        if(callbackCount % 20 == 0) {  /* 每20次回调打印一次,避免日志太多 */
            DebugP_log("[DisplayCallback] Callback #%d, Frame: %d\r\n", 
                       callbackCount, gLoopCount);
        }
        
        (void) SemaphoreP_post(&instObj->syncSem);
        
        return (retVal);
    }
    
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if(gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
        {
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].frameCount = gLoopCount;
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVP_G1[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    	if(gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
        {
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyInterupt = true;
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].vpId = vpID;
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].frameCount = gLoopCount;
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
            gSafetyCallbackDataVP_G2[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
        }
    
    }
    
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData)
    {
        if(Dss_dispIsVidInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVID.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVID.safetyInterupt = true;
                gSafetyCallbackDataVID.pipeId = pipeId;
                gSafetyCallbackDataVID.frameCount = gLoopCount;
                gSafetyCallbackDataVID.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVID.cbData.capturedSign = capturedSign;
            }
        }
        else if(Dss_dispIsVidLInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVIDL.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVIDL.safetyInterupt = true;
                gSafetyCallbackDataVIDL.pipeId = pipeId;
                gSafetyCallbackDataVIDL.frameCount = gLoopCount;
                gSafetyCallbackDataVIDL.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVIDL.cbData.capturedSign = capturedSign;
            }
        }
    
    }
    /* 安全检查数据日志函数 - 支持%E4%B8%A4个组的日志输出 */
    static int32_t DispApp_logSafetyCheckData()
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t count;
    
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            DebugP_log("****************************************************\r\n");
    
            DebugP_log("Safety Data Log Region : %d\r\n", gSafetyCallbackDataVP_G1[count].cbData.regionId);
            DebugP_log("Safety Data VP ID: %s\r\n",gSafetyCallbackDataVP_G1[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    		
            if(gSafetyCallbackDataVP_G1[count].safetyInterupt == true)
            {
                DebugP_log("1 Safety Check Interupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVP_G1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("1 Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVP_G1[count].frameCount < gDssVpSafetyParams_Group1[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVP_G1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("1 Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("1 Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP_G1[count].frameCount);
                DebugP_log("1 Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP_G1[count].cbData.capturedSign);
            }
            else
            {
                status = SystemP_FAILURE;
                DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
            }
    		//组2
    		if(gSafetyCallbackDataVP_G2[count].safetyInterupt == true)
            {
                DebugP_log("2 Safety Check Interupt Trigger: TRUE\r\n");
    
                if(gSafetyCallbackDataVP_G2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                {
                    DebugP_log("2 Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                    if(gSafetyCallbackDataVP_G2[count].frameCount < gDssVpSafetyParams_Group2[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                    {
                        status = SystemP_FAILURE;
                    }
                }
                else if(gSafetyCallbackDataVP_G2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                {
                    DebugP_log("2 Safety Check Mode: DATA_INTEGRITY\r\n");
                }
    
                DebugP_log("2 Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP_G2[count].frameCount);
                DebugP_log("2 Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP_G2[count].cbData.capturedSign);
            }
            else
            {
                status = SystemP_FAILURE;
                DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
            }
    
        }
    
        for(uint32_t instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                if(Dss_dispIsVidInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VID1\r\n");
    
                    if(gSafetyCallbackDataVID.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVID.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVID.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVID.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
                else if(Dss_dispIsVidLInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VIDL1\r\n");
    
                    if(gSafetyCallbackDataVIDL.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVIDL.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVIDL.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVIDL.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
            }
        }
    
        return status;
    }
    //Add
    /* Safety parameter group switching function */
    static int32_t DispApp_switchSafetyParamsGroup(Dss_Object *appObj, uint8_t groupIdx)
    {
        int32_t retVal = FVID2_SOK;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        
        /* choose group */
        Dss_DctrlVpSafetyChkParams *newGroup = NULL;
        if(groupIdx == 0) {
            newGroup = gDssVpSafetyParams_Group1;
        } else if(groupIdx == 1) {
            newGroup = gDssVpSafetyParams_Group2;
        } 
         /* init parameter */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            Dss_dctrlVpSafetyChkParamsInit(newGroup + count);
        }
        /* 更新安全参数配置 */
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            vpSafetyParams[count].vpId = newGroup[count].vpId;
            vpSafetyParams[count].safetySignSeedVal = newGroup[count].safetySignSeedVal;
            vpSafetyParams[count].regionSafetyChkCfg.regionId = newGroup[count].regionSafetyChkCfg.regionId;
            vpSafetyParams[count].regionSafetyChkCfg.referenceSign = newGroup[count].regionSafetyChkCfg.referenceSign;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = newGroup[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = newGroup[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = newGroup[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = newGroup[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = newGroup[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
            
            vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback;
            vpSafetyParams[count].appData = &vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            
            /* 重新配置硬件 */
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
                vpSafetyParams + count,
                NULL);
            
            if(retVal != FVID2_SOK) {
                DebugP_log("Safety params switch failed for region %d!!!\r\n", count);
                return retVal;
            }
        }
        
        DebugP_log("Safety parameters switched to Group %d successfully\r\n", groupIdx);
        return FVID2_SOK;
    }

    The code is modified based on dss_safety_test.c, with two additional tasks added—one for display and the other for switching the monitored region. However, during testing, we found that when switching every 30 frames, the screen doesn't freeze but error messages appear. When switching every 10 frames or less, the system freezes, and the screen becomes unresponsive as well. Two log snippets are shown in the figure below. Could you please help check where the issue might be?

       

  • Hello Expert,

    /*
     *  Copyright (C) 2023 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file dss_safety_test.c
     *
     *  \brief DSS sample application that configures and tests DSS safety features
     *         (Freeze Frame Detect and Data Integrity Check).
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <stdio.h>
    #include <string.h>
    #include <drivers/dss.h>
    #include <drivers/fvid2.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include "ti_drivers_open_close.h"
    #include "ti_drivers_config.h"
    #include "ti_board_open_close.h"
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* Number of frames */
    #define DISP_NUM_FRAMES_COUNT               ((uint32_t)100U)
    
    /* Max frame size based on resolution */
    #define DISP_FRAME_SIZE_MAX                 (3840U*1080U)
    
    /* Max pixel width */
    #define DISP_FRAME_PIXEL_WIDTH_MAX          (4U)
    
    /* Corrupt frame number */
    #define DISP_FRAME_CORRUPT_NUM              (70U)
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    typedef struct
    {
        uint32_t safetyInterupt;
        /**< Flag to check interupt received */
        uint32_t vpId;
        /**< Video Port Id */
        uint32_t pipeId;
        /**< Pipe Id */
        uint32_t frameCount;
        /**< Frame Count */
        uint32_t safetyCheckMode;
        /**< Mode of operation of the safety check module */
        Dss_DctrlVpSafetyCbData cbData;
        /**< Safety Error callback data to be returned to application */
    } Dss_safetyTestCbData;
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static void DispApp_init(Dss_Object *appObj);
    static void DispApp_deInit(Dss_Object *appObj);
    static void DispApp_create(Dss_Object *appObj);
    static void DispApp_delete(Dss_Object *appObj);
    static int32_t DispApp_configDctrl(Dss_Object *appObj);
    static int32_t DispApp_runTest(Dss_Object *appObj);
    static void DispApp_initPipelineParams(Dss_Object *appObj);
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj);
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData);
    static void DispApp_initDssParams(Dss_Object *appObj);
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData);
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData);
    static int32_t DispApp_logSafetyCheckData();
    
    extern void Disp_prepareFrameBuffer(uint32_t instCount,
                                uint32_t inDataFmt, \
                                uint32_t inWidth, \
                                uint32_t inHeight,\
                                uint32_t pitch, \
                                void* \
                                frameBuffer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE]);
    
    static int32_t DispApp_switchSafetyParamsGroup(Dss_Object *appObj, uint8_t groupIdx);
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    uint32_t gStopProfileTime, gStartProfileTime;
    
    /*
     * Global frame buffers. Maximum frames per handle is considered 2 and first frame
     * is used for first pipeline instance and other is used for second pipeline instance.
     */
    uint8_t gFirstPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096)));
    uint8_t gSecondPipelineFrameBuf[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE][DISP_FRAME_SIZE_MAX * DISP_FRAME_PIXEL_WIDTH_MAX]__attribute__ ((section (".dssFrameBuffer"), aligned (4096))) ;
    
    /* Pointer to frame buffers per pipleline */
    void *gfirstPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    void *gsecondPipeFrameBufferPointer[CONFIG_DSS_NUM_FRAMES_PER_PIPELINE];
    
    //////new change
    static Dss_safetyTestCbData gSafetyCallbackDataVP_G1[4];
    static Dss_safetyTestCbData gSafetyCallbackDataVP_G2[4];
    
    //static Dss_safetyTestCbData gSafetyCallbackDataVP[CONFIG_DSS_NUM_SAFETY_REGIONS];
    static Dss_safetyTestCbData gSafetyCallbackDataVID;
    static Dss_safetyTestCbData gSafetyCallbackDataVIDL;
    
    static volatile uint32_t gLoopCount;
    
    /// new add
    static volatile uint32_t gcurrentGroup;
    /* DSS VP Safety Params Group 2 */
    Dss_DctrlVpSafetyChkParams gDssVpSafetyParams_Group2[CONFIG_DSS_NUM_SAFETY_REGIONS] =
    {
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_0,
                .referenceSign = 0xDEADBEEFU,  
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 60U,  
                        .startY = 20U,
                    },
                    .regionSize = {
                        .width = 50U,   
                        .height = 40U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_1,
                .referenceSign = 0xCAFEBABEU,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 200U,
                        .startY = 120U,
                    },
                    .regionSize = {
                        .width = 70U,
                        .height = 50U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_2,
                .referenceSign = 0x12345678U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1060U,
                        .startY = 860U,
                    },
                    .regionSize = {
                        .width = 50U,
                        .height = 30U,
                    }
                },
            },
        },
        {
            .vpId = CSL_DSS_VP_ID_1,
            .safetySignSeedVal = 0xFFFFFFFFU,
            .regionSafetyChkCfg = {
                .regionId = CSL_DSS_VP_SAFETY_REGION_3,
                .referenceSign = 0x87654321U,
                .safetyChkCfg = {
                    .safetyChkEnable = TRUE,
                    .safetyChkMode  = CSL_DSS_SAFETY_CHK_DATA_INTEGRITY,
                    .seedSelectEnable = FALSE,
                    .thresholdValue = 0x0U,
                    .frameSkip = CSL_DSS_SAFETY_CHK_FRAME_SKIP_NO,
                    .regionPos = {
                        .startX = 1720U,
                        .startY = 940U,
                    },
                    .regionSize = {
                        .width = 70U,
                        .height = 50U,
                    }
                },
            },
        },
    };
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void DispApp_initFrames()
    {
        uint32_t instCnt = 0;
        uint32_t numPipes = gDssConfigPipelineParams.numTestPipes <= DSS_DISP_INST_MAX \
                            ? gDssConfigPipelineParams.numTestPipes : DSS_DISP_INST_MAX;
    
        for(instCnt = 0; instCnt < CONFIG_DSS_NUM_FRAMES_PER_PIPELINE; instCnt++)
        {
            gfirstPipeFrameBufferPointer[instCnt] = &gFirstPipelineFrameBuf[instCnt];
            gsecondPipeFrameBufferPointer[instCnt] = &gSecondPipelineFrameBuf[instCnt];
        }
    
        for(instCnt = 0U; instCnt< numPipes ; instCnt++)
        {
            if(instCnt == 0)
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gfirstPipeFrameBufferPointer);
            }
            else
            {
                Disp_prepareFrameBuffer(instCnt,
                                        gDssConfigPipelineParams.inDataFmt[instCnt],
                                        gDssConfigPipelineParams.inWidth[instCnt],
                                        gDssConfigPipelineParams.inHeight[instCnt],
                                        gDssConfigPipelineParams.pitch[instCnt][0],
                                        gsecondPipeFrameBufferPointer);
            }
        }
    }
    
    /*
     * DSS display test
     */
    void dss_safety_test_main(void *args)
    {
        int32_t retVal = SystemP_SUCCESS;
    
        /* Initialise frames */
        DispApp_initFrames();
    
        DispApp_init(&gDssObjects[CONFIG_DSS0]);
    
        DebugP_log("DSS display application started...\r\n");
    
        retVal = DispApp_runTest(&gDssObjects[CONFIG_DSS0]);
    
        DispApp_deInit(&gDssObjects[CONFIG_DSS0]);
    
        retVal = DispApp_logSafetyCheckData();
    
        if(SystemP_SUCCESS == retVal)
        {
            DebugP_log("DSS Safety Test Passed!!\r\n");
        }
        else
        {
            DebugP_log("DSS Safety Test Failed!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_init(Dss_Object *appObj)
    {
        int32_t         retVal = FVID2_SOK;
        Fvid2_InitPrms  initPrms;
    
        Fvid2InitPrms_init(&initPrms);
        retVal = Fvid2_init(&initPrms);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Fvid2 Init Failed!!!\r\n");
        }
    
        Dss_initParamsInit(&appObj->initParams);
    
        Dss_init(&appObj->initParams);
    
        if(FVID2_SOK == retVal)
        {
            /* Create DCTRL handle, used for common driver configuration */
            appObj->dctrlHandle = Fvid2_create(
                DSS_DCTRL_DRV_ID,
                DSS_DCTRL_INST_0,
                NULL,
                NULL,
                NULL);
            if(NULL == appObj->dctrlHandle)
            {
                DebugP_log("DCTRL Create Failed!!!\r\n");
            }
        }
    
        if(appObj->oldiParams != NULL)
        {
            Dss_setOLDITxPowerDown(appObj->oldiParams->oldiCfg.oldiMapType, TRUE);
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("DispApp_init() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_deInit(Dss_Object *appObj)
    {
        int32_t  retVal = FVID2_SOK;
    
        /* Delete DCTRL handle */
        retVal = Fvid2_delete(appObj->dctrlHandle, NULL);
        retVal += Dss_deInit();
        retVal += Fvid2_deInit(NULL);
        if(retVal != FVID2_SOK)
        {
             DebugP_log("DCTRL handle delete failed!!!\r\n");
        }
        else
        {
             DebugP_log("DispApp_deInit() - DONE !!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_runTest(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
        Fvid2_FrameList  frmList;
    
        /* Create driver */
        DispApp_create(appObj);
    
        DebugP_log("Starting display ... !!!\r\n");
        DebugP_log("Display in progress ... DO NOT HALT !!!\r\n");
    
        /* Start driver */
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
    
            retVal = Fvid2_start(instObj->drvHandle, NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Display Start Failed!!!\r\n");
                break;
            }
        }
    
        gStartProfileTime = (ClockP_getTimeUsec() / 1000U);
    
        while(gLoopCount++ < DISP_NUM_FRAMES_COUNT)
        {
    		//Add
            if(gLoopCount % 30 == 0)  // switch group every 10 frame  (20, 30)
            {
                //choose group 0 or 1
            //uint8_t newGroup = (gLoopCount / 10) % 2; 
                uint8_t newGroup = (gLoopCount / 10) % 2; 
                gcurrentGroup = newGroup;
                int32_t retVal = DispApp_switchSafetyParamsGroup(appObj, newGroup);
                if(retVal == FVID2_SOK) {
    
                    DebugP_log("Switch to group %d success!\r\n", newGroup);
                } else {
                    DebugP_log("Switch failed! Ret: %d\r\n", retVal);
                }
            }
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
                (void) SemaphoreP_pend(&instObj->syncSem, SystemP_WAIT_FOREVER);
    
                
                retVal = Fvid2_dequeue(instObj->drvHandle,
                                       &frmList,
                                       0U,
                                       FVID2_TIMEOUT_NONE);
    
                /* Corrupt frame to introduce data integrity error */
                if(gLoopCount == DISP_FRAME_CORRUPT_NUM)
                {
                    for(uint32_t count = 0; count < gDssConfigPipelineParams.inHeight[instCnt] * \
                    gDssConfigPipelineParams.pitch[instCnt][0]; count++)
                    {
                        *(uint8_t *)(frmList.frames[0]->addr[0] + count) = 0xAA;
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
                    if(FVID2_SOK != retVal)
                    {
                        DebugP_log("Display Queue Failed!!!\r\n");
                        break;
                    }
                }
                else if (FVID2_EAGAIN == retVal)
                {
                    /* Do nothing as this is first callback */
                }
                else
                {
                    /* Error */
                    DebugP_log("Display Dequeue Failed!!!\r\n");
                    break;
                }
            }
        }
    
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
            retVal  = Fvid2_stop(instObj->drvHandle, NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("Display Stop Failed!!!\r\n");
                break;
            }
        }
    
        gStopProfileTime = (ClockP_getTimeUsec() / 1000U);
    
        if(FVID2_SOK == retVal)
        {
            /* Delete driver */
            DispApp_delete(appObj);
        }
    
        return (retVal != FVID2_SOK? SystemP_FAILURE:SystemP_SUCCESS);
    }
    
    static void DispApp_initDssParams(Dss_Object *appObj)
    {
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlAdvVpParams *advVpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
    
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        globalDssParams = &appObj->globalDssParams;
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
    
        Dss_dctrlVpParamsInit(vpParams);
        Dss_dctrlAdvVpParamsInit(advVpParams);
        Dss_dctrlOverlayParamsInit(overlayParams);
        Dss_dctrlOverlayLayerParamsInit(layerParams);
        Dss_dctrlGlobalDssParamsInit(globalDssParams);
    
        /* Configure VP params */
        vpParams->vpId = gDssVpParams.vpId;
        vpParams->lcdOpTimingCfg.mInfo.standard = gDssVpParams.lcdOpTimingCfg.mInfo.standard;
        vpParams->lcdOpTimingCfg.mInfo.width = gDssVpParams.lcdOpTimingCfg.mInfo.width;
        vpParams->lcdOpTimingCfg.mInfo.height = gDssVpParams.lcdOpTimingCfg.mInfo.height;
        vpParams->lcdOpTimingCfg.mInfo.hFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.hBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.hBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.hSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.hSyncLen;
        vpParams->lcdOpTimingCfg.mInfo.vFrontPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vFrontPorch;
        vpParams->lcdOpTimingCfg.mInfo.vBackPorch = gDssVpParams.lcdOpTimingCfg.mInfo.vBackPorch;
        vpParams->lcdOpTimingCfg.mInfo.vSyncLen = gDssVpParams.lcdOpTimingCfg.mInfo.vSyncLen;
    
        vpParams->lcdOpTimingCfg.dvoFormat = gDssVpParams.lcdOpTimingCfg.dvoFormat;
        vpParams->lcdOpTimingCfg.videoIfWidth = gDssVpParams.lcdOpTimingCfg.videoIfWidth;
    
        vpParams->lcdPolarityCfg.actVidPolarity =  gDssVpParams.lcdPolarityCfg.actVidPolarity;
        vpParams->lcdPolarityCfg.hsPolarity = gDssVpParams.lcdPolarityCfg.hsPolarity;
        vpParams->lcdPolarityCfg.vsPolarity = gDssVpParams.lcdPolarityCfg.vsPolarity;
        vpParams->lcdPolarityCfg.pixelClkPolarity = gDssVpParams.lcdPolarityCfg.pixelClkPolarity ;
    
        /* Configure VP Advance Params*/
        advVpParams->vpId = gDssAdvVpParams.vpId;
        advVpParams->lcdAdvSignalCfg.hVAlign = gDssAdvVpParams.lcdAdvSignalCfg.hVAlign;
        advVpParams->lcdAdvSignalCfg.hVClkControl = gDssAdvVpParams.lcdAdvSignalCfg.hVClkControl;
    
        /* Configure VP Safety Params */
        for(uint8_t count = 0; count < CSL_DSS_VP_SAFETY_REGION_MAX; count++)
        {
            Dss_dctrlVpSafetyChkParamsInit(vpSafetyParams + count);
        }
    /*
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            vpSafetyParams[count].vpId = gDssVpSafetyParams[count].vpId;
            vpSafetyParams[count].safetySignSeedVal = gDssVpSafetyParams[count].safetySignSeedVal;
            vpSafetyParams[count].regionSafetyChkCfg.regionId = gDssVpSafetyParams[count].regionSafetyChkCfg.regionId;
            vpSafetyParams[count].regionSafetyChkCfg.referenceSign = gDssVpSafetyParams[count].regionSafetyChkCfg.referenceSign;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
    
            vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback;
            vpSafetyParams[count].appData = &vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
        }
    */
        /* Configure Overlay Params */
        overlayParams->overlayId =  gDssOverlayParams.overlayId;
        overlayParams->colorbarEnable =  gDssOverlayParams.colorbarEnable;
        overlayParams->overlayCfg.colorKeyEnable =  gDssOverlayParams.overlayCfg.colorKeyEnable;
        overlayParams->overlayCfg.colorKeySel =  gDssOverlayParams.overlayCfg.colorKeySel;
        overlayParams->overlayCfg.backGroundColor =  gDssOverlayParams.overlayCfg.backGroundColor;
    
        /* Configure Overlay Layer params */
        layerParams->overlayId = gDssOverlayLayerParams.overlayId;
        memcpy((void*)layerParams->pipeLayerNum, (void* )gDssOverlayLayerParams.pipeLayerNum, \
        sizeof(gDssOverlayLayerParams.pipeLayerNum));
    
    }
    
    static void DispApp_create(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
        int32_t status = SystemP_SUCCESS;
        uint32_t instCnt = 0U;
        Dss_InstObject *instObj;
    
        /* Init VP, Overlay and Panel params */
        DispApp_initDssParams(appObj);
    
        /* Configure DSS pipeline params */
        DispApp_initPipelineParams(appObj);
    
        /* Config IOCTL for VP, Overlay and Panel */
        retVal = DispApp_configDctrl(appObj);
    
        if(retVal == FVID2_SOK)
        {
            for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
            {
                instObj = &appObj->instObj[instCnt];
    
                status = SemaphoreP_constructBinary(&instObj->syncSem, 0);
                if(status != SystemP_SUCCESS)
                {
                    retVal = FVID2_EFAIL;
                }
    
                instObj->drvHandle = Fvid2_create(
                    DSS_DISP_DRV_ID,
                    instObj->instId,
                    &instObj->createParams,
                    &instObj->createStatus,
                    &instObj->cbParams);
    
                if((NULL == instObj->drvHandle) ||
                (instObj->createStatus.retVal != FVID2_SOK))
                {
                    DebugP_log("Display Create Failed!!!\r\n");
                    retVal = instObj->createStatus.retVal;
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_DSS_PARAMS,
                        &instObj->dispParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Params IOCTL Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = Fvid2_control(
                        instObj->drvHandle,
                        IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS,
                        &instObj->mflagParams,
                        NULL);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("DSS Set Mflag Params IOCTL Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
                    {
                        retVal = Fvid2_control(
                            instObj->drvHandle,
                            IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS,
                            &instObj->safetyParams,
                            NULL);
                        if(retVal != FVID2_SOK)
                        {
                            DebugP_log("DSS Set Safety Params IOCTL Failed!!!\r\n");
                        }
                    }
                }
    
                if(FVID2_SOK == retVal)
                {
                    retVal = DispApp_allocAndQueueFrames(appObj, instObj);
                    if(retVal != FVID2_SOK)
                    {
                        DebugP_log("Display Alloc and Queue Failed!!!\r\n");
                    }
                }
    
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
        }
    
        if(FVID2_SOK == retVal)
        {
            DebugP_log("Display create complete!!\r\n");
        }
    
        return;
    }
    
    static void DispApp_delete(Dss_Object *appObj)
    {
        int32_t retVal;
        uint32_t instCnt;
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlVpErrorStats *pErrorStats;
        Dss_InstObject *instObj;
        Dss_DispCurrentStatus currStatus;
        Fvid2_FrameList frmList;
    
        vpParams = &appObj->vpParams;
        pErrorStats = &appObj->errorStats;
    
        for(instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            instObj = &appObj->instObj[instCnt];
    
            /* Check for DSS underflow errors */
            retVal = Fvid2_control(
                instObj->drvHandle,
                IOCTL_DSS_DISP_GET_CURRENT_STATUS,
                &currStatus,
                NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Failed to get Display Stats!!!\r\n");
            }
    
            /* Print Synclost errors */
            if(0U != currStatus.underflowCount)
            {
                GT_2trace(DssTrace, GT_ERR, "No of Underflows for Inst %d: %d\r\n", instCnt, currStatus.underflowCount);
            }
            else
            {
                DebugP_log("Underflow did not occur\r\n");
            }
    
            /* Dequeue all the request from the driver */
            while (1U)
            {
                retVal = Fvid2_dequeue(
                    instObj->drvHandle,
                    &frmList,
                    0U,
                    FVID2_TIMEOUT_NONE);
                if(FVID2_SOK != retVal)
                {
                    break;
                }
            }
    
            retVal = Fvid2_delete(instObj->drvHandle, NULL);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Delete Failed!!!\r\n");
                break;
            }
        }
    
        /* Check for DSS synclost errors */
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_GET_VP_ERROR_STATS,
            pErrorStats,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Failed to get VP Stats!!!\r\n");
        }
    
        /* Print Synclost errors */
        if(0U != pErrorStats->syncLost)
        {
            GT_1trace(DssTrace, GT_ERR, "No of Sync Lost: %d\r\n", pErrorStats->syncLost);
        }
        else
        {
            DebugP_log("Sync Lost did not occur\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_CLEAR_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(FVID2_SOK != retVal)
        {
            DebugP_log("Clear Path Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_STOP_VP,
            vpParams,
            NULL);
    
        if(FVID2_SOK != retVal)
        {
            DebugP_log("VP Stop Failed!!!\r\n");
        }
    
        if(FVID2_SOK == retVal)
        {
             DebugP_log("Display delete complete!!\r\n");
        }
    
        return;
    }
    
    static int32_t DispApp_allocAndQueueFrames(const Dss_Object *appObj,
                                               Dss_InstObject *instObj)
    {
        int32_t  retVal = FVID2_SOK;
        uint32_t frmId, numFrames;
        Fvid2_Frame *frm;
        Fvid2_FrameList frmList;
    
        Fvid2FrameList_init(&frmList);
        frm = instObj->frames;
        numFrames = instObj->numFrames;
        /* init memory pointer for 'numFrames'  */
        for(frmId=0U; frmId<numFrames; frmId++)
        {
            /* init Fvid2_Frame to 0's  */
            Fvid2Frame_init((Fvid2_Frame *)(frm + frmId));
            if(instObj->instId == gDssConfigPipelineParams.instId[0U])
            {
                frm[frmId].addr[0U] = (uint64_t)gfirstPipeFrameBufferPointer[frmId];
            }
            else
            {
                frm[frmId].addr[0U] = (uint64_t)gsecondPipeFrameBufferPointer[frmId];
            }
    
            frm[frmId].fid = FVID2_FID_FRAME;
            frm[frmId].appData = instObj;
    
            /* Set number of frame in frame list - one at a time */
            frmList.numFrames  = 1U;
            frmList.frames[0U] = &frm[frmId];
    
            /*
             * queue the frames in frmList
             * All allocate frames are queued here as an example.
             * In general atleast 2 frames per channel need to queued
             * before starting display,
             * else frame will get dropped until frames are queued
             */
            retVal = Fvid2_queue(instObj->drvHandle, &frmList, 0U);
            if(FVID2_SOK != retVal)
            {
                DebugP_log("Display Queue Failed!!!\r\n");
                break;
            }
        }
    
        return (retVal);
    }
    
    static void DispApp_initPipelineParams(Dss_Object *appObj)
    {
        uint32_t instCnt = 0U, numPipes = 0U;
        Dss_DispParams *dispParams;
        Dss_InstObject *instObj;
    
        numPipes = gDssConfigPipelineParams.numTestPipes;
    
        for(instCnt=0U; instCnt<numPipes; instCnt++)
        {
            /* Initialize video pipes */
            instObj = &appObj->instObj[instCnt];
            instObj->instId = gDssConfigPipelineParams.instId[instCnt];
    
            Dss_dispCreateParamsInit(&instObj->createParams);
            Fvid2CbParams_init(&instObj->cbParams);
    
            instObj->cbParams.cbFxn = &DispApp_pipeCbFxn;
            instObj->cbParams.appData = instObj;
    
            dispParams = &instObj->dispParams;
            Dss_dispParamsInit(dispParams);
    
            dispParams->pipeCfg.pipeType = gDssConfigPipelineParams.pipeType[instCnt];
            dispParams->pipeCfg.inFmt.width = gDssConfigPipelineParams.inWidth[instCnt];
            dispParams->pipeCfg.inFmt.height = gDssConfigPipelineParams.inHeight[instCnt];
    
            for(uint32_t count = 0U; count < FVID2_MAX_PLANES; count++)
            {
                dispParams->pipeCfg.inFmt.pitch[count] =
                                            gDssConfigPipelineParams.pitch[instCnt][count];
            }
    
            dispParams->pipeCfg.inFmt.dataFormat =
                                            gDssConfigPipelineParams.inDataFmt[instCnt];
            dispParams->pipeCfg.inFmt.scanFormat =
                                            gDssConfigPipelineParams.inScanFmt[instCnt];
            dispParams->pipeCfg.outWidth = gDssConfigPipelineParams.outWidth[instCnt];
            dispParams->pipeCfg.outHeight = gDssConfigPipelineParams.outHeight[instCnt];
            dispParams->pipeCfg.scEnable = gDssConfigPipelineParams.scEnable[instCnt];
    
            dispParams->alphaCfg.globalAlpha =
                                    gDssConfigPipelineParams.globalAlpha[instCnt];
            dispParams->alphaCfg.preMultiplyAlpha =
                                    gDssConfigPipelineParams.preMultiplyAlpha[instCnt];
            dispParams->layerPos.startX = gDssConfigPipelineParams.posx[instCnt];
            dispParams->layerPos.startY = gDssConfigPipelineParams.posy[instCnt];
    
            Dss_dispPipeMflagParamsInit(&instObj->mflagParams);
    
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                Dss_dispPipeSafetyChkParamsInit(&instObj->safetyParams);
    
                instObj->safetyParams.safetySignSeedVal = gDssPipelineSafetyParams[instCnt].safetySignSeedVal;
                instObj->safetyParams.referenceSign = gDssPipelineSafetyParams[instCnt].referenceSign;
                instObj->safetyParams.safetyChkCfg.safetyChkEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkEnable;
                instObj->safetyParams.safetyChkCfg.safetyChkMode = gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
                instObj->safetyParams.safetyChkCfg.seedSelectEnable = gDssPipelineSafetyParams[instCnt].safetyChkCfg.seedSelectEnable;
                instObj->safetyParams.safetyChkCfg.thresholdValue = gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue;
                instObj->safetyParams.safetyChkCfg.frameSkip = gDssPipelineSafetyParams[instCnt].safetyChkCfg.frameSkip;
                instObj->safetyParams.safetyChkCfg.regionPos.startX = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startX;
                instObj->safetyParams.safetyChkCfg.regionPos.startY = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionPos.startY;
                instObj->safetyParams.safetyChkCfg.regionSize.width = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.width;
                instObj->safetyParams.safetyChkCfg.regionSize.height = gDssPipelineSafetyParams[instCnt].safetyChkCfg.regionSize.height;
    
                instObj->safetyParams.safetyErrCbFxn = DispApp_pipelineSafetyErrCallback;
                instObj->safetyParams.appData = &gDssPipelineSafetyParams[instCnt].safetyChkCfg.safetyChkMode;
            }
        }
    }
    
    static int32_t DispApp_configDctrl(Dss_Object *appObj)
    {
        int32_t retVal = FVID2_SOK;
    
        Dss_DctrlVpParams *vpParams;
        Dss_DctrlOverlayParams *overlayParams;
        Dss_DctrlOverlayLayerParams *layerParams;
        Dss_DctrlAdvVpParams *advVpParams;
        //Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        Dss_DctrlGlobalDssParams *globalDssParams;
        Dss_DctrlOldiParams *oldiParams;
    
        oldiParams = appObj->oldiParams;
        vpParams = &appObj->vpParams;
        overlayParams = &appObj->overlayParams;
        layerParams = &appObj->layerParams;
        advVpParams = &appObj->advVpParams;
        //vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        globalDssParams= &appObj->globalDssParams;
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_PATH,
            appObj->dctrlPathInfo,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set Path IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_ADV_VP_PARAMS,
            advVpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Advance VP Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_PARAMS,
            vpParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("Dctrl Set VP Params IOCTL Failed!!!\r\n");
        }
    
        if (appObj->oldiParams != NULL)
        {
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_OLDI_PARAMS,
                oldiParams,
                NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set OLDI Params IOCTL Failed!!!\r\n");
            }
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS,
            overlayParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Overlay Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_LAYER_PARAMS,
            layerParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Layer Params IOCTL Failed!!!\r\n");
        }
    
        retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS,
            globalDssParams,
            NULL);
        if(retVal != FVID2_SOK)
        {
            DebugP_log("DCTRL Set Global DSS Params IOCTL Failed!!!\r\n");
        }
    /*
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            retVal = Fvid2_control(
            appObj->dctrlHandle,
            IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
            vpSafetyParams + count,
            NULL);
            if(retVal != FVID2_SOK)
            {
                DebugP_log("DCTRL Set Safety Params IOCTL Failed!!!\r\n");
                break;
            }
        }
    */
        return (retVal);
    }
    
    static int32_t DispApp_pipeCbFxn(Fvid2_Handle handle, void *appData)
    {
        int32_t retVal  = FVID2_SOK;
        Dss_InstObject *instObj = (Dss_InstObject *) appData;
    
        GT_assert (DssTrace, (NULL != instObj));
        (void) SemaphoreP_post(&instObj->syncSem);
    
        return (retVal);
    }
    
    static void DispApp_vpSafetyErrCallback(uint32_t vpID,
                                            Dss_DctrlVpSafetyCbData safetyCbData,
                                            void *appData)
    {
        if (gcurrentGroup == 0)
        {
            if(gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyInterupt = true;
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].vpId = vpID;
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].frameCount = gLoopCount;
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
                gSafetyCallbackDataVP_G1[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
            }
        }
        else if (gcurrentGroup == 1)
        {
            if(gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyInterupt = true;
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].vpId = vpID;
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].frameCount = gLoopCount;
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].cbData.capturedSign = safetyCbData.capturedSign;
                gSafetyCallbackDataVP_G2[safetyCbData.regionId].cbData.regionId = safetyCbData.regionId;
            }
        }
    }
    
    static void DispApp_pipelineSafetyErrCallback(uint32_t pipeId,
                                                  uint32_t capturedSign,
                                                  void *appData)
    {
        if(Dss_dispIsVidInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVID.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVID.safetyInterupt = true;
                gSafetyCallbackDataVID.pipeId = pipeId;
                gSafetyCallbackDataVID.frameCount = gLoopCount;
                gSafetyCallbackDataVID.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVID.cbData.capturedSign = capturedSign;
            }
        }
        else if(Dss_dispIsVidLInst(pipeId) == TRUE)
        {
            if(gSafetyCallbackDataVIDL.safetyInterupt != true && gLoopCount < DISP_NUM_FRAMES_COUNT)
            {
                gSafetyCallbackDataVIDL.safetyInterupt = true;
                gSafetyCallbackDataVIDL.pipeId = pipeId;
                gSafetyCallbackDataVIDL.frameCount = gLoopCount;
                gSafetyCallbackDataVIDL.safetyCheckMode = *(uint32_t *)appData;
                gSafetyCallbackDataVIDL.cbData.capturedSign = capturedSign;
            }
        }
    
    }
    
    static int32_t DispApp_logSafetyCheckData()
    {
        int32_t status = SystemP_SUCCESS;
        uint32_t count;
    
        for(count = 0U; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            DebugP_log("****************************************************\r\n");
    
            DebugP_log("Safety Data Log Region : %d\r\n", gSafetyCallbackDataVP_G1[count].cbData.regionId);
            DebugP_log("Safety Data VP ID: %s\r\n",gSafetyCallbackDataVP_G1[count].vpId == CSL_DSS_VP_ID_1 ? "VP1" : "Invalid VP");
    		if (gcurrentGroup == 0)
            {
                if(gSafetyCallbackDataVP_G1[count].safetyInterupt == true)
                {
                    DebugP_log("1 Safety Check Interupt Trigger: TRUE\r\n");
    
                    if(gSafetyCallbackDataVP_G1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                    {
                        DebugP_log("1 Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                        if(gSafetyCallbackDataVP_G1[count].frameCount < gDssVpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                        {
                            status = SystemP_FAILURE;
                        }
                    }
                    else if(gSafetyCallbackDataVP_G1[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                    {
                        DebugP_log("1 Safety Check Mode: DATA_INTEGRITY\r\n");
                    }
    
                    DebugP_log("1 Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP_G1[count].frameCount);
                    DebugP_log("1 Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP_G1[count].cbData.capturedSign);
                }
                else
                {
                    status = SystemP_FAILURE;
                    DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                }
            }
    		//组2
            else if (gcurrentGroup == 1)
            {
                if(gSafetyCallbackDataVP_G2[count].safetyInterupt == true)
                {
                    DebugP_log("2 Safety Check Interupt Trigger: TRUE\r\n");
    
                    if(gSafetyCallbackDataVP_G2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                    {
                        DebugP_log("2 Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                        if(gSafetyCallbackDataVP_G2[count].frameCount < gDssVpSafetyParams_Group2[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue)
                        {
                            status = SystemP_FAILURE;
                        }
                    }
                    else if(gSafetyCallbackDataVP_G2[count].safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                    {
                        DebugP_log("2 Safety Check Mode: DATA_INTEGRITY\r\n");
                    }
    
                    DebugP_log("2 Safety Data Frame count: %d\r\n", gSafetyCallbackDataVP_G2[count].frameCount);
                    DebugP_log("2 Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVP_G2[count].cbData.capturedSign);
                }
                else
                {
                    status = SystemP_FAILURE;
                    DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                }
            }
    
        }
    
        for(uint32_t instCnt=0U; instCnt<gDssConfigPipelineParams.numTestPipes; instCnt++)
        {
            if(gDssConfigPipelineParams.safetyCheck[instCnt] == TRUE)
            {
                if(Dss_dispIsVidInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VID1\r\n");
    
                    if(gSafetyCallbackDataVID.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVID.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVID.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVID.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVID.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
                else if(Dss_dispIsVidLInst(gDssConfigPipelineParams.pipeId[instCnt]) == TRUE)
                {
                    DebugP_log("****************************************************\r\n");
    
                    DebugP_log("Safety Data Pipeline ID: VIDL1\r\n");
    
                    if(gSafetyCallbackDataVIDL.safetyInterupt == true)
                    {
                        DebugP_log("Safety Check Interupt Trigger: TRUE\r\n");
    
                        if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_FRAME_FREEZE_DETECT)
                        {
                            DebugP_log("Safety Check Mode: FRAME_FREEZE_DETECT\r\n");
    
                            if(gSafetyCallbackDataVIDL.frameCount < gDssPipelineSafetyParams[instCnt].safetyChkCfg.thresholdValue)
                            {
                                status = SystemP_FAILURE;
                            }
                        }
                        else if(gSafetyCallbackDataVIDL.safetyCheckMode == CSL_DSS_SAFETY_CHK_DATA_INTEGRITY)
                        {
                            DebugP_log("Safety Check Mode: DATA_INTEGRITY\r\n");
                        }
    
                        DebugP_log("Safety Data Frame count: %d\r\n", gSafetyCallbackDataVIDL.frameCount);
                        DebugP_log("Safety Data Captured Signature: 0x%lX\r\n", gSafetyCallbackDataVIDL.cbData.capturedSign);
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                        DebugP_log("Safety Check Interupt Trigger: FALSE\r\n");
                    }
    
                }
            }
        }
    
        return status;
    }
    
    
    //Add
    /* Safety parameter group switching function 
    *
    * @param appObj DSS object pointer
    * @param groupIdx Safety parameter group index (0 or 1 or more)
    
    */
    static int32_t DispApp_switchSafetyParamsGroup(Dss_Object *appObj, uint8_t groupIdx)
    {
        int32_t retVal = FVID2_SOK;
        Dss_DctrlVpSafetyChkParams *vpSafetyParams;
        
        vpSafetyParams = (Dss_DctrlVpSafetyChkParams*)&appObj->vpSafetyParams;
        
        /* choose group */
        Dss_DctrlVpSafetyChkParams *newGroup = NULL;
        if(groupIdx == 0) {///gruop 0
            newGroup = gDssVpSafetyParams;
        } else if(groupIdx == 1) {///gruop 1
            newGroup = gDssVpSafetyParams_Group2;
        } 
    
        for(uint8_t count = 0; count < CONFIG_DSS_NUM_SAFETY_REGIONS; count++)
        {
            vpSafetyParams[count].vpId = newGroup[count].vpId;
            vpSafetyParams[count].safetySignSeedVal = newGroup[count].safetySignSeedVal;
            vpSafetyParams[count].regionSafetyChkCfg.regionId = newGroup[count].regionSafetyChkCfg.regionId;
            vpSafetyParams[count].regionSafetyChkCfg.referenceSign = newGroup[count].regionSafetyChkCfg.referenceSign;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable = newGroup[count].regionSafetyChkCfg.safetyChkCfg.safetyChkEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode = newGroup[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable = newGroup[count].regionSafetyChkCfg.safetyChkCfg.seedSelectEnable;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue = newGroup[count].regionSafetyChkCfg.safetyChkCfg.thresholdValue;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.frameSkip = newGroup[count].regionSafetyChkCfg.safetyChkCfg.frameSkip;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startX;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionPos.startY;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionSize.width;
            vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height = newGroup[count].regionSafetyChkCfg.safetyChkCfg.regionSize.height;
            
            vpSafetyParams[count].safetyErrCbFxn = DispApp_vpSafetyErrCallback;
            vpSafetyParams[count].appData = &vpSafetyParams[count].regionSafetyChkCfg.safetyChkCfg.safetyChkMode;
            
    
            retVal = Fvid2_control(
                appObj->dctrlHandle,
                IOCTL_DSS_DCTRL_SET_VP_SAFETY_CHK_PARAMS,
                vpSafetyParams + count,
                NULL);
            
            if(retVal != FVID2_SOK) {
                DebugP_log("Safety params switch failed for region %d!!!\r\n", count);
                return retVal;
            }
        }
        
        DebugP_log("Safety parameters switched to Group %d successfully\r\n", groupIdx);
        return FVID2_SOK;
    }

    The code is modified based on dss_safety_test.c.

    During testing, we found that when switching every 30 frames, the screen doesn't freeze but error messages appear. And if the total number of display frames is increased. The the screen and log all freeze.

    When switching every 10 frames or less, the system freezes, and the screen becomes unresponsive as well. Two log snippets are shown in the figure below. Could you please help check where the issue might be?

      

  • Hi weizhuang:

    Can you introduce you build up method? we try to reproduce your failure at EVM board.

    Use you provide latest code replace /mcu_plus_sdk_am62px_11_01_01_08/examples/drivers/dss/dss_safety_test/dss_safety_test.c and compile it run at EVM board. my side those test case can not run. below are my side use command/log and modified configure file.

    Best Regards!

    Han Tao

    python uart_uniflash.py -p /dev/ttyUSB0 --cfg=sbl_prebuilt/am62px-sk/default_sbl_ospi_linux_hs_fs.cfg

    2318.default_sbl_ospi_linux_hs_fs.cfg

    �Sciserver Testapp Built On: Dec 26 2025 11:37:29
    Sciserver Version: v2025.10.0.0-REL.MCUSDK.K3.11.01.01.08+
    RM_PM_HAL Version: v11.01.02
    Starting Sciserver..... PASSED
    WARNING: Bootloader_rprcImageLoad:240: Software version mismatch, Installer version 0xb0101001
    DispApp_init() - DONE !!!
    DSS display application started...
    Display create complete!!
    Starting display ... !!!
    Display in progress ... DO NOT HALT !!!
    Safety parameters switched to Group 1 successfully
    Switch to group 1 success!
    ASSERT: 1.97409s: FreeRTOS-Kernel/tasks.c:xTaskPriorityDisinherit:6696: (uint32_t)(pxTCB == p!

  • Hello,

    It's exactly as per the steps in the documentation.

    My default_sbl_ospi_linux_hs_fs.cfg. But when I use yours, the result is the same as before.

    #-----------------------------------------------------------------------------#
    #                                                                             #
    #      DEFAULT CONFIGURATION FILE TO BE USED WITH THE FLASHWRITER SCRIPT      #
    #                                                                             #
    #-----------------------------------------------------------------------------#
    #
    # By default this config file,
    # - points to pre-built flash writer, bootloader for this EVM
    # - The application image points to relative path of the ipc rpmsg linux application image for this EVM
    #   - Make sure this application is built before running this script
    # - You can customized this config file to point to your own bootloader and/or application images
    # - You can use --operation=flashverify if you just want to verify the flash contents and not flash the file.
    #
    
    # First point to sbl_uart_uniflash_stage1 binary, which initialises DDR and receives sbl_uart_uniflash_stage2 binary
    --flash-writer=sbl_prebuilt/am62px-sk/sbl_uart_uniflash_stage1.release.hs_fs.tiimage
    
    # Points to sbl_uart_uniflash_stage2 binary, which function's as a server to flash one or more files
    # Please note this binary is copied to DDR by sbl_uart_uniflash_stage1 and not written to any boot media like flash or eMMC
    
    --file=../../examples/drivers/boot/sbl_uart_uniflash_multistage/sbl_uart_uniflash_stage2/am62px-sk/wkup-r5fss0-0_nortos/ti-arm-clang/sbl_uart_uniflash_stage2.release.appimage.hs_fs --operation=flash --flash-offset=0x0
    
    # Program the OSPI PHY tuning attack vector
    --operation=flash-phy-tuning-data
    
    # Now send one or more files to flash or flashverify as needed. The order of sending files does not matter
    
    # When sending bootloader make sure to flash at offset 0x0. ROM expects bootloader at offset 0x0
    --file=sbl_prebuilt/am62px-sk/sbl_ospi_linux_stage1.release.hs_fs.tiimage --operation=flash --flash-offset=0x0
    
    # 2nd stage bootloader with DM is flashed at 0x80000 or to whatever offset your bootloader is configured for
    #--file=../../examples/drivers/dss/dss_safety_test/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/dss_safety_test.release.appimage.hs_fs --operation=flash --flash-offset=0x80000
    --file=../../examples/drivers/dss/dss_safety/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/dss_safety.release.appimage.hs_fs --operation=flash --flash-offset=0x80000
    
    
    #--file=../../examples/drivers/dss/dss_safety/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/dss_safety.release.appimage.hs_fs --operation=flash --flash-offset=0x80000
    
    #--file=../../examples/drivers/dss/dss_display_share/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/dss_display_share.release.appimage.hs_fs --operation=flash --flash-offset=0x80000
    
    #--file=../../examples/drivers/dss/dss_colorbar_test/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/dss_colorbar_test.release.appimage.hs_fs --operation=flash --flash-offset=0x80000
    
    # When sending application image, make sure to flash at offset 0x100000 (default) or to whatever offset your bootloader is configured for
    #--file=../../examples/drivers/ipc/ipc_rpmsg_echo_linux/am62px-sk/mcu-r5fss0-0_freertos/ti-arm-clang/ipc_rpmsg_echo_linux.release.appimage.hs_fs --operation=flash --flash-offset=0x800000
    #--file=../../examples/drivers/ipc/ipc_rpmsg_echo_linux/am62px-sk/wkup-r5fss0-0_freertos/ti-arm-clang/ipc_rpmsg_echo_linux.release.appimage.hs_fs --operation=flash --flash-offset=0x800000
    
    # HSM image is flashed at 0x800000 or to whatever offset your bootloader is configured for
    --file=HSMAppimageGen/board/am62px-sk/hsm.appimage.hs_fs --operation=flash --flash-offset=0x240000
    
    # Linux image is flashed at 0xC00000 or to whatever offset your bootloader is configured for
    --file=linuxAppimageGen/board/am62px-sk/linux.appimage.hs_fs --operation=flash --flash-offset=0x1200000
    
    # u-boot.img is flashed at 0x280000
    --file=linuxAppimageGen/board/am62px-sk/u-boot.img --operation=flash --flash-offset=0x280000
    

    BR!