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.

OMAP-l138 EDMA+McASP no interrupts

Other Parts Discussed in Thread: OMAP-L138, OMAPL138

Hi guys,

I'm using omap-l138 LCDK and the only thing I'd like to do is to setup EDMA for audio data transfers.

I have no problems setting McASP in interrupt driven mode, when my handler process a sample by sample. But it's not a clear solution. Please have a look at code I'm using - this is my try for ping-pong EDMA transfers:

This is a way I setup McASP :

void L138_initialise_edma(int32_t fs, int16_t adc_gain, int16_t dac_atten, int8_t input_type)
{
  // allocate memory for ping pong buffers
  pingOUT = (int16_t *)malloc(BUFCOUNT*sizeof(int16_t));
  pongOUT = (int16_t *)malloc(BUFCOUNT*sizeof(int16_t));
  pingIN = (int16_t *)malloc(BUFCOUNT*sizeof(int16_t));
  pongIN = (int16_t *)malloc(BUFCOUNT*sizeof(int16_t));

  USTIMER_init();

  EVMOMAPL138_lpscTransition(PSC1, DOMAIN0, LPSC_MCASP0, PSC_ENABLE);
  EVMOMAPL138_pinmuxConfig(PINMUX_MCASP_REG_0, PINMUX_MCASP_MASK_0, PINMUX_MCASP_VAL_0);
  EVMOMAPL138_pinmuxConfig(PINMUX_MCASP_REG_1, PINMUX_MCASP_MASK_1, PINMUX_MCASP_VAL_1);

  // replaces I2C_init();
  *( volatile uint32_t* )(0x01C22024) = 0;
  *( volatile uint32_t* )(0x01C22030) = 2;
  *( volatile uint32_t* )(0x01C2200C) = 5;
  *( volatile uint32_t* )(0x01C22010) = 5;
  *( volatile uint32_t* )(0x01C22024) |= 0x20;
 
  CSR = 0x0000; // disable interrupts globally while initialising
                // GIE is bit 0 of CSR register

  L138_init_aic3106_registers(fs, adc_gain, dac_atten,input_type);

  L138_init_mcasp_edma();

  // clear any pending interrupts within EDMA3CC
  EDMA_3CC_ICR = 0x0007; // writing to ICR affects IPR
  // associate event n with interrupt 4 by writing n into LSBs of INTMUX1
  // LSBs of INTMUX1 are literally associated with INT4
  // in this case n=8 (EDMA3CC   event)
  INTC_INTMUX1 = 0x00000008;

  ISTP = (unsigned int)vectors;
  // enable TCC = 0 and TCC = 1 EDMA3 interrupts by setting bits 0 and 1 in IESR
  EDMA3_IESR = 0x0003;
  EDMA3_DRAE1 = 0x0003;

  // clear all pending interrupt flags
  // interrupt clear register ICR is used to clear bits in interrupt flag register IFR
  ICR = 0xFFF0;  // ICR bits 3, 2, 1, and 0 are reserved, read as 0, write has no effect
  IER |= 0x12;  //enable NMI (bit 1) and INT4 (bit 4)
 
  CSR |= 0x01;  // enable interrupts globally
  L138_init_LCDK_DIP();

}

And this is how I set EDMA PaRAM to handle serializers 13 and 14 respectively :

void EDMA3_PaRAM_setup() // sets up PaRAM and enables EDMA events
{
uint32_t *EDMA3_PaRAM_ptr;
// PaRAM sets (channels) 0 and 1, triggered by McASP0
// receive and transmit events respectively, are used
// with linked parameters set up in PaRAM sets (channels) 64, 65, 67, and 68
// the linked parameters differ only in the ping or pong buffers used

// set up PaRAM set 1 (MCASP0 XEVT)

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04020);

*EDMA3_PaRAM_ptr++ = 0x00000000; // no EDMA3 interrupts on transfer complete
*EDMA3_PaRAM_ptr++ = (unsigned int)pingOUT; // source is one of two output buffers
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
 // BCNT = BUFCOUNT/2(arrays per frame), ACNT = 4(bytes per array) writing to a (32-bit) McASP0 serialiser
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x234; // destination is DMA port of McASP0
*EDMA3_PaRAM_ptr++ = 0x00000004; // dest address is static, increment source address by ACNT bytes
*EDMA3_PaRAM_ptr++ = 0x00000800; // BCNT reload value is redundant - link to PaRAM set 64
*EDMA3_PaRAM_ptr++ = 0x00000000; // CCNTIDX
*EDMA3_PaRAM_ptr++ = 0x00000001; // rsvd, CCNT = 1(frame per block)

