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.

Large EDMA3 transfer is interfering with audio EDMA transfers

I am trying to port code from a c6713 (EDMA2) to c6747 (EDMA3).

I have various audio (McASP) EDMA transfers operating on PARAMSET 0 thru 5 successfully.

I have been trying to make an EDMA transfer to a 220 x 176 x 16bit LCD module but the resulting large EDMA transfer appears to hold off audio DMA transfers and prevent audio interrupts from occurring in a timely fashion. I thought I saw some evidence that the large transfer was preventing any DSP code from running at all but I am not sure of that now.

I have fiddled with the priorities of TC1,TC0 in the SysCfg register as well as the edma3ccRegs->QUEPRI register. 

I am not sure I understand how to assign this LCD DMA transfer to TC1 or TC0 so I can separate its priority from the other higher priority transfers.

I Have also fiddled with edma3tc(0and1)Regs->RDRATE hoping to slow down the transfer requests, all to no avail.

I suspect there may be a way to break up the large transfer using a different setup of acnt and bcnt settings but I don’t know if that will help and I have been unsuccessful in getting that strategy to transfer any data whatsoever.

I am having a second problem with not being able to write to the LCD module's single address data register in non-increment mode.  I read that the EMIF will not support this mode when used as a destination since it is not a fifo. Is there any way around this so I can use DMA to transfer to the same EMIFA address repeatedly?  I am currently getting around this by isolating the EIMFA address bus from my LCD module temporarily with a PLD. This will become a bigger issue when I apply this transfer strategy to my CF card interface however which also uses a single 16bit data register for sector data transfers.

If this does not get resolved I am planning on using the PRU unit to do the transfers instead.

Below is my test code which manually breaks up the transfer in an inefficient way to prevent  audio interrupts  from failing.

thanks,

-howy

