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.

TMS320C6738 EDMA interrupt problems

Other Parts Discussed in Thread: TMS320C6748, OMAPL138

Hi

I am using the edma to send samples to the mcasp where a codec is connected. This is on the LCDK eval board. Previously I was doing it via mcasp interrupts and everything worked fine except for the inefficiency.


Now I am using the edma to do this using ping pong buffers. Each buffer is 2048 shorts. Three params are used for the ping-pong control. The main param is updated with either ping or pong alternately. An interrupt routine is used to signal a semaphore in a task that is waiting for the expiration of each buffer.. The cpu task upon being signaled will fill the buffer that is not being used by the edma. This follows the basic ping pong buffering idea using edma interrupts.

I hooked the audio output from the codec to an oscilloscope and noticed spikes in the waveform. The spikes happen exactly at the boundary where the switch over happens. The buffers are filled with a sine wave by the task and I expect to see a near perfect sine wave on the scope.

Next I filled the ping-pong buffers during initialization of the edma and allow the edma to free run without going into the edma interrupt routine. The spikes completely vanished.

It seems as if the spikes are introduced by the edma entering the edma isr and a 0 is sent out to the mcasp during this time of change over. This brings up several questions regarding the timing of events of the edma during an update of the param.

1 Does the Param copying from one of the holder params happen before entering the isr or during the isr or after returning from the isr?

2 Logically I would expect the param copying to happen before entering the isr after the last sample of the ping or pong buffer has been sent out to the mcasp.

This would allow enough time for the isr to be serviced and exited. before the expiration of the buffer being read out to the mcasp. Is this the case?

3 Does the edma wait for return from the isr to send out the next sample for an event request from the mcasp? This could cause an under run on the mcasp but I haven't seen evidence of this.

When the edma is free running without the transfer completion isr enabled everything works fine which points to that the param copying is happening in time before the next event. Entering the isr seems to throw a spanner in the works. I have double checked that the IPR is cleared properly of all outstanding interrupt events. However it is difficult to verify via the debug system. There is a chance that the IPR is not fully cleared and is being re-entered.

This is highly important issue for us as this is a critical piece of the system that has to work correctly and we cannot tolerate any spurious outputs on the audio channel and that the edma should behave properly and predictably.

Your help to sort this out is much appreciated. I have also attached the edma test code file.

Thank you and regards

Manjula

7444.edma_test.c
/*
 * edma_test.c
 *
 *  Created on: May 13, 2014
 *      Author: Manjula Ellepola
 */


#include <xdc/std.h>                                //mandatory - have to include first, for BIOS types
#include <ti/sysbios/BIOS.h>                        //mandatory - if you call APIs like BIOS_start()
#include <xdc/cfg/global.h>                         //header file for statically defined objects/handles


#include "hw_psc_C6748.h"
#include "soc_C6748.h"
//#include "interrupt.h"
//#include "uartStdio.h"
#include "lcdkC6748.h"
#include "hw_types.h"
#include "edma.h"
#include "psc.h"
#include "interrupt.h"
#include "math.h"

#define PI 3.1415926535897932384626433832795

#define CHTYPE_DMA

/* MAX ACOUNT */
#define MAX_ACOUNT        (512u)

/* MAX BCOUNT */
#define MAX_BCOUNT        (1u)

/* MAX CCOUNT */
#define MAX_CCOUNT        (1u)

#define MAX_BUFFER_SIZE     (MAX_ACOUNT * MAX_BCOUNT * MAX_CCOUNT)

volatile short   _rxBuff[MAX_BUFFER_SIZE];
volatile short    _dstBuff[32];

volatile short tx_buf0[4096];
//volatile short tx_buf1[1024];

volatile short dma_sin_buf[64] = { 0, 0, 3121, 0, 6122,   0, 8889,  0, 11313,  0, 13303, 0, 14782,  0, 15692, 0, 16000, 0, 15692,  0, 14782, 0, 13303, 0, 11313, 0, 8889, 0,
        6122, 0, 3121, 0,0, 0, -3122,0, -6123,0, -8890,0,-11314,0, -13304,0,  -14783,0, -15693,0, -16000,0, -15693,0,-14783,0, -13304,0, -11314,
        0, -8890,0,  -6123,0, -3122, 0};



volatile short *rxBuff;
volatile short *dstBuff;

volatile short* dmaTxBuffPtr;

EDMA3CCPaRAMEntry paramSet;

unsigned int McASP_DMA_rx;
unsigned int McASP_DMA_tx;

/* DATA PARAMETERS PROVIDED BY APPLICATION */
#ifdef CHTYPE_DMA
    unsigned int chType     = EDMA3_CHANNEL_TYPE_DMA;
    unsigned int chNum      = 1;
    unsigned int tccNum     = 0;
    unsigned int edmaTC     = 0;
    unsigned int syncType     = EDMA3_SYNC_A;
    unsigned int trigMode     = EDMA3_TRIG_MODE_EVENT; //EDMA3_TRIG_MODE_MANUAL;
    unsigned int evtQ           = 0;/* Event Queue used                     */
#else
    unsigned int chType     = EDMA3_CHANNEL_TYPE_QDMA;
    unsigned int chNum      = 0;
    unsigned int tccNum     = 0;
    unsigned int edmaTC     = 0;
    unsigned int syncType     = EDMA3_SYNC_A;
    unsigned int trigMode     = EDMA3_TRIG_MODE_QDMA;
    unsigned int paRAMId        = 32u;
    unsigned int evtQ           = 0;/* Event Queue used                     */
    unsigned int opt            = 0;
#endif




void init_edma_McAspTx(void)
{
           volatile unsigned int index = 0;
           volatile unsigned int count = 0;
           volatile unsigned int isIPR;


           unsigned char data = 0u;
           unsigned int retVal = 0u;
           unsigned int Istestpassed = 0u;
           unsigned int numenabled = 0u;
           unsigned int acnt = MAX_ACOUNT;
           unsigned int bcnt = MAX_BCOUNT;
           unsigned int ccnt = MAX_CCOUNT;
           unsigned int irqRaised = 0;
           int i; float phi, phi2, dphi, sin_val, sin_val1, dphi2 = 0;

           phi = 0; phi2 =0;
              //dphi = 360.0 * 100.0/48000.0;
              dphi = 2*PI*6.7/512.0; //*128/2048;
             // dphi2 = 2*PI*23.0/512.0;

            /* Enabling the PSC for EDMA3CC_0.*/
            PSCModuleControl(SOC_PSC_0_REGS, 0, 0, PSC_MDCTL_NEXT_ENABLE);

            /* Enabling the PSC for EDMA3TC_0.*/
            PSCModuleControl(SOC_PSC_0_REGS, 1, 0, PSC_MDCTL_NEXT_ENABLE);

            EDMA3Init(SOC_EDMA30CC_0_REGS, evtQ);



               //srcBuff = (char *)_srcBuff;
               //dstBuff = (char *)_dstBuff;


              // rxBuff = (short *)_rxBuff;
            dmaTxBuffPtr = tx_buf0; //dma_sin_buf;

            for(i=0; i< 2048; i++)
            {

                sin_val = (short)( 8000.0*sin(phi));
                sin_val1 = 0.0; //(short)( 8000.0*sin(phi2));
                tx_buf0[i*2] = sin_val;
                tx_buf0[i*2+1] = sin_val1;
               // tx_buf1[i*2] = sin_val1;
               // tx_buf1[i*2+1] = sin_val;

                phi = phi + dphi;
                if (phi > 2*PI) phi -= 2*PI;

                phi2 = phi2 + dphi2;
                if (phi2 > 2*PI) phi2 -= 2*PI;
            }


               /* Request DMA channel and TCC */
               retVal = EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, chNum, tccNum, evtQ);

               //McASP_DMA_rx = 0x01D002B8; //0x01D02000;  0x01D002B8;
               McASP_DMA_tx = 0x01D00234;

               if (TRUE == retVal)
                   {
                       /* Fill the PaRAM Set with transfer specific information */
         //              paramSet.srcAddr  =  dstBuff; //(volatile int)(rxBuff); //McASP_DMA_rx; //(unsigned int)(srcBuff);

                       paramSet.srcAddr  =  (unsigned int) dmaTxBuffPtr;
                       paramSet.destAddr =  McASP_DMA_tx;

                       paramSet.aCnt = 2u;
                       paramSet.bCnt = 2048u; //64u;
                       paramSet.cCnt = (unsigned short)1;

                       /* Setting up the SRC/DES Index */
                       paramSet.srcBIdx = 2u;
                       paramSet.destBIdx = 0;

                       paramSet.srcCIdx  = 1u; //2u;
                       paramSet.destCIdx = 0;


                       paramSet.linkAddr = (unsigned short)0x43C0u;   // point to par-ram 30
                       paramSet.bCntReload = 2048u; //64u;
                           paramSet.opt = 0u;
                       /* Src & Dest are in INCR modes */
                       paramSet.opt &= 0xFFFFFFFCu;
                       /* Program the TCC */
                       paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);

                       /* Enable Intermediate & Final transfer completion interrupt */
                    //  paramSet.opt |= (1 << EDMA3CC_OPT_ITCINTEN_SHIFT);
                       paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);

                      // if (syncType == EDMA3_SYNC_A)
                      //     {
                           paramSet.opt &= 0xFFFFFFFBu;

                           //paramSet.opt = 0000|0000|0101|0000|0000|0000|0000
                           paramSet.opt = 0x00100000;

                       /* Now, write the PaRAM Set. */
                       EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, chNum, &paramSet);
                   }

               paramSet.srcAddr  = (unsigned int)(tx_buf0+2048); // (unsigned int) dmaTxBuffPtr;
               paramSet.linkAddr = (unsigned short)0x43E0u;
               EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 30, &paramSet);

               paramSet.srcAddr  = (unsigned int)tx_buf0; // (unsigned int) dmaTxBuffPtr;
               paramSet.linkAddr = (unsigned short)0x43C0u;
               EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);

                   // clear int enable reg in edma
                   HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_IECR) = 0xFFFFFFFF;
                   // clear IPR in edma
                 //  HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_ICR) = 0xFFFFFFFF;
                   HWREG(0x01C01070) = 0xFFFFFFFF;




                  // EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, chNum);
            //      EDMA3EnableEvtIntr(SOC_EDMA30CC_0_REGS, 0); // enable edma evt-1 interrupt which is mapped to McASP tx


                  retVal = EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);


}


void init_edma_McAspRx(void)
{
           volatile unsigned int index = 0;
           volatile unsigned int count = 0;
           volatile unsigned int isIPR;
           EDMA3CCPaRAMEntry paramSet;
           unsigned char data = 0u;
           unsigned int retVal = 0u;
           unsigned int Istestpassed = 0u;
           unsigned int numenabled = 0u;
           unsigned int acnt = MAX_ACOUNT;
           unsigned int bcnt = MAX_BCOUNT;
           unsigned int ccnt = MAX_CCOUNT;
           unsigned int irqRaised = 0;
           int i;

            /* Enabling the PSC for EDMA3CC_0.*/
            PSCModuleControl(SOC_PSC_0_REGS, 0, 0, PSC_MDCTL_NEXT_ENABLE);

            /* Enabling the PSC for EDMA3TC_0.*/
            PSCModuleControl(SOC_PSC_0_REGS, 1, 0, PSC_MDCTL_NEXT_ENABLE);

            EDMA3Init(SOC_EDMA30CC_0_REGS, evtQ);



               //srcBuff = (char *)_srcBuff;
               //dstBuff = (char *)_dstBuff;

               rxBuff = (short *)_rxBuff;
               dstBuff = (short *)_dstBuff;

               /* Initalize source and destination buffers */
               for (count = 0u; count < (acnt*bcnt*ccnt); count++)
               {
               //rxBuff[count] = 0; ////(short)(512.0*sin(2*PI*count/128));
               dstBuff[count] = 0;
               /*
                * No need to initialize the destination buffer as it is
                    * being invalidated.
                */
               }

               /* Request DMA channel and TCC */
               retVal = EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, chNum, tccNum, evtQ);

               McASP_DMA_rx = 0x01D002B8; //0x01D02000;  0x01D002B8;

               if (TRUE == retVal)
                   {
                       /* Fill the PaRAM Set with transfer specific information */
                       paramSet.srcAddr  =  McASP_DMA_rx; //(volatile int)(rxBuff); //McASP_DMA_rx; //(unsigned int)(srcBuff);
                       paramSet.destAddr = (unsigned int)(dstBuff);

                       paramSet.aCnt = 2u;
                       paramSet.bCnt = 512u;
                       paramSet.cCnt = (unsigned short)1;

                       /* Setting up the SRC/DES Index */
                       paramSet.srcBIdx = 0;
                       paramSet.destBIdx = 2u;

                       paramSet.srcCIdx  = 0;
                       paramSet.destCIdx = 2u;


                       paramSet.linkAddr = (unsigned short)0xFFFFu;
                       paramSet.bCntReload = 512u;
                           paramSet.opt = 0u;
                       /* Src & Dest are in INCR modes */
                       paramSet.opt &= 0xFFFFFFFCu;
                       /* Program the TCC */
                       paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);

                       /* Enable Intermediate & Final transfer completion interrupt */
                    //  paramSet.opt |= (1 << EDMA3CC_OPT_ITCINTEN_SHIFT);
                       paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);

                      // if (syncType == EDMA3_SYNC_A)
                      //     {
                           paramSet.opt &= 0xFFFFFFFBu;

                       /* Now, write the PaRAM Set. */
                       EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, chNum, &paramSet);
                   }

                   isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);

                   for(i=0; i<32; i++)
                   {
                       EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, i);
                   }

                   isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
                   EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, chNum);
            //      EDMA3EnableEvtIntr(SOC_EDMA30CC_0_REGS, 0);
           //        retVal = EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);


}



/**
 * edma3CCComplIsr
 * \brief   ISR for successful transfer completion.
 *
 * \note    This function first disables its own interrupt to make it non-
 *          entrant.
 *
 * \return  None.
 */
void edma3CCComplIsr(void)
{
    volatile unsigned int pendingIrqs;
    volatile unsigned int isIPR = 0;

    unsigned int indexl;
    unsigned int Cnt = 0;
    indexl = 0u;
#ifdef _TMS320C6X
   // IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
#else
  //  IntSystemStatusClear(SYS_INT_CCINT0);
#endif
  //  isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);


  //  Semaphore_post (txVectorModStart);
    HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(1)) = 0xFFFFFFFF;

    // check for mxASP dma interrupt
  //  indexl = isIPR  & 0x1; // bit 0 of dma-IPR
 //   if (indexl != 0)
//   {



        // switch buffers
    /*
        if(paramSet.srcAddr  == (unsigned int)tx_buf1)
        {
            paramSet.srcAddr  = (unsigned int)tx_buf0;
            EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);
            dmaTxBuffPtr = tx_buf0;
        }
        else
        {
           paramSet.srcAddr  = (unsigned int)tx_buf1;
            EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);
            dmaTxBuffPtr = tx_buf1;
        }
        */

        // trigger swi or post semaphore
     //   Semaphore_post (txVectorModStart);

        // clear IPR bit
 //       EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, 0);
     //   HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_ICR(0)) = 0xFFFFFFFF;
  //  }

  //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(1)) = 0xFFFFFFFF;
  //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(0)) = 0xFFFFFFFF;
  //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(2)) = 0xFFFFFFFF;
    // do other dmas that are enabled


    // check IPR again
 //   isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);

  //  if(isIPR != 0)
  //  {

   //     HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_IEVAL) = 1;
  //  }

  //  return;




  //  Semaphore_post (dmaNextBufStart);

}

void holder(void)

{
    volatile unsigned int pendingIrqs;
       volatile unsigned int isIPR = 0;

       unsigned int indexl;
       unsigned int Cnt = 0;
       indexl = 0u;

    if(isIPR)
      {
          while ((Cnt < EDMA3CC_COMPL_HANDLER_RETRY_COUNT)&& (indexl != 0u))
         {
              indexl = 0u;
              pendingIrqs = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
              while (pendingIrqs)
              {
                  if(pendingIrqs & 1u == 1)
                  {
                      /**
                       * If the user has not given any callback function
                       * while requesting the TCC, its TCC specific bit
                       * in the IPR register will NOT be cleared.
                       */
                      /* Here write to ICR to clear the corresponding IPR bits */
                      EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, indexl);

                  }
                  ++indexl;
                  pendingIrqs >>= 1u;
               }

              Cnt++;
         }
      }

}


  • The DSP is TMS320C6748
  • Hi,
    Please refer to the following TI E2E posts which is similar to your problems.

    e2e.ti.com/.../1061108

    e2e.ti.com/.../1352229
  • Hi Titus

    Thank you for the feedback. I had a look at the links provided. By the way you have got a very very interesting name :)

    Both the links provided did not provide the answer however I suspect that one of them might have faced a similar issue. After laboring for nearly a week to find the problem, I have finally solved it today. I am happy about this as this was go/no go issue for this processor which I like very much and would have been sad to move onto something else. We plan to produce 10k to 50k units per year, so the problem had to be solved.

    This is a very serious case with the Edma. Either it is an undocumented feature or a silicon error. I want you guys to look into this a bit more before I tell you what I did to solve the problem as there might be an alternate solution.

    Basically the problem is: Particularly when you do ping-pong buffering the edma puts out a spurious value through to the mcAsp on the boundary transitions from the second to first buffer. That is if you start with ping proceed onto pong and then when pong switches back to ping is where the spurious value is read out and sent to Mcasp. The spikes caused by the spurious value can be easily seen on the scope.

    Another clue is that the magnitude of the spikes varied with each compile and build :)


    I look forward to your feed back if you have any suggestions for the above problem. I am keen to get this out to the community as some might be having the same issue as well.

    Thanks and regards

    Manjula
  • Hi Manjula,

    Thanks for your update.

    For basic DMA buffer handling for ping pong operation, please ensure your code is compliant to the below wiki:

    http://processors.wiki.ti.com/index.php/StarterWare_Audio_Application

    To understand more on EDMA ping pong buffer, you could also check the below tutorial:

    http://processors.wiki.ti.com/images/b/b8/Eindhoven_JAN_12-10_IntroTo_Edma.pdf?keyMatch=EDMA ping pong buffering&tisearch=Search-EN

    I would suggest first you to check the PaRAM settings before and after you start off the transfer and also check whether the data is wrritten to the corresponding memory location.

    Have you checked the status of interrupt pending register and see whether the corresponding interrupt is pending or not?

    Likewise, there are lot many status registers available to you to evaluate the status of interrupts, data transfer completion notification etc. For more details, please refer the C6748 EDMA user guide.

    Can you provide the PaRAM values that got programmed in the PaRAM registers after the EDMA is configured? Also run to execute this and verify that the data had written in the destination buffer.

    Can you open a memory window and display what's at the PaRAM entry you've done?

    Can you look at the IPR of the Shadow regions or the Global Regions IPR.  Can you do memory dumps of the channel registers before the transfer and after the transfer?

    Why don't you to try the EDMA ping pong buffer code which is attached as zip file from the below E2E post and evaluate whether any spurious value being sent to mcasp and do you observe any spikes caused by the spurious value:

    http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/115/p/376334/1352229#1352229

    Kindly test the EDMA ping pong buffer code and let us know your inputs on the code (4784.OMAPL138_StarterWare_McASP_EDMA_PING_PONG.zip)

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • HI Sivaraj

    Thank you for the excellent support content and suggestions I will go through them for added info.

    As mentioned in my previous post I have solved this problem and I wanted to see if there was anything you guys have come across regarding the ping pong buffers and spurious output issues. 

    The solution I found was that I needed to align the ping-pong buffers using the pragma align macro. Once I did this the spurious output issue got solved. This points to a pipeline problem or index updating  problem on the roll over in the edma controller. In my case the buffer is 1024 x int32s. The buffer is split into half for  ping-pong buffering (ie buf, buf+512).. I found that I had to use a minimum value of 64 for the pragma align. Any value above this works. The 64 value must have something to do with the burst size of the edma and the pipeline.


    I have done all the debug and checked the params etc that you have asked me to check above and they are as they should be. I was really puzzled by this issue but I was sure that the issue happened in the boundary where the pong switches back to ping. There is no problem in the ping to pong transition.

    I wonder if you guys have come across this issue before. I can send you my test code if you are interested to investigate further. I think this is a serious issue that needs to be investigated further.

    Thank you for all your support. I find this forum and support excellent and have solved many issues for me.


    Best regards

    Manjula

  • Hi

    I would like some feedback to this problem. I may or may not be correct in the above finding and I am looking to your expertise for a definitive answer/feedback as when we develop products we need to know that the product will have definitive behaviour. Otherwise we spend hours in chasing ghosts and shadows when the real problem is somewhere else. I thing this is an important issue as the DMA is an important system component of this particular system.

    Thanks
    Manjula
  • Hi,

    Thanks for your update.

    Please provide the PaRAM values that got programmed in the PaRAM registers after the EDMA is configured.
    Kindly execute this and ensure that the data has been written in the destination buffer.

    Please open a memory window and display what's at the PaRAM entry you've done and give us the snapshot.

    Please look at the IPR of the Shadow regions or the Global Regions IPR and kindly provide us the memory dumps of the channel registers before the transfer and after the transfer.

    Kindly provide the snapshots for the above.

    Thanks & regards,
    Sivaraj K
  • Hi Sivaraj

    Thank you for your support and sorry for the late reply. Please find attached the dumps as requested. Also I have attached the edma test file. Please note the Pragma align for the buffers. You can test with and without this directive. I am using RTOS and also the edma API from the starter ware.

    At the moment this works properly. However what I am not sure is if the alignment of the buffers solved the problem I was having described above or not. There was something about SAM/DAM and alignment for buffers for constant addressing in the documentation. The SAM/DAM as you can see is set to 0 as it should be for this processor.

    I am keen to see your analysis and resolution to this.

    Thanks a lot.

    BR
    Manjula

    7343.edma_test.c
    /*
     * edma_test.c
     *
     *  Created on: May 13, 2014
     *      Author: Manjula Ellepola
     */
    
    
    #include <xdc/std.h>                                //mandatory - have to include first, for BIOS types
    #include <ti/sysbios/BIOS.h>                        //mandatory - if you call APIs like BIOS_start()
    #include <xdc/cfg/global.h>                         //header file for statically defined objects/handles
    
    
    #include "hw_psc_C6748.h"
    #include "soc_C6748.h"
    //#include "interrupt.h"
    //#include "uartStdio.h"
    #include "lcdkC6748.h"
    #include "hw_types.h"
    #include "edma.h"
    #include "psc.h"
    #include "interrupt.h"
    #include "math.h"
    
    #define PI 3.1415926535897932384626433832795
    
    #define CHTYPE_DMA
    
    /* MAX ACOUNT */
    #define MAX_ACOUNT        (512u)
    
    /* MAX BCOUNT */
    #define MAX_BCOUNT        (1u)
    
    /* MAX CCOUNT */
    #define MAX_CCOUNT        (1u)
    
    #define MAX_BUFFER_SIZE     (MAX_ACOUNT * MAX_BCOUNT * MAX_CCOUNT)
    
    volatile short  _rxBuff[MAX_BUFFER_SIZE];
    volatile short    _dstBuff[32];
    
    #pragma DATA_ALIGN(tx_buf0, 128)   // **try with and without the pragma to see if problem occurs at boundary
    volatile int tx_buf0[2048]; // 512 ints for each channel
    
    #pragma DATA_ALIGN(rx_buf0, 64)
    volatile short rx_buf0[2048];
    
    void init_edma_McAspRx(void);
    
    volatile short *rxBuff;
    volatile short *dstBuff;
    
    volatile int* dmaTxBuffPtr;
    
    EDMA3CCPaRAMEntry paramSet;
    
    unsigned int McASP_DMA_rx;
    unsigned int McASP_DMA_tx;
    
    void taskTxTone(void);
    
    /* DATA PARAMETERS PROVIDED BY APPLICATION */
    #ifdef CHTYPE_DMA
        unsigned int chType     = EDMA3_CHANNEL_TYPE_DMA;
        unsigned int chNum      = 1;
        unsigned int tccNum     = 0;
        unsigned int edmaTC     = 0;
        unsigned int syncType     = EDMA3_SYNC_A;
        unsigned int trigMode     = EDMA3_TRIG_MODE_EVENT; //EDMA3_TRIG_MODE_MANUAL;
        unsigned int evtQ           = 0;/* Event Queue used                     */
    #else
        unsigned int chType     = EDMA3_CHANNEL_TYPE_QDMA;
        unsigned int chNum      = 0;
        unsigned int tccNum     = 0;
        unsigned int edmaTC     = 0;
        unsigned int syncType     = EDMA3_SYNC_A;
        unsigned int trigMode     = EDMA3_TRIG_MODE_QDMA;
        unsigned int paRAMId        = 32u;
        unsigned int evtQ           = 0;/* Event Queue used                     */
        unsigned int opt            = 0;
    #endif
    
    
    int pingPong = 0;
    
    void init_edma_McAspTx(void)
    {
               volatile unsigned int index = 0;
               volatile unsigned int count = 0;
               volatile unsigned int isIPR;
    
    
               unsigned char data = 0u;
               unsigned int retVal = 0u;
               unsigned int Istestpassed = 0u;
               unsigned int numenabled = 0u;
               unsigned int acnt = MAX_ACOUNT;
               unsigned int bcnt = MAX_BCOUNT;
               unsigned int ccnt = MAX_CCOUNT;
               unsigned int irqRaised = 0;
               int i; float phi, phi2, dphi, dphi2 = 0;
               int sin_val, sin_val1 = 0;
    
    
               phi = 0; phi2 =0;
                  //dphi = 360.0 * 100.0/48000.0;
                  dphi = 2*PI*8.3/512.0; //*128/2048;
                 // dphi2 = 2*PI*23.0/512.0;
    
                /* Enabling the PSC for EDMA3CC_0.*/
                PSCModuleControl(SOC_PSC_0_REGS, 0, 0, PSC_MDCTL_NEXT_ENABLE);
    
                /* Enabling the PSC for EDMA3TC_0.*/
                PSCModuleControl(SOC_PSC_0_REGS, 1, 0, PSC_MDCTL_NEXT_ENABLE);
    
                EDMA3Init(SOC_EDMA30CC_0_REGS, evtQ);
    
    
    
                   //srcBuff = (char *)_srcBuff;
                   //dstBuff = (char *)_dstBuff;
    
    
                  // rxBuff = (short *)_rxBuff;
                dmaTxBuffPtr = tx_buf0; //dma_sin_buf;
    
    
                   /* Request DMA channel and TCC */
                   retVal = EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, chNum, tccNum, evtQ);
    
                   //McASP_DMA_rx = 0x01D002B8; //0x01D02000;  0x01D002B8;
                   McASP_DMA_tx = 0x01D02000; //0x01D00234;
    
                   if (TRUE == retVal)
                       {
                           /* Fill the PaRAM Set with transfer specific information */
             //              paramSet.srcAddr  =  dstBuff; //(volatile int)(rxBuff); //McASP_DMA_rx; //(unsigned int)(srcBuff);
    
                           paramSet.srcAddr  = (unsigned int)tx_buf0;
                           paramSet.destAddr =  McASP_DMA_tx;
    
                           paramSet.aCnt = 4u;
                           paramSet.bCnt = 1024u; //512u; //64u;
                           paramSet.cCnt = (unsigned short)1;
    
                           /* Setting up the SRC/DES Index */
                           paramSet.srcBIdx = 4u;
                           paramSet.destBIdx = 0;
    
                           paramSet.srcCIdx  = 0; //1u; //2u;
                           paramSet.destCIdx = 0;
    
    
                           paramSet.linkAddr = (unsigned short)0x43C0u;   // point to par-ram 30
                           paramSet.bCntReload = 0; //512u; //64u;
                               paramSet.opt = 0u;
                           /* Src & Dest are in INCR modes */
                           paramSet.opt &= 0xFFFFFFFCu;
                           /* Program the TCC */
                           paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
    
                           /* Enable Intermediate & Final transfer completion interrupt */
                        //  paramSet.opt |= (1 << EDMA3CC_OPT_ITCINTEN_SHIFT);
                           paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
    
                          // if (syncType == EDMA3_SYNC_A)
                          //     {
                               paramSet.opt &= 0xFFFFFFFBu;
                               //               31  |27  |23  |19  |15  |11  |7   |3
                               //paramSet.opt = 0000|0000|0000|0000|0000|0000|0000|0000
                            //   paramSet.opt = 0x00D00000;
                               paramSet.opt = 0x00100000;
    
                           /* Now, write the PaRAM Set. */
                           EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, chNum, &paramSet);
                       }
    
                   paramSet.srcAddr  = (unsigned int)(tx_buf0+1024); // (unsigned int) dmaTxBuffPtr;
                   paramSet.linkAddr = (unsigned short)0x43E0u;
                   EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 30, &paramSet);
    
                   paramSet.srcAddr  = (unsigned int)tx_buf0; // (unsigned int) dmaTxBuffPtr;
                   paramSet.linkAddr = (unsigned short)0x43C0u;
                   EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);
    
                       // clear int enable reg in edma
                       HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_IECR) = 0xFFFFFFFF;
                       // clear IPR in edma
                     //  HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_ICR) = 0xFFFFFFFF;
                       HWREG(0x01C01070) = 0xFFFFFFFF;
    
    
                    init_edma_McAspRx();
    
                      // EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, chNum);
                      EDMA3EnableEvtIntr(SOC_EDMA30CC_0_REGS, 0); // enable edma evt-1 interrupt which is mapped to McASP tx
    
    
                      retVal = EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);
    
    
    }
    
    
    void init_edma_McAspRx(void)
    {
               volatile unsigned int index = 0;
               volatile unsigned int count = 0;
               volatile unsigned int isIPR;
               EDMA3CCPaRAMEntry paramSet;
               unsigned char data = 0u;
               unsigned int retVal = 0u;
               unsigned int Istestpassed = 0u;
               unsigned int numenabled = 0u;
               unsigned int acnt = MAX_ACOUNT;
               unsigned int bcnt = MAX_BCOUNT;
               unsigned int ccnt = MAX_CCOUNT;
               unsigned int irqRaised = 0;
               int i;
    
                /* Enabling the PSC for EDMA3CC_0.*/
         //       PSCModuleControl(SOC_PSC_0_REGS, 0, 0, PSC_MDCTL_NEXT_ENABLE);
    
                /* Enabling the PSC for EDMA3TC_0.*/
         //       PSCModuleControl(SOC_PSC_0_REGS, 1, 0, PSC_MDCTL_NEXT_ENABLE);
    
          //      EDMA3Init(SOC_EDMA30CC_0_REGS, evtQ);
    
    
    
    
                   /* Request DMA channel and TCC */
                  // retVal = EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, chNum, tccNum, evtQ);
               retVal = EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, chType, 0, 1, evtQ);
    
                   McASP_DMA_rx = 0x01D002B8; //0x01D02000;  0x01D002B8;
    
                   if (TRUE == retVal)
                       {
                           /* Fill the PaRAM Set with transfer specific information */
                           paramSet.srcAddr  =  McASP_DMA_rx; //(volatile int)(rxBuff); //McASP_DMA_rx; //(unsigned int)(srcBuff);
                           paramSet.destAddr = (unsigned int)rx_buf0;
    
                           paramSet.aCnt = 2u;
                           paramSet.bCnt = 1024u;
                           paramSet.cCnt = 1u;
    
                           /* Setting up the SRC/DES Index */
                           paramSet.srcBIdx = 0;
                           paramSet.destBIdx = 2u;
    
                           paramSet.srcCIdx  = 0;
                           paramSet.destCIdx = 0; //2u;
    
    
                           paramSet.linkAddr = (unsigned short)0x4380; // param 28
                           paramSet.bCntReload = 0; //512u;
    
                           //               31  |27  |23  |19  |15  |11  |7   |3
                           //paramSet.opt = 0000|0000|0000|0000|0000|0000|0000|0000
                           paramSet.opt = 0x00001000;
    
                           /* Now, write the PaRAM Set. */
                           EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 0, &paramSet);
                       }
    
    
                   // enable receiver ping-pong buffering
    
                         paramSet.destAddr  = (unsigned int)(rx_buf0+1024); // (unsigned int) dmaTxBuffPtr;
                         paramSet.linkAddr = (unsigned short)0x43A0;
                         EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 28, &paramSet);
    
                         paramSet.destAddr  = (unsigned int)rx_buf0; // (unsigned int) dmaTxBuffPtr;
                         paramSet.linkAddr = (unsigned short)0x4380;
                         EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 29, &paramSet);
    
    
    
                //      EDMA3EnableEvtIntr(SOC_EDMA30CC_0_REGS, 0);
                       retVal = EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, 0, EDMA3_TRIG_MODE_EVENT);
    
    
    }
    
    
    
    /**
     * edma3CCComplIsr
     * \brief   ISR for successful transfer completion.
     *
     * \note    This function first disables its own interrupt to make it non-
     *          entrant.
     *
     * \return  None.
     */
    void edma3CCComplIsr(void)
    {
        volatile unsigned int pendingIrqs;
        volatile unsigned int isIPR = 0;
    
        unsigned int indexl;
        unsigned int Cnt = 0;
        indexl = 0u;
    #ifdef _TMS320C6X
       // IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
    #else
      //  IntSystemStatusClear(SYS_INT_CCINT0);
    #endif
        isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
    
       if(isIPR & 0x1)
       {
           if(pingPong == 0)
           {
               dmaTxBuffPtr = tx_buf0;
               pingPong = 1;
           }
           else
           {
               dmaTxBuffPtr = tx_buf0+1024;
               pingPong = 0;
           }
    
           Semaphore_post (dmaTxBufRdy);
       }
    
    
     //   Semaphore_post (txVectorModStart);
        HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(1)) = 0xFFFFFFFF;
    
        // check for mxASP dma interrupt
      //  indexl = isIPR  & 0x1; // bit 0 of dma-IPR
     //   if (indexl != 0)
    //   {
    
    
    
            // switch buffers
        /*
            if(paramSet.srcAddr  == (unsigned int)tx_buf1)
            {
                paramSet.srcAddr  = (unsigned int)tx_buf0;
                EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);
                dmaTxBuffPtr = tx_buf0;
            }
            else
            {
               paramSet.srcAddr  = (unsigned int)tx_buf1;
                EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, 31, &paramSet);
                dmaTxBuffPtr = tx_buf1;
            }
            */
    
            // trigger swi or post semaphore
         //   Semaphore_post (txVectorModStart);
    
            // clear IPR bit
     //       EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, 0);
         //   HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_ICR(0)) = 0xFFFFFFFF;
      //  }
    
      //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(1)) = 0xFFFFFFFF;
      //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(0)) = 0xFFFFFFFF;
      //  HWREG(SOC_EDMA30CC_0_REGS + EDMA3CC_S_ICR(2)) = 0xFFFFFFFF;
        // do other dmas that are enabled
    
    
        // check IPR again
     //   isIPR = EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS);
    
      //  if(isIPR != 0)
      //  {
    
       //     HWREG(SOC_EDMA30CC_0_REGS+EDMA3CC_IEVAL) = 1;
      //  }
    
      //  return;
    
    
    
    
      //  Semaphore_post (dmaNextBufStart);
    
    }
    
    //-------------------------------------------------------------------------
    // test transmit tone via edma
    //-------------------------------------------------------------------------
    void taskTxTone(void)
    {
        int i=0;
        volatile int k, j = 0;
        volatile float phi, dphi, dphi_d, dphi_a;
        int sin_val, sin_val2;
        phi = 0;
        //dphi = 360.0 * 100.0/48000.0;
        dphi = 2*PI*15.9/512;
        int flag = 0;
        volatile int* tx_buf_ptr;
        short count = 0;
        float PI2 = 2*PI;
    
        float m_phi[3], m_phid[3];
        float phi_acc[5], phid[5];
    
        float t[3];
    
        int tone_acc = 0;
    
        for(i=0; i<3; i++) { m_phi[i] = 0; phi_acc[i] = 0; phid[i] = 0; }
    
        m_phid[0] = PI2 * 5/8192;  m_phid[1] = PI2 * 8/8192;
        m_phid[2] = PI2 * 13/8192;
    
        phid[0] = PI/2.3; //PI2 * 7.2348/512;
        phid[1] = PI2 * 6.59/512;
        phid[2] = PI2 * 8.8/512;
        phid[3] = PI2 * 8.8/550512;
        phid[4] = PI2 * 5.23/1250512;
    
        tx_buf_ptr = dmaTxBuffPtr;
    
        dphi_d = 16.0;
        dphi_a = 32.0;
    
        //dphi = 2*PI*dphi_d/(float)512;
        //dphi_a = 2*PI*8/512;
    
        for( i = 0; i < 256; i++)
          {
             w_buf[i] = (int)( 8000.0*sinsp(phi));
    
              phi = phi + dphi;
             if (phi > 2*PI)
                 {
                     phi = phi - PI2;
                 }
    
          }
    
    
       // w_buf[255] = 0.0;
    
        while(1)
        {
    
    
          //  if(count == 256) count = 257;
            if( count >= 512) count = 0;
    
    
    
            Semaphore_pend(dmaTxBufRdy, BIOS_WAIT_FOREVER);
    
           for( i = 0; i < 512; i++)
           {
             
               w_buf[i] = 0.0;
    
               w_buf[i] = (int)( 32000.0*( sinsp(phi_acc[0])));
    
           
               for(k=0; k<5; k++)
               {
                   phi_acc[k] += phid[k];
                   if (phi_acc[k] > PI2)
                     {
                         phi_acc[k] -= PI2;
                     }
    
               }
    
           }
    
    
    
           for(k=0; k< 3; k++)
           {
               t[k] = sinsp(m_phi[k]);
               m_phi[k] += m_phid[k];
               if(m_phi[k] > PI2)
               {
                   m_phi[k] -= PI2;
               }
           }
    
    
            for(i=0; i< 512; i++)
            {
    
              //  sin_val = (int)sin_buf[i]; // (int)( 8000.0*sinsp(phi));
                dphi_a = -1*w_buf[i];
                dmaTxBuffPtr[i*2] = w_buf[i];
                dmaTxBuffPtr[i*2+1] = dphi_a;
                //count+= 1;
    
            }
    
    
    
    
        }
    }
    
    
    

    IPR after.dat

    IPR before.dat

    params.dat

  • Hi,

    Thanks for your update.

    Yes you are right, the buffer alignment had solved the problem.

    Do not use SAM & DAM set to 1. In the EDMA3 User Guide section "Constant Addressing Mode Transfers/Alignment Issues", there is a note that includes

    "On the C674x/OMAP-L1x processors, no peripherals, memory, or memory controller support constant addressing mode."


    Thanks & regards,
    Sivaraj K
  • Hi Sivaraj,

    Thank you for the reply. If you were to look in the code the SAM/DAM is set to 0 in all PARAMS that are used. The problem happened even with the SAM/DAM set to 0 and only got solved after I used the PRAGMA ALIGN directive. That is why I am suspecting another problem either with the chip or the compiler.

    Can you please clarify?

    BR

    Manjula

  • Hi Manjula,

    Thanks for your update.

    This cannot be a chip issue for sure and may be the compiler you  specified or some other issue, it could be. Please clarify the #directive which you have used to solve this issue.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj

    it is:

    #pragma DATA_ALIGN(tx_buf0, 64)

    64 is the minimum value that I have to use.

    I had to do this even with SAM/DAM set to 0.

    Await your fb.

    BR

    Manjula

  • Can anyone give a conclusive answer to the questions in this thread?
  • Hi,

    To my understanding, even with SAM/DAM set to 0, aligning the ping-pong buffers using the #pragma directive macro as you mentioned above which really matters inorder to fix the buffer alignment issue in EDMA ping pong usecases.

    The fix which you have proposed should hold good for ping pong buffer alignment issue and for sure, don't suspect any chip issue or any compiler issue for the same. This cannot be the cause for the buffer alignment issue.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------

    Please click the Verify Answer button on this post if it answers your question

    -------------------------------------------------------------------------------------------------------

  • Hi Sivaraj,

    Thank you for the feedback. I am still unclear though. You say that the fix that I proposed of aligning the ping-pong buffers will fix the buffer boundary problem (even with SAM/DAM set to 0). I don't find that this should be done anywhere in the documentation. However you also say there is no problem with the chip or the compiler. So I am still unclear what is causing the problem?? Is it an undocumented feature/anomaly?


    Thanks and regards

    Manjla

  • Hi,

    May be, it is not documentated, but i do observe customers aligning these ping pong buffer which would probably fix buffer boundary issue even with SAM/DAM set to 0 which i am aware of.

    Thanks for your understanding.

    Regards,
    Sivaraj K
  • Hi Sivaraj

    Ok, I will keep calm and carry on :)

    Thank you for your help.


    BR


    Manjula