软件lvds输出无法进入到完成中断

Other Parts Discussed in Thread: IWR1843

目前我们准备在dss端通过Lvds输出ADC数据,发现配置lvds后,可以进入到MmwDemo_LVDSS_SendData,无法进入到frameDoneCallbackFxn这个回调函数?

附件是我们的lvds的代码,帮忙查看一下哪个配置有问题???

/**
 *   @file  dss_lvds_stream.c
 *
 *   @brief
 *      Implements LVDS stream functionality.
 *
 *  \par
 *  NOTE:
 *      (C) Copyright 2016 Texas Instruments, Inc.
 *
 *  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.
 */

/**************************************************************************
 *************************** Include Files ********************************
 **************************************************************************/
#include <stdint.h>
#include <string.h>
#include <stdio.h>

/* BIOS/XDC Include Files. */
#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/IHeap.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Memory.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/heaps/HeapBuf.h>
#include <ti/sysbios/heaps/HeapMem.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/family/c64p/Cache.h>
#include <ti/sysbios/family/c64p/Hwi.h>
#include <ti/sysbios/family/c64p/EventCombiner.h>
#include <ti/sysbios/utils/Load.h>

/* MMWSDK Include Files. */
#include <ti/drivers/soc/soc.h>
#include <ti/common/sys_common.h>
#include <ti/drivers/osal/DebugP.h>
#include <ti/drivers/osal/MemoryP.h>
#include <ti/drivers/adcbuf/ADCBuf.h>
#include <ti/drivers/edma/edma.h>
#include <ti/drivers/cbuff/cbuff.h>
#include <ti/utils/hsiheader/hsiheader.h>

/* MMWAVE Demo Include Files */
#include <Hardware/dss_lvds_stream.h>
#include <mmw_res.h>
#include <mmw_dss.h>

#define REAL_DATA (1)

extern MmwDemo_DSS_MCB    gMmwDssMCB;

#pragma DATA_ALIGN(gUserBuffHead, 64);

uint32_t g_transfer_complete = 0;

//֡ͷ
uint16_t gUserBuffHead[66] =
{
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,0x00FFU,
     0x0000,0x0000
};

//֡β
uint16_t gUserBufferEnd[16] =
{
    0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,
    0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U,0x7788U
};
#if !(REAL_DATA)
uint16_t gSwUserBuffer[2048];
#endif

 /**
 *  @b Description
 *  @n
 *      This function initializes/configures the LVDS
 *      streaming EDMA resources.
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */

void MmwDemo_LVDSStream_EDMAInit (void)
{
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelAllocatorIndex = 0;

    /* Populate the LVDS Stream SW Session EDMA Channel Table: */
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[0].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_0;
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[0].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_0;
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[1].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_1;
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[1].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_1;
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[2].chainChannelsId       = MMW_LVDS_STREAM_SW_SESSION_EDMA_CH_2;
    gMmwDssMCB.lvdsStream.swSessionEDMAChannelTable[2].shadowLinkChannelsId  = MMW_LVDS_STREAM_SW_SESSION_EDMA_SHADOW_CH_2;
}

 /**
 *  @b Description
 *  @n
 *      This is the LVDS streaming init function.
 *      It initializes the necessary modules
 *      that implement the streaming.
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
int32_t MmwDemo_LVDSStreamInit (void)
{
    CBUFF_InitCfg           initCfg;
    int32_t                 retVal = MINUS_ONE;
    int32_t                 errCode;

    /*************************************************************************************
     * Open the CBUFF Driver:
     *************************************************************************************/
    memset ((void *)&initCfg, 0, sizeof(CBUFF_InitCfg));

    /* Populate the configuration: */
    initCfg.socHandle                 = gMmwDssMCB.socHandle;
    initCfg.enableECC                 = 0U;
    initCfg.crcEnable                 = 1U;
    /* Up to 1 SW session + 1 HW session can be configured for each subframe. Therefore max session is 2. */
    initCfg.maxSessions               = 2U;
    initCfg.enableDebugMode           = false;
    initCfg.interface                 = CBUFF_Interface_LVDS;
    initCfg.outputDataFmt             = CBUFF_OutputDataFmt_16bit;
    initCfg.u.lvdsCfg.crcEnable       = 0U;
    initCfg.u.lvdsCfg.msbFirst        = 1U;
    /* Enable all lanes available on the platform*/
    initCfg.u.lvdsCfg.lvdsLaneEnable  = 0x3U;
    initCfg.u.lvdsCfg.ddrClockMode    = 1U;
    initCfg.u.lvdsCfg.ddrClockModeMux = 1U;

    /* Initialize the CBUFF Driver: */
    gMmwDssMCB.lvdsStream.cbuffHandle = CBUFF_init (&initCfg, &errCode);
    if (gMmwDssMCB.lvdsStream.cbuffHandle == NULL)
    {
        /* Error: Unable to initialize the CBUFF Driver */
//        System_printf("Error: CBUFF_init failed with [Error=%d]\n", errCode);
        goto exit;
    }

    /* Initialize the HSI Header Module: */
    if (HSIHeader_init (&initCfg, &errCode) < 0)
    {
        /* Error: Unable to initialize the HSI Header Module */
        System_printf("Error: HSIHeader_init failed with [Error=%d]\n", errCode);
        goto exit;
    }

    /* Populate EDMA resources */
    MmwDemo_LVDSStream_EDMAInit();

    retVal = 0;

exit:
    return retVal;
}

int32_t MmwDemo_LVDSS_SendData(uint16_t flame_num, uint16_t chirp_num)
{
    int32_t errCode;
    MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwDssMCB.lvdsStream;
    //MmwDemo_DataPathObj *dataPathObj = &gMmwMCB.dataPathObj;
    if((uint16_t)flame_num == 0x00FF)
           flame_num++;
    gUserBuffHead[sizeof(gUserBuffHead) / 2 - 2] = flame_num;
    gUserBuffHead[sizeof(gUserBuffHead) / 2 - 1] = chirp_num;

    CBUFF_deactivateSession (streamMcb->swSessionHandle, &errCode);

   // Activate the hardware session
    CBUFF_activateSession (streamMcb->swSessionHandle, &errCode);

   return errCode;
}

/**
 *  @b Description
 *  @n
 *      Function that allocates CBUFF-EDMA channel
 *
 *  @param[in]  ptrEDMAInfo
 *      Pointer to the EDMA Information
 *  @param[out]  ptrEDMACfg
 *      Populated EDMA channel configuration
 *
 */
static void MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel
(
    CBUFF_EDMAInfo*         ptrEDMAInfo,
    CBUFF_EDMAChannelCfg*   ptrEDMACfg
)
{
    if(ptrEDMAInfo->dmaNum == 0)
    {
        ptrEDMACfg->chainChannelsId      = MMW_LVDS_STREAM_CBUFF_EDMA_CH_0;
        ptrEDMACfg->shadowLinkChannelsId = MMW_LVDS_STREAM_CBUFF_EDMA_SHADOW_CH_0;
    }
    else if(ptrEDMAInfo->dmaNum == 1)
    {
        ptrEDMACfg->chainChannelsId      = MMW_LVDS_STREAM_CBUFF_EDMA_CH_1;
        ptrEDMACfg->shadowLinkChannelsId = MMW_LVDS_STREAM_CBUFF_EDMA_SHADOW_CH_1;
    }
    else
    {
        /* Max of 2 CBUFF sessions can be configured*/
        //MmwDemo_dssAssert (0);
    }
}

/**
 *  @b Description
 *  @n
 *      This is the registered CBUFF EDMA channel allocation function
 *      which allocates EDMA channels for CBUFF SW Session
 *
 *  @param[in]  ptrEDMAInfo
 *      Pointer to the EDMA Information
 *  @param[out]  ptrEDMACfg
 *      Populated EDMA channel configuration
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t MmwDemo_LVDSStream_EDMAAllocateCBUFFSwChannel
(
    CBUFF_EDMAInfo*         ptrEDMAInfo,
    CBUFF_EDMAChannelCfg*   ptrEDMACfg
)
{
    int32_t         retVal = MINUS_ONE;
    MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwDssMCB.lvdsStream;

    if(ptrEDMAInfo->isFirstEDMAChannel)
    {
        MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel(ptrEDMAInfo, ptrEDMACfg);
        retVal = 0;
    }
    else
    {
        /* Sanity Check: Are there sufficient EDMA channels? */
        if (streamMCBPtr->swSessionEDMAChannelAllocatorIndex >= MMWDEMO_LVDS_STREAM_SW_SESSION_MAX_EDMA_CHANNEL)
        {
            /* Error: All the EDMA channels are allocated */
//            System_printf ("Error: MmwDemo_LVDSStream_EDMAAllocateCBUFFChannel failed. SW channel index=%d\n",
//                            streamMCBPtr->swSessionEDMAChannelAllocatorIndex);
            goto exit;
        }

        /* Copy over the allocated EDMA configuration. */
        memcpy ((void *)ptrEDMACfg,
                (void*)&streamMCBPtr->swSessionEDMAChannelTable[streamMCBPtr->swSessionEDMAChannelAllocatorIndex],
                sizeof(CBUFF_EDMAChannelCfg));

        /* Increment the allocator index: */
        streamMCBPtr->swSessionEDMAChannelAllocatorIndex++;

        /* EDMA Channel allocated successfully */
        retVal = 0;
    }

exit:
    return retVal;
}

/**
 *  @b Description
 *  @n
 *      This is the registered CBUFF EDMA channel free function which frees EDMA channels
 *      which had been allocated for use by a CBUFF SW Session
 *
 *  @retval
 *      Not applicable
 */
static void MmwDemo_LVDSStream_EDMAFreeCBUFFSwChannel (CBUFF_EDMAChannelCfg* ptrEDMACfg)
{
    uint8_t    index;
    MmwDemo_LVDSStream_MCB_t *streamMCBPtr =  &gMmwDssMCB.lvdsStream;

    if((ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_0) ||
       (ptrEDMACfg->chainChannelsId == MMW_LVDS_STREAM_CBUFF_EDMA_CH_1))
    {
        /*This is the CBUFF trigger channel. It is not part of the resource table so
          nothing needs to be done*/
        goto exit;
    }


    for (index = 0U; index < MMWDEMO_LVDS_STREAM_SW_SESSION_MAX_EDMA_CHANNEL; index++)
    {
        /* Do we have a match? */
        if (memcmp ((void*)ptrEDMACfg,
                    (void*)&streamMCBPtr->swSessionEDMAChannelTable[index],
                    sizeof(CBUFF_EDMAChannelCfg)) == 0)
        {
            /* Yes: Decrement the SW Session index */
            streamMCBPtr->swSessionEDMAChannelAllocatorIndex--;
            goto exit;
        }
    }

    /* Sanity Check: We should have had a match. An assertion is thrown to indicate that the EDMA channel
     * being cleaned up does not belong to the table*/
    //MmwDemo_dssAssert (0);

exit:
    return;
}


 static void MmwDemo_LVDSStream_SwTriggerFrameDone (CBUFF_SessionHandle sessionHandle)
 {	  
	 int32_t	 errCode;

	 g_transfer_complete++;
	
#if 0 
	 /* Increment stats*/
	 gMmwMssMCB.lvdsStream.swFrameDoneCount++;
	 
	 if(sessionHandle != NULL)
	 {
		 if(CBUFF_deactivateSession (sessionHandle, &errCode) < 0)
		 {
			 /* Error: Unable to deactivate the session. */
			 DebugP_assert(0);
			 return;
		 }
		 
		 /*If only one subframe has been configured (legacy frame) and
		   a HW session has been configured for that subframe, we need to
		   enable it here as for the legacy frame the HW is NOT reconfigured
		   every frame. 
		   If more than one subframe is configured, the HW
		   session is reconfigured and activated every subframe
		   in the application code, not here.*/
		 if((gMmwMssMCB.objDetCommonCfg.preStartCommonCfg.numSubFrames == 1) &&
			(gMmwMssMCB.lvdsStream.hwSessionHandle != NULL))
		 {		  
			 if(CBUFF_activateSession (gMmwMssMCB.lvdsStream.hwSessionHandle, &errCode) < 0)
			 {
				 DebugP_assert(0);
			 }
		 }		  
	 }
	 else
	 {
		 DebugP_assert(0);
	 }	  
	 
	 Semaphore_post(gMmwMssMCB.lvdsStream.swFrameDoneSemHandle);
#endif
 }


 /**
 *  @b Description
 *  @n
 *      This is the LVDS streaming config function.
 *      It configures the sessions for the LVDS streaming.
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
int32_t MmwDemo_LVDSStreamConfigure (ObjDetObj *datPathObj)
{
    CBUFF_SessionCfg          sessionCfg;
    MmwDemo_LVDSStream_MCB_t* streamMcb = &gMmwDssMCB.lvdsStream;
    int32_t                   errCode;
    int32_t                   retVal = MINUS_ONE;
    uint32_t                  adcBufAddress = SOC_XWR18XX_DSS_ADCBUF_BASE_ADDRESS;//SOC_XWR68XX_DSS_ADCBUF_BASE_ADDRESS;

    memset ((void*)&sessionCfg, 0, sizeof(CBUFF_SessionCfg));

    /* Populate the configuration: */
    sessionCfg.executionMode                     = CBUFF_SessionExecuteMode_SW;
    sessionCfg.edmaHandle                        =  gMmwDssMCB.dataPathObj.edmaHandle; //datPathObj->edmaHandle[EDMA_INSTANCE_1];//gMmwDssMCB.dataPathContext.edmaHandle[MMW_LVDS_STREAM_EDMA_INSTANCE];
    sessionCfg.allocateEDMAChannelFxn            = MmwDemo_LVDSStream_EDMAAllocateCBUFFSwChannel;
    sessionCfg.freeEDMAChannelFxn                = MmwDemo_LVDSStream_EDMAFreeCBUFFSwChannel;
    sessionCfg.frameDoneCallbackFxn              = MmwDemo_LVDSStream_SwTriggerFrameDone;
    sessionCfg.dataType                          = CBUFF_DataType_REAL;
    sessionCfg.u.swCfg.userBufferInfo[0].size    = sizeof(gUserBuffHead)/2;
    sessionCfg.u.swCfg.userBufferInfo[0].address = (uint32_t)&gUserBuffHead[0];
    sessionCfg.u.swCfg.userBufferInfo[1].size    = 128; //datPathObj->numAdcSamples * datPathObj->numPhyRxAntennas * 2 - 2;
#if (REAL_DATA)
    sessionCfg.u.swCfg.userBufferInfo[1].address = adcBufAddress+4;
#else
    sessionCfg.u.swCfg.userBufferInfo[1].address = (uint32_t)&gSwUserBuffer[0];
#endif
    sessionCfg.u.swCfg.userBufferInfo[2].size    = sizeof(gUserBufferEnd)/2;
    sessionCfg.u.swCfg.userBufferInfo[2].address = (uint32_t)&gUserBufferEnd[0];

    /* Create the SW Session. */
    streamMcb->swSessionHandle = CBUFF_createSession (gMmwDssMCB.lvdsStream.cbuffHandle, &sessionCfg, &errCode);

    if (streamMcb->swSessionHandle == NULL)
    {
        /* Error: Unable to create the CBUFF SW session */
//        System_printf("Error: MmwDemo_LVDSStream_config unable to create the CBUFF SW session with [Error=%d]\n", errCode);
        goto exit;
    }

#if !(REAL_DATA)
    uint16_t i;
    for( i = 0; i < (sizeof(gSwUserBuffer) / 2); i++)
    {
        gSwUserBuffer[i] = i;
    }
#endif
    /* Control comes here implies that the LVDS Stream has been configured successfully */
    retVal = 0;

exit:
    return retVal;
}