#define QLCD_PARAMSET_7  7  // LCD block xfer
#define QLCD_TC_CODE     7
void QDMAxfer(ushort *DSTaddr, ushort *SRCaddr, int words16)
{
    volatile int i=0, j, Words, WordsPerXfer, tmp;
    volatile int acnt,bcnt,srcBidx,dstBidx,bcntRLD,srcCidx,dstCidx,ccnt;
    volatile uint16 *p16;

     edma3ccRegs->QRAE[0] |= 0xFFFFFFFF; // just let them all thru
     edma3ccRegs->QRAE[1] |= 0xFFFFFFFF; // just let them all thru
     edma3ccRegs->QRAE[2] |= 0xFFFFFFFF; // just let them all thru
     edma3ccRegs->QRAE[3] |= 0xFFFFFFFF; // just let them all thru

   WordsPerXfer = 220*2;
    acnt    = WordsPerXfer; //  Words * sizeof(int16);
    bcnt    = 1;
    bcntRLD = 1;
    srcBidx = 2;
    dstBidx = 0;
    srcCidx = 0;
    dstCidx = 0;
    ccnt    = 1; // never leave ccnt as zero!

    edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].OPT =
        CSL_FMKT(EDMA3CC_OPT_ITCCHEN,  DISABLE)  |
        CSL_FMKT(EDMA3CC_OPT_TCCHEN,   DISABLE)  |
        CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE)  |
        CSL_FMKT(EDMA3CC_OPT_TCINTEN,  ENABLE)  |  // set bit 7 of IPR when complete
        CSL_FMK(EDMA3CC_OPT_TCC,     QLCD_TC_CODE) |  // transfer complete code = 12 or 8
        CSL_FMKT(EDMA3CC_OPT_TCCMOD,   NORMAL) |
        CSL_FMKT(EDMA3CC_OPT_FWID,    16BIT)   |     // word width
        CSL_FMKT(EDMA3CC_OPT_STATIC,  STATIC)  | // NORMAL=0 STATIC=1
        CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC)   |
        CSL_FMKT(EDMA3CC_OPT_DAM,     INCR)   |  //dst CONST or INCR
        CSL_FMKT(EDMA3CC_OPT_SAM,     INCR);     //src CONST or INCR
          // NOTE: src addr and dst addr have limits when using CONST addr mode (32byte boundery)

   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC          = (uint32)SRCaddr; //  srcBOO; // dstBuff;
   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].DST          = (uint32)LCD_DATA_ADDR; // &dstBOO; // dstBuff;
   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].A_B_CNT      = CSL_FMK(EDMA3CC_A_B_CNT_ACNT,         acnt)    | CSL_FMK(EDMA3CC_A_B_CNT_BCNT,     bcnt);

   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC_DST_BIDX = CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, srcBidx) | CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX,dstBidx);
   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].LINK_BCNTRLD = CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK,    0xFFFF ) | CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD,bcntRLD);
   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC_DST_CIDX = CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, srcCidx) | CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX,dstCidx);
   edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].CCNT         =  ccnt;

    //hdelayMS(10); // wait for cache
    BitPLD(baForceLCDA0,1); // force DATA writes to PLD so address bit cannot change (FRONT_A0=1)
    p16 = (uint16 *)SRCaddr;
    for(j=0;j<(220*176)/(WordsPerXfer/2);j++) // size of LCD is 220x176 16bit words (EMIFA is 16bits wide)
         {    
        edma3ccRegs->PARAMSET[QLCD_PARAMSET_7].SRC  = (uint32)SRCaddr;
        SRCaddr += WordsPerXfer/2;
        edma3ccRegs->ICR = (1<<QLCD_PARAMSET_7); // clear iterrupt pending bit
        edma3ccRegs->ESR = (1<<QLCD_PARAMSET_7); // event set reg
        for(i=0;i<1e9;i++)
            {
            tmp = edma3ccRegs->IPR; // wait for EDMA transfer to finish
            if(tmp & (1<<QLCD_PARAMSET_7))
                break;
            }
          hdelay(gboodly);
        tmp = edma3ccRegs->IPR; // for debug
        }
    return;
}

  • Howy,

    What is the data rate of your audio data?

    How much audio data do you transfer per audio DMA event? How many audio DMA events and channels do you use?

    How often do you expect to get audio interrupts?

    Sort of combining all of those questions: what is the time period between audio events at which the DMA response is required to be able to meet real-time requirements?

    What would your ideal DMA operation be to go to the LCD?

    Your function name is QDMAxfer, but it is using ESR to trigger. Is QDMA the old way you used to do it?

    How small do you have to make the LCD transfers to avoid any stalls in your audio?

    To the question on selecting TC0 or TC1, please see the EDMA3 User's Guide Section 4.2.1.4 on the DMAQNUMn registers. You make this setting on a channel-by-channel basis. There is also a QDMAQNUM register for the QDMA channels.

    howy said:
    I am having a second problem with not being able to write to the LCD module's single address data register in non-increment mode.  I read that the EMIF will not support this mode when used as a destination since it is not a fifo. Is there any way around this so I can use DMA to transfer to the same EMIFA address repeatedly?  I am currently getting around this by isolating the EIMFA address bus from my LCD module temporarily with a PLD. This will become a bigger issue when I apply this transfer strategy to my CF card interface however which also uses a single 16bit data register for sector data transfers.

    You are correct that you cannot use the CONST mode for SAM and DAM. Just use BIDX=0 and ACNT=2 and ABSYNC and BCNT=#words to xfer. The EDMA3 UG explains this most technically, but one of the online training videos may help you understand how this works.

    In the Training section of TI.com, there is a training video set for the C6474. Although it is a different device, the EDMA3/QDMA/IDMA Module may help you understand some of the features and options available within the EDMA3 module. You can find the complete video set here.

    The EMIF transfers are generally more efficient if you use incrementing addresses. If you can map the pins to your EMIF devices so they do not use the bottom 8 EMIF address bits, for example, then you can send data to 256 half-words using one command with incrementing addresses and your device will not know the difference between that and sending the data to a single address. Just a thought and recommendation, but not a requirement.

    Regards,
    RandyP

  • My audio sample rate is currently 48khz but will be 192khz.  I have about 20 McAsp serializers for 40 channels of audio into and out of the box.

    My audio interrupt occurs every 32 samples so my interrupt rate is 1500Hz at 48k and 6000 Hz at 192K. My Audio DMA is set to 2 words per transfer.

    At an interrupt rate of 1500 Hz my program fails when I transfer more than about 1400 words to the LCD in one shot.

    The LCD transfer does not have a strict deadline so my intention was to give it the lowest priority possible which is what the QDMA seems to do nicely on the 6713.  I was expecting to transfer 16 to 64 words at a time to the LCD. If I set up an LCD chained EDMA transfer of 32 words at a time would that allow my audio DMA to sneak in between the delay in the chaining process?

    If I use the PRU to large transfers will I have the same problem?

    -howy

  • >>>Your function name is QDMAxfer, but it is using ESR to trigger. Is QDMA the old way you used to do it?

    I was under the impression that using PARAMSET 0-7 dictated that I was using QDMA. How should I trigger QDMA and what difference in behavior should I expect to see when using QDMA properly?

    -howy

  • Howy,

    How much audio data do you transfer per audio DMA event? How many audio DMA events and channels do you use?

    What is the time period between audio events at which the DMA response is required to be able to meet real-time requirements?

    You have multiple McASPs, and there are a total of 6 DMA events that could be used if you also need to do any transmitting of audio data. Or you could do all the transfers off a single event under the assumption they are synchronous. Also, there are FIFOs that can be used to reduce the number of times the DMA channel responds to an event while increasing the amount of data the DMA event will transfer each time. That information may be useful for figuring out where your problem is.

    Which memory do the audio transfers move data to/from, L2, DDR, EMIFA SDRAM, Shared memory?

    Which memory do the LCD transfers move data from, L2, DDR, EMIFA SDRAM, Shared memory?

    If there is not a bottleneck or conflict at the memory device, then moving the LCD transfers to TC1 should get rid of your problems.

    Please let us know the result of moving to TC1 (Q1), or send the extra answers and questions if that does not solve it for you.

    Regards,
    RandyP

  • Howy,

    Howy said:
    I was under the impression that using PARAMSET 0-7 dictated that I was using QDMA. How should I trigger QDMA and what difference in behavior should I expect to see when using QDMA properly?

    That is not a common way to allocate the PARAM, from my experience, but that depends on how you have configured the channels. The training video I referenced discusses this, but the software you use to do the configuration makes the final choice.

    If you were trying to use QDMA, then you were doing it wrong. You do not use ESR for QDMA. Either the videos or the EDMA3 UG will help you understand it better.

    Regards,
    RandyP

  • It only took me 30 minutes to get the PRU fired up and it does exactly what I want now, so I will just leave the EDMA3 programming to the younger guys who still have a few brain cell s left.

    thanks,

    -howy