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.

EDMA3 McASP CSL problem on OMAP L138

Other Parts Discussed in Thread: TLV320AIC3106

Hi,

I'm trying to setup EDMA3 with CSL for the DSP side of the OMAP L138 in order to gather samples into buffers from the onboard TLV320AIC3106 of my experimenter kit.

Two DSP examples from http://processors.wiki.ti.com/index.php/QuickStartOMAPL1x_rCSL were used for this EDMA 3 project as a starting point:

  • Audio example (mcasp directory)
  • EDMA_ping_pong_dspL138 (edma directory)

Both projects were executed on the DSP without any issue. So the audio project was a good starting point for my EDMA3 project to echo back samples from the input lines to output lines.

- First of all, I add to the PSC_Init() function the below two lines in the psc.c file:

CSL_FINST(psc0Regs->MDCTL[EDMA3_0CC_LPSC], PSC_MDCTL_NEXT, ENABLE);
CSL_FINST(psc0Regs->MDCTL[EDMA3_0TC0_LPSC], PSC_MDCTL_NEXT, ENABLE);

- Then enable the EDMA3 interrupt into DSPInit() function in the dspmm.c file:

CSL_FINST(IER, CHIP_IER_IE08, ENABLE );                // Enable Interrupt 8

- Select the EDMA3 Interrupt by adding the below line into the DSPIntCtrlInit

CSL_FINS(dspintcRegs->INTMUX2, DSPINTC_INTMUX2_INTSEL8, CSL_INTC_EVENTID_EDMA3_0_CC0_INT1);

- Change _INT8_ISR function by the one below:

Uint32 u32_EDMA_Xmt_Interrupt_Counter = 0u;

Uint32 u32_EDMA_Rcv_Interrupt_Counter = 0u;

interrupt void INT8_ISR(void)
{
    Uint32 regIPR, IxBitMask, IxCounter;

    while(edma3ccRegs->IPR != 0)
    {
        // Read Interrupt Pending Register
        regIPR = edma3ccRegs->IPR;

        // Loop for Set Interrupt Pending Bit
        for(IxCounter = 0; IxCounter < 32; IxCounter++)
        {
            IxBitMask = 1 << IxCounter;

            if(regIPR & IxBitMask)
            {
                // Exit Example on Correct Interrupt
                if(IxCounter == EDMA_EVENT0)
                {
                    // Interrupt Rcv counter increment
                    u32_EDMA_Rcv_Interrupt_Counter++;

                }
                else if(IxCounter == EDMA_EVENT1)
                {
                    // Interrupt Xmit counter increment
                    u32_EDMA_Xmt_Interrupt_Counter++;
                }
                else
                {
                    // No operation
                    asm(" NOP");
                }

                // Clear Pending Interrupt
                edma3ccRegs->ICR = IxBitMask;

                break;
            }
        }
    }
}

- Setup EDMA3 channels with functions below:

#define NUM_OF_BYTES_PER_WORD        4u    // ACNT
#define NUM_OF_WORD_PER_BUFFER        128u    // BCNT
#define NUM_OF_BUFFER            1u    // CCNT

#define BUFSIZE                NUM_OF_WORD_PER_BUFFER * NUM_OF_BUFFER

#define EDMA_EVENT0             (Uint8)0u
#define EDMA_EVENT1             (Uint8)1u

#define EDMA_PARAMETER_SET0         (Uint8)0u
#define EDMA_PARAMETER_SET1         (Uint8)1u
#define EDMA_PARAMETER_SET64        (Uint8)64u
#define EDMA_PARAMETER_SET65        (Uint8)65u

// Data alignment for both receive and transmit buffers
#pragma DATA_ALIGN(u32_Rcv_Buffer, 256u);
#pragma DATA_ALIGN(u32_Xmt_Buffer, 256u);

// Buffers
volatile Uint32 u32_Rcv_Buffer[BUFSIZE] = { 0u };
volatile Uint32 u32_Xmt_Buffer[BUFSIZE] = { 0u };

CSL_Edma3ccRegsOvly edma3ccRegs = (CSL_Edma3ccRegsOvly)(CSL_EDMA30CC_0_REGS);

// Function called just before calling McASPInit() function
void MAT_EDMA_Init(void)
{
    Uint32 u32_Edma_Init_Counter = 0u;

    // Setup EDMA
    MAT_EDMA_Config();

   // Init buffers
   for(u32_Edma_Init_Counter = 0u; u32_Edma_Init_Counter < BUFSIZE; u32_Edma_Init_Counter++)
   {
      U32_Rcv_Buffer[u32_Edma_Init_Counter] = 0u;
      U32_Xmt_Buffer[u32_Edma_Init_Counter] = 0u;
   }
}

void MAT_EDMA_Config(void)
{
    // Clear registers
    CSL_FINST(edma3ccRegs->ECR,    EDMA3CC_ECR_REG, MASK);
    CSL_FINST(edma3ccRegs->SECR, EDMA3CC_SECR_REG, MASK);
    CSL_FINST(edma3ccRegs->IECR, EDMA3CC_IPR_REG, MASK);
    CSL_FINST(edma3ccRegs->ICR, EDMA3CC_IPR_REG, MASK);

    // Enable channels - Region 1 (Region 0: ARM / Region 1: DSP)
    edma3ccRegs->DRA[CSL_EDMA3_REGION_1].DRAE =
        CSL_FMKT(EDMA3CC_DRAE_E0, ENABLE) |
        CSL_FMKT(EDMA3CC_DRAE_E1, ENABLE);

    // Assign Channel 0 - 1 to Queue 0
    edma3ccRegs->DMAQNUM[0u] =
        CSL_FMKT(EDMA3CC_DMAQNUM_E0, Q0) |
        CSL_FMKT(EDMA3CC_DMAQNUM_E1, Q0);

    // Initialize PaRAM Transfer Context for Events 0 - 1
    MAT_EDMA_Config_Rcv_Param();
    MAT_EDMA_Config_Xmt_Param();

    // Enable channel 0 and 1
    CSL_FINST(edma3ccRegs->EESR, EDMA3CC_EESR_E0, SET);
    CSL_FINST(edma3ccRegs->EESR, EDMA3CC_EESR_E1, SET);

    // Enable interrupt 0 and 1
    CSL_FINST(edma3ccRegs->IESR, EDMA3CC_IESR_I0, SET);
    CSL_FINST(edma3ccRegs->IESR, EDMA3CC_IESR_I1, SET);
}

void MAT_EDMA_Config_Rcv_Param (void)
{

//**************   Parameter Set 0 *******************//
    // Reset EDMA PaRAM OPT Register
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].OPT = CSL_EDMA3CC_OPT_RESETVAL;

    // Config PaRAM OPT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].OPT =
        CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE)    |
        CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE) |
        CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC) |
        CSL_FMK(EDMA3CC_OPT_TCC, EDMA_EVENT0);

    // Initialize EDMA Event Src and Dst Addresses
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].SRC = (Uint32)&mcaspRegs->RBUF12;
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].DST = (Uint32)&u32_Rcv_Buffer[0u];

    // Set EDMA Event PaRAM A,B,C CNT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].A_B_CNT =
        CSL_FMK(EDMA3CC_A_B_CNT_ACNT, NUM_OF_BYTES_PER_WORD) |
        CSL_FMK(EDMA3CC_A_B_CNT_BCNT, NUM_OF_WORD_PER_BUFFER);
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].CCNT = NUM_OF_BUFFER;

    // Set EDMA Event PaRAM SRC/DST BIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].SRC_DST_BIDX =
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0u) |
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX, NUM_OF_BYTES_PER_WORD);

    // Set EDMA Event PaRAM SRC/DST CIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].SRC_DST_CIDX =
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, 0u) |
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0u);

    // Set EDMA Event PaRAM LINK and BCNTRLD
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET0].LINK_BCNTRLD =
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64] & 0xFFFFu) |
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD, NUM_OF_WORD_PER_BUFFER);

    //**************   Parameter Set 64  *******************//
    // Reset EDMA PaRAM OPT Register
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].OPT = CSL_EDMA3CC_OPT_RESETVAL;

    // Config PaRAM OPT (Enable TC & ITC Chaining; Set TCC)
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].OPT =
        CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE)    |
        CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE) |
        CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC) |
        CSL_FMK(EDMA3CC_OPT_TCC, EDMA_EVENT0);

    // Initialize EDMA Event Src and Dst Addresses
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].SRC = (Uint32)&mcaspRegs->RBUF12;
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].DST = (Uint32)&u32_Rcv _Buffer[0u];

    // Set EDMA Event PaRAM A,B,C CNT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].A_B_CNT =
        CSL_FMK(EDMA3CC_A_B_CNT_ACNT, NUM_OF_BYTES_PER_WORD) |
        CSL_FMK(EDMA3CC_A_B_CNT_BCNT, NUM_OF_WORD_PER_BUFFER);
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].CCNT = NUM_OF_BUFFER;

    // Set EDMA Event PaRAM SRC/DST BIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].SRC_DST_BIDX =
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, 0u) |
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX, NUM_OF_BYTES_PER_WORD);

    // Set EDMA Event PaRAM SRC/DST CIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].SRC_DST_CIDX =
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, 0u) |
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0u);

    // Set EDMA Event PaRAM LINK and BCNTRLD
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64].LINK_BCNTRLD =
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64] & 0xFFFFu) |
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD, NUM_OF_WORD_PER_BUFFER);
}

void MAT_EDMA_Config_Xmt_ Param(void)
{
//**************   Link to parameter set 1  *******************//
    // Reset EDMA PaRAM OPT Register
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].OPT = CSL_EDMA3CC_OPT_RESETVAL;

    // Config PaRAM OPT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].OPT =
        CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE)    |
        CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE)     |
        CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC) |
        CSL_FMK(EDMA3CC_OPT_TCC, EDMA_EVENT1);

    // Initialize EDMA Event Src and Dst Addresses
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].SRC = (Uint32)&u32_Xmt_Buffer[0u];
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].DST = (Uint32)&mcaspRegs->XBUF11;

    // Set EDMA Event PaRAM A,B,C CNT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].A_B_CNT =
        CSL_FMK(EDMA3CC_A_B_CNT_ACNT, NUM_OF_BYTES_PER_WORD) |           
        CSL_FMK(EDMA3CC_A_B_CNT_BCNT, NUM_OF_WORD_PER_BUFFER);           
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].CCNT = NUM_OF_BUFFER;

    // Set EDMA Event PaRAM SRC/DST BIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].SRC_DST_BIDX =
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, NUM_OF_BYTES_PER_WORD) |
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0u);

    // Set EDMA Event PaRAM SRC/DST CIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].SRC_DST_CIDX =
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, 0) |
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0);

    // Set EDMA Event PaRAM LINK and BCNTRLD
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].LINK_BCNTRLD =
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65] & 0xFFFFu) |
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD, NUM_OF_WORD_PER_BUFFER);

//**************   Link to parameter set 65  *******************//

    // Reset EDMA PaRAM OPT Register
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].OPT = CSL_EDMA3CC_OPT_RESETVAL;

    // Config PaRAM OPT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].OPT =
        CSL_FMKT(EDMA3CC_OPT_ITCINTEN, DISABLE)    |
        CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE)     |
        CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ASYNC) |
        CSL_FMK(EDMA3CC_OPT_TCC, EDMA_EVENT1);

    // Initialize EDMA Event Src and Dst Addresses
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].SRC = (Uint32)&u32_Xmt_Buffer[0u];
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET1].DST = (Uint32)&mcaspRegs->XBUF11;

    // Set EDMA Event PaRAM A,B,C CNT
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].A_B_CNT =
        CSL_FMK(EDMA3CC_A_B_CNT_ACNT, NUM_OF_BYTES_PER_WORD) |           
        CSL_FMK(EDMA3CC_A_B_CNT_BCNT, NUM_OF_WORD_PER_BUFFER);
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].CCNT = NUM_OF_BUFFER;

    // Set EDMA Event PaRAM SRC/DST BIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].SRC_DST_BIDX =
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, NUM_OF_BYTES_PER_WORD) |
        CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0u);

    // Set EDMA Event PaRAM SRC/DST CIDX
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].SRC_DST_CIDX =
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, 0) |
        CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0);

    // Set EDMA Event PaRAM LINK and BCNTRLD
    edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65].LINK_BCNTRLD =
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET65] & 0xFFFFu) |
        CSL_FMK(EDMA3CC_LINK_BCNTRLD_BCNTRLD, NUM_OF_WORD_PER_BUFFER);
}

- At the end, I add the MAT_EDMA_Init() call into the main() routine just after the CodecInit() function call.

I can see both receive and transmit interrupt counters increasing synchonized but unfortunately nothing into the receive buffer when halting the CPU?

I hope someone can tell me what is missing into my code.

Thanks in advance,

Térence

P.S. I also toggle a GPIO into the EDMA3 interrupt receive and transmit event and I can mesure the period which is the codec sampling period multiplies of the by the buffer size!

  • Terence

    Terence HUERTAS said:

    I can see both receive and transmit interrupt counters increasing synchonized but unfortunately nothing into the receive buffer when halting the CPU?

    I hope someone can tell me what is missing into my code.

     

    Just some thoughts - 

     - The EDMA3 event for the the McASP happens after each audio sample (Fs). You buffer appears to be set up to transfer 128 (32 bit words), sso in theory you are attempting to transfer 127 words that do not need to be transferred. It might make sense to change the BCNT to 1, since ACNT is already 4, this way you will be transferring 1 32 bit word per audio sample Rx event.

    - Did you enable the McASP FIFO? If so - you may be attempting to read the audio sample from the wrong register. You may wish to double check the address of your source/destinations to make sure they align with the datasheet memory map. (I assume they do, but it doesn't hurt to double check)

    - Make sure you buffer(s) are located in global memory (Shared RAM, or L2 that is accessible by the both the C674x DSP and the EMDA3.) I believe for Global L2 it starts at address 0x11xxxxxx - but i don't remember off the top of my head. The memory map is in the datasheet.

     

  • Hi Drew,

    Sorry about the late of my reply!

    Drew Abuan said:
     

     - The EDMA3 event for the the McASP happens after each audio sample (Fs). You buffer appears to be set up to transfer 128 (32 bit words), sso in theory you are attempting to transfer 127 words that do not need to be transferred. It might make sense to change the BCNT to 1, since ACNT is already 4, this way you will be transferring 1 32 bit word per audio sample Rx event.

    In fact, I would implement an EDMA ping/pong buffering scheme. As a starting point you're right, I tried with only one sample:

    #define NUM_OF_WORD_PER_BUFFER        1u    // BCNT

    Drew Abuan said:
     

    - Did you enable the McASP FIFO? If so - you may be attempting to read the audio sample from the wrong register. You may wish to double check the address of your source/destinations to make sure they align with the datasheet memory map. (I assume they do, but it doesn't hurt to double check)

    No the McASP FIFO were disabled and I don't want to use them.

    Drew Abuan said:
     

    - Make sure you buffer(s) are located in global memory (Shared RAM, or L2 that is accessible by the both the C674x DSP and the EMDA3.) I believe for Global L2 it starts at address 0x11xxxxxx - but i don't remember off the top of my head. The memory map is in the datasheet.

    I come from the "only one DSP world"! With the OMAP L138, it's the multiprocessor world ;o) And of course I forget to check the memory map! A real beginner error!

    Now I have a CSL EDMA Ping Pong buffering example working on my experimenter kit!

    Many thanks for your quick answer!

    I can provide the Ping Pong Buffer Audio example if someone is interested, or I can send you the code to you Drew maybe to add to the quickStartOMAPL1x_rCSL?

    Best regards,

    Térence

     

     

     

  • Terence,

           Glad to hear you were able to get it working. I made the same mistake when I first started with multi-core processors. It's almost too easy to make.

        Anyways - feel free to zip up up your example and attach to this thread if you wish to share it.

  • Hi

    Could you share your project.

    I am doing something similar

     

    thanks

    izzet