// set up PaRAM set 64

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04800);

*EDMA3_PaRAM_ptr++ = 0x00000000; // same as PaRAM set 1
*EDMA3_PaRAM_ptr++ = (unsigned int)pongOUT; // apart from source buffer used
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x234;
*EDMA3_PaRAM_ptr++ = 0x00000004;
*EDMA3_PaRAM_ptr++ = 0x00000820; // BCNT reload value is redundant - link to PaRAM set 65
*EDMA3_PaRAM_ptr++ = 0x00000000;  
*EDMA3_PaRAM_ptr++ = 0x00000001;

// set up PaRAM set 65

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04820);

*EDMA3_PaRAM_ptr++ = 0x00000000; // exactly the same as PaRAM set 1
*EDMA3_PaRAM_ptr++ = (unsigned int)pingOUT;
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x234;
*EDMA3_PaRAM_ptr++ = 0x00000004;
*EDMA3_PaRAM_ptr++ = 0x00000800; // BCNT reload value is redundant - link to PaRAM set 64
*EDMA3_PaRAM_ptr++ = 0x00000000;  
*EDMA3_PaRAM_ptr++ = 0x00000001;


// set up PaRAM set 0 (MCASP0 REVT)

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04000);

*EDMA3_PaRAM_ptr++ = 0x00100000; // OPT interrupt on transfer complete with TCC = 0
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x2B8; // SRC DMA port of McASP0
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
*EDMA3_PaRAM_ptr++ = (unsigned int)pingIN; // DST one of two output buffers
*EDMA3_PaRAM_ptr++ = 0x00040000; // DSTBIDX, SRCBIDX increment dest by 4 bytes, src is static
*EDMA3_PaRAM_ptr++ = 0x00000860; // BCNT reload value is redundant - link to PaRAM set 67
*EDMA3_PaRAM_ptr++ = 0x00000000; //
*EDMA3_PaRAM_ptr++ = 0x00000001; // rsvd, CCNT 1 frame per block

// set up parameter RAM set 67

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04860);

*EDMA3_PaRAM_ptr++ = 0x00101000; // OPT similar to PaRAM set 1 but TCC = 1 and different buffer used
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x2B8;    // SRC
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
*EDMA3_PaRAM_ptr++ = (unsigned int)pongIN; // DST - single address used for XBUFn, RBUFn if RBSEL = 0
*EDMA3_PaRAM_ptr++ = 0x00040000; // DSTBIDX, SRCBIDX
*EDMA3_PaRAM_ptr++ = 0x00000880; // BCNT reload value is redundant - link to PaRAM set 68
*EDMA3_PaRAM_ptr++ = 0x00000000; //
*EDMA3_PaRAM_ptr++ = 0x00000001; // rsvd, CCNT

// set up parameter RAM set 68

EDMA3_PaRAM_ptr = (unsigned int *)(0x01C04880); // exactly the same as PaRAM set 1

*EDMA3_PaRAM_ptr++ = 0x00100000; // OPT
*EDMA3_PaRAM_ptr++ = 0x01D02000 + 0x2B8;    // SRC
*EDMA3_PaRAM_ptr++ = (int32_t)((((BUFCOUNT/2)<<16) & 0xFFFF0000) | 0x00000004);
*EDMA3_PaRAM_ptr++ = (unsigned int)pingIN; // DST - single address used for XBUFn, RBUFn if RBSEL = 0
*EDMA3_PaRAM_ptr++ = 0x00040000; // DSTBIDX, SRCBIDX
*EDMA3_PaRAM_ptr++ = 0x00000860; // BCNT reload value is redundant - link to PaRAM set 67
*EDMA3_PaRAM_ptr++ = 0x00000000; //
*EDMA3_PaRAM_ptr++ = 0x00000001; // rsvd, CCNT


  EDMA_3CC_IECRH  = 0xffffffff;   // IERH - Disable high interrupts
  EDMA_3CC_EECRH  = 0xffffffff;   // EERH - Disable high events
  EDMA_3CC_ICRH   = 0xffffffff;   // ICRH - Clear high interrupts
  EDMA_3CC_ECRH   = 0xffffffff;   // ICRH - Clear high events

  EDMA_3CC_IECR   = 0xffffffff;   // IER  - Disable low interrupts
  EDMA_3CC_EECR   = 0xffffffff;   // EER  - Disable low events
  EDMA_3CC_ICR    = 0xffffffff;   // ICR  - Clear low interrupts
  EDMA_3CC_ECR    = 0xffffffff;   // ICRH - Clear low events


EDMA_3CC_EESR = 0x00000003; // enable EDMA3 events 0 and 1, i.e. McASP REVT and XEVT
}

And finally I have the following interrupt handler :

interrupt void interrupt4(void) // interrupt service routine
{
 switch(EDMA_3CC_IPR)
  {
    case 1:                     // TCC = 0
      procBuffer = PING;        // process ping
      EDMA_3CC_ICR = 0x0001;    // clear EDMA3 IPR bit TCC
      break;
    case 2:                     // TCC = 1
      procBuffer = PONG;        // process pong
      EDMA_3CC_ICR = 0x0002;    // clear EDMA3 IPR bit TCC
      break;
    default:                    // may have missed an interrupt
      EDMA_3CC_ICR = 0x0003;    // clear EDMA3 IPR bits 0 and 1
      break;
  }
  EVTCLR0 = 0x00000100;
  buffer_full = 1;              // flag EDMA3 transfer
  return;
}

But I see that it has never been invoked !

Please help me as I'm running out of ideas what could go wrong -the setup seems to be very easy but nothing works. Maybe my eyes are soaped...

Looking forward for any comments

Kindest Regards,

Dmitry

  • Hi Dimitry,

    Thanks for your post.

    To generate DMA Tx/Rx events, first you need to make sure, whether the transmit/receive data ready flag (XDATA/RDATA) bit is set in transmit/receive status registers (XSTAT/RSTAT) as well in transmit/receive interrupt control registers (XINTCTL/RINTCTL).

    If XDATA/RDATA interrupt is set, an DMA transmit/receive events (AXEVT/AREVT) are automatically generated to notify the DMA of the XBUF/RBUF empty status and obviously, an transmit/receive interrupts (AXINT/ARINT) are also generated if XDATA/RDATA interrupts are enabled in the XINTCTL/RINTCTL registers respectively.

    If DMA is used to service the McASP, the DMA automatically services the McASP upon receiving AXEVT/AREVT. So, Please make sure, the above interrupts and events are set correctly in your code. Also, you shall enable error interrupt flags (Overrun, underrun, clock failure, DMA error, unexpected framesync) to detect error conditions & trigger error interrupts. Please refer Section 25.2.4.6.3 in the TRM.

    Please refer Section 25.2.4.1.2 in the TRM to follow the steps to properly configure the McASP transmit/receive section initialization. Also, please see sections 25.2.4.3.1.1, 25.2.4.3.2, 25.3.20, 25.3.21, 25.3.32 & 25.3.33 respectively.

    OMAPL138 TRM: http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf

    Thanks &regards,

    Sivaraj K

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

     

  • Hi Sivaraj,

    Thanks for the feedback. According to your notes, I've checked the mentioned registers :

    MCASP->RINTCTL    = 0x00000020;

    MCASP->XINTCTL    = 0x00000020;

    So the interrupts are enabled. Then I have the following loop to check XSTAT:

    while ( ( MCASP->XSTAT & 0x00000020 ) != 0x00000000 );

    which is passed successfully. So I don't see any issues regarding these settings. But I still see no interrupts and no data in my ping-pong buffres.

    What could go wrong? Do I use the correct RX/TX McASP address :

    *EDMA3_PaRAM_ptr++ = 0x01D02000; // SRC DMA port of McASP0

    Do you have any tested code snippet for EDMA+McASP on Omap-l138 LCDK? I don't want to setup PSP package because my task is an easy one and must be resolved without any additional overhead.

    Looking fwd to any ideas/help from your side..

    Thx and BR,

    Dmitry