This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

A strange problem about EDMA3

Hi All, I use C6678 evm, I use the EDMA to move data from MSMC to DDR3. The DMA source address will change, but the destination  address is fixed. Every time, move a cif image data.  The first time, the data move to destinaton buffer correctly. but the others the data of destination buffer never change. following is my code, please tell the reason if you find the problem.

 

S32 EdmaInit()
{
 CSL_Edma3Context            context;
 CSL_Status                  status;
 CSL_Edma3Obj                edmaObj;
 CSL_Edma3ChannelAttr        chAttr;
 CSL_Edma3ChannelObj         chObj;
 U32 paramSetId = 0;
 U32 i = 0;

 /* Module initialization */
    if (CSL_edma3Init(&context) != CSL_SOK)  // do nothing
    {
        printf ("Error: EDMA module initialization failed\n");  
        return -1;
    }

 /* Module level open */
    hModule0 = CSL_edma3Open(&edmaObj,0,NULL,&status);
    if ((hModule0 == NULL) || (status != CSL_SOK))
    {
        printf ("Error: EDMA0 module open failed\n");
        return -1;
    }
#if 0  // if needed, can open the EDMA1/2 through open this macro
 /* Module level open */
    hModule1 = CSL_edma3Open(&edmaObj,0,NULL,&status);
    if ((hModule1 == NULL) || (status != CSL_SOK))
    {
        printf ("Error: EDMA0 module open failed\n");
        return -1;
    }
  /* Module level open */
    hModule2 = CSL_edma3Open(&edmaObj,0,NULL,&status);
    if ((hModule2 == NULL) || (status != CSL_SOK))
    {
        printf ("Error: EDMA0 module open failed\n");
        return -1;
    }
#endif
 // Clear All IPR/IPRH
 REG(0x02701070) = 0xffffffff;
 REG(0x02701074) = 0xffffffff;

 paramSetId = 0;
 
 for(i = 0; i < 16; i++)
 {
  /* Open QDMA Channel i */
     chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
     chAttr.chaNum    = 16 + i;
     hChannel0[i] = CSL_edma3ChannelOpen(&chObj, 0, &chAttr, &status);  
     if ((hChannel0[i] == NULL) || (status != CSL_SOK))
     {
         printf ("Error: EDMA channel open failed\n");   
         return -1;
     }

  /* Map the QDMA Channel to the ParamSet,Every Channel have 4 ParamSets*/
  CSL_edma3HwChannelSetupParam (hChannel0[i], paramSetId);
  

  /* Setup the trigger word for the QDMA Channel. CNT Word is the trigger word*/
  CSL_edma3HwChannelSetupTriggerWord(hChannel0[i], CSL_EDMA3_TRIGWORD_CCNT);

  /* Get Parameter Entry Handle */
  hParam0[i] = CSL_edma3GetParamHandle(hChannel0[i], paramSetId, &status);
  paramSetId += 4;
  
     /* Enable Channel */
     if (CSL_edma3HwChannelControl(hChannel0[i],CSL_EDMA3_CMD_CHANNEL_ENABLE, NULL) != CSL_SOK)
     {
          printf ("Error: EDMA channel enable command failed\n");
          return -1;
     }

  /* Mapping channel 0 to event queue 0 */
     if (CSL_edma3HwChannelSetupQue(hChannel0[i],CSL_EDMA3_QUE_0) != CSL_SOK)
     {
         printf("Error: EDMA channel setup queue is failed\n");
         return -1;
     }
  
 } 
    return 0;
}

S32 EdmaExit()
{
 U32 i = 0;

 for(i = 0; i < 16; i++)
 {
  /* Disable the channel */
     CSL_edma3HwChannelControl(hChannel0[i],CSL_EDMA3_CMD_CHANNEL_DISABLE, NULL);

  /* Close channel */
     if (CSL_edma3ChannelClose(hChannel0[i]) != CSL_SOK)
     {
         printf("Error: EDMA channel close failed\n");
         return -1;
     }
 }

 /* Close EDMA module */
    if (CSL_edma3Close(hModule0) != CSL_SOK)
    {
        printf("Error: EDMA module close failed\n");
        return -1;
    }

 
 return 0;
}


#define WIDTH 352
#define HEIGHT 288
#define PICSIZEY (WIDTH*HEIGHT)
#define PICNUM
// place the yuvDataBuf in MSMCSRAM and pTmpImg in the DDR3 in my *.cmd file
U8 yuvDataBuf[PICSIZEY*PICNUM];
U8 pTmpImg[PICSIZEY];
U8 *currY;
// Used for test
S32 EdmaTest()
{
 CSL_Edma3ParamSetup         myParamSetup;
 CSL_Edma3CmdIntr            regionIntr;
 U32 i = 0;
 U32 frmNum = 0;
 
 currY = yuvDataBuf;

 for(frmNum = 0; frmNum < PICNUM; frmNum++)
 {
  myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
                                              CSL_EDMA3_TCCH_DIS, \
                                              CSL_EDMA3_ITCINT_DIS, \
                                              CSL_EDMA3_TCINT_EN,\
                                              0,CSL_EDMA3_TCC_NORMAL,\
                                              CSL_EDMA3_FIFOWIDTH_NONE, \
                                              CSL_EDMA3_STATIC_EN, \
                                              CSL_EDMA3_SYNC_AB, \
                                              CSL_EDMA3_ADDRMODE_INCR, \
                                              CSL_EDMA3_ADDRMODE_INCR);
  myParamSetup.srcAddr    = (Uint32)currY;        
     myParamSetup.aCntbCnt   = CSL_EDMA3_CNT_MAKE(PICWIDTH,PICHEIGHT);      
     myParamSetup.dstAddr    = (Uint32)pTmpImg;       
     myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(PICWIDTH,PICWIDTH);    
     myParamSetup.linkBcntrld=  0;    
     myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0,0);
     myParamSetup.cCnt       = 1;

  if (CSL_edma3ParamSetup(hParam0[0], &myParamSetup) != CSL_SOK)
     {
          printf ("Error: EDMA param setup failed\n");
          return -1;
     }


  /* Poll IPR bit */
     regionIntr.region = CSL_EDMA3_REGION_GLOBAL;
     do {
         CSL_edma3GetHwStatus(hModule0,CSL_EDMA3_QUERY_INTRPEND,&regionIntr);
     } while (!(regionIntr.intr & 0x1));

  

     /* Clear pending interrupt */
     if (CSL_edma3HwControl(hModule0,CSL_EDMA3_CMD_INTRPEND_CLEAR, &regionIntr) != CSL_SOK)
     {
          printf ("Error: EDMA clear interrupt pend command failed\n");
          return -1;
     }
    
    // Check Data
     for(i = 0; i < 352*288; i++)
     {
      if(currY[i] != pTmpImg[i])
      {
       printf("frmNum:%d EDMA error:%d\n",i);
      }
     }
  currY += PICSIZEY;
 }
}


int main(void)
{
 EdmaInit();
 
 // readfile 10 CIF picture data to the yuvDataBuf buffer
 
 EdmaTest();
 
 
 return 0;
}

  • Eric,

    I've only took a glance at it, but it appears you're linking to PaRAM entry 0, if you don't have anything in there for a proper NULL transfer you'll set the Secondary Event Register which that PaRAM entry will not transfer again until this is cleared.  Instead you probably want to link it to 0xFFFF which is predefined NULL transfer (i.e. if you're not linking to something you need to set the Link to 0xFFFF.)  More details can be found in the EDMA UG http://www.ti.com/lit/ug/sprugs5/sprugs5.pdf

    Best Regards,

    Chad

  • Hi Chad,

    I've changed my configure value.  I use the same configure value as the 3.2 Subframe Extraction Example  list in the EDMA user guide document. But only the first time, the picture move correctly, the rest times didn't move even one byte.

     

     

    Eric

     

     

  • I place the destination buffer into the L2, then can move correctly, if place in the DDR3, can't move correctly.

  • Can you update us. If destination in L2 (instead of DDR), can you move data from source (MSMC) everytime ? 

    For successful as well as unsuccessful transfer, can you please share the value of the ParamSet. You can put the address of the ParamSet in the Memory Browser of CCS and set the display type to 'Hex 32 bit'

    Also is the respective SER(secondary event register) set.

    Thanks

    Varada

  • I have list the code before, and didn't change anything except the cfg file, Program.sectMap["src_data_sect"] = "DDR3"->Program.sectMap["src_data_sect"] = "L2SRAM".

     After change the placement of the src_data_sect, data move correctly everytime.

  • Your problem is cache coherence.  Please do the following;

    • Align your data buffers to a 128 byte boundary
    • Pad your buffers to fill a multiple of 128 bytes
    • Prior to reading the buffer with the CPU, perform a L2 block invalidate on that address range (it will implicitly operate on L1 as well)
    • Now you can read from the CPU and get "fresh" data each time.
    • If you're writing to the buffer as well you should perform a L2 block writeback after you're finished writing to the buffer.

    Cache coherence is handled in hardware for L1/L2 memory.  For shared data buffers in external memory it is the programmers responsibility to handle coherence as I have outlined above.

  • Hi Brad

    I've done as you suggest,  but the problem didn't change.  The first image move correctly ,and the rest didn't move anything. I record the EDMA3 register. I use Global Channel Registers.

      I map the QDMA_Channel0 to the ParamSet 0

      currDma = (EDMAParam *)(0x02704000);
      currDma->OPT = 0x0010000c;
      currDma->SRC = (U32)(inputImg);
      currDma->A_B_CNT = ((PICHEIGHT) << 16) | PICWIDTH;
      currDma->DST = (U32)(outputImg);
      currDma->S_D_BIDX = (PICWIDTH << 16) | PICWIDTH;
      currDma->LINK_BCNTRLD = 0x1FFFF;
      currDma->S_D_CIDX = 0;
      currDma->CCNT = 1;

                                                                    First time                                                                                                      Second time

                                           IPR                QER              QEER            QSER                         |              IPR                    QER              QEER            QSER                               

    Before DMA                 0x0                   0x0                 0x1                 0x0                           |                0x0                   0x0                 0x1                 0x0   

    Write TiggerWord        0x1                 0x0                  0x1                 0x0                           |                0x1                 0x0                  0x1                 0x0                          

    Write   ICR                     0x0                0x0                   0x1                0x0                            |                0x0                0x0                   0x1                0x0

    Check Destination Buffer               correct                                                                        |                    Wrong

    Address of inputImg                        0x0C000000                                                            |                      0x0C018C00

    Address if outputImg                       0x0x80233700                                                        |                      0x80233700

     

    Everytime before configure the ParamSet value and check the destination Buffer, I use the two functions first

    CACHE_wbL1dWait();
    CACHE_wbL2Wait();

     

     

     

  • If you don't implement it exactly the way I told you then it won't work.  Where's the invalidate...

  • I use the  CACHE_wbInvL1dWait(); and  CACHE_wbInvAllL2Wait(); instead now,  But the second time, the data still didn't move .

  • Please re-post your code and highlight your new cache-related changes in red.  I'm having trouble understanding what you've done.

  • Hi Brad

       I pick out the EDMA code from my project and form a new project,  But  now the first time also didn't move data, I really can't find the reason,

    2844.EdmaTest_C6678.rar

  • You are using global cache operations whereas I specified block cache operations.  You are using 2 write-back invalidate operations while I specified a single invalidate BEFORE READING and a single writeback AFTER WRITING.  I also specified that only the L2 operation needs to be done because it implicitly operates on L1.

    It looks to me like your routine for checking the data is only reading the data.  So what I expected was for you to do a BLOCK INVALIDATE before checking the data.  (Not a writeback, not global.)  That's all...