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.

Registering EDMA ISR with DSP core.

Other Parts Discussed in Thread: OMAPL138, OMAP-L138, SYSBIOS

I am writing EDMA driver for OMAPL138 for EDMA 1 with base address 0x01E30000  has given in omap-l138.pdf and I am trying to register ISR for event 91. My code is given below. I am using Channel 0 for transfers . ISR is not being called.

int edma_register_isr(void *isr_func, struct edma_prv_data *pdata)
{
  /* TODO: User is required to define this function */

  Hwi_Params hwiParams;
  Hwi_Handle myHwi;
  Error_Block eb;
  System_printf("Registering ISR\n");
  REGW32(DSP_INTMUX1,(91<<0));
  /* Initialize error block and hwiParams to default values */
  Error_init(&eb);
  Hwi_Params_init(&hwiParams);
  /* Set ISR parameters */
  hwiParams.arg =(unsigned int)pdata ;    /* Set your prvdata structure */
  hwiParams.eventId =91;    /* INT Num*/
  hwiParams.enableInt = FALSE;

  /* Create a Hwi object for interrupt number 91
   * that invokes ISR with argument*/
  myHwi = Hwi_create(4,isr_func, &hwiParams, &eb);
  if (myHwi == NULL) {
    System_abort("Hwi create failed");
  }
  /* enable both interrupts */
  Hwi_enableInterrupt(4);

  return 0;
}

My ISR functions has prints which are not being printed.

I have prints for IPR register before issuing start and after the end of transfer, which shows that the interrupts have occured. (IPR = 1). I have also enabled interrupts by writing 0xffffffff in IESR register.

  • Kartik,

    Please start with the EDMA3_LLD drivers and/or CSL, whichever you have source for and have examples for.

    Have you started from a TI example? If so, which one?

    Regards,
    RandyP
  • I looked at the example in CSL , it doesn't have IRQ number and is looping on ACTV bit in CCSTAT register to indicate completion of transfer and not on ISR.

  • Hi,

    Thanks for your update.

    Are you making use of the EDMA3 LLD examples for creating your DMA transfer set up?

    If you were creating your own example from scratch, here are something to keep in consideration:

    In general, it is simple to have TCC value be equal to the DMA channel number, for example, if you are using DMA channel # 10, you can have OPT.TCC set to 10 too.  To have the EDMA3 CC generate transfer completion interrupts to ARM or DSP interrupt controller, you will need to enable

    1) EDMA3CC.IER (via write to EDMA3.IESR)

    2) Enable the DMA Region Access Enable Register bit corresponding to the TCC value you chose, for the right shadow region. On OMAPL138, if you need to send the EDMA transfer completion interrupt to ARM Interrupt controller , you would need to write to DRAE0 register (Region 0) and if you need to send the EDMA transfer completion interrupt to DSP interrupt controller, you would need to write to DRAE1 register (Region 1) to enable the bit corresponding to the TCC value,

    3) In addition to above, you will need to enable the interrupts appropriately in the DSP or ARM interrupt controller. Note that there is also an IER register in the DSP Interrupt controller.

    In general the above steps (and other initialization steps) are also summarized in the EDMA3 reference guide as below:

    http://www.ti.com/lit/ug/spru234c/spru234c.pdf.

    It would be recommended for you to use the EDMA3 LLD which comes along with the MCSDK. There are several examples which you could try building "as-is" and then study how they work.

    There are also some starter examples in the quickStartOMAP-L1x-rCSL package as below:

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

    There are other EDMA3 LLD basic examples from the pdf doc. below:

    http://processors.wiki.ti.com/images/5/5e/EDMA3_LLD.pdf

    http://processors.wiki.ti.com/index.php/Programming_the_EDMA3_using_the_Low-Level_Driver_%28LLD%29

    Thanks & regards,

    Sivaraj K

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

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

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

  • Thanks Sivaraj for sharing the documents I looked through the EDMA3 LLD and I could see that the code present in it is same as mine. The file sample_omapl138_arm_int_reg.c has this code

    /**  To Register the ISRs with the underlying OS, if required. */
    void registerEdma3Interrupts (unsigned int edma3Id)
        {
        static UInt32 cookie = 0;
        unsigned int numTc = 0;
        Hwi_Params hwiParams; 
            
        /* Disabling the global interrupts */
        cookie = Hwi_disable();
    
        /* Initialize the HWI parameters with user specified values */
        Hwi_Params_init(&hwiParams);
        
        /* argument for the ISR */
        hwiParams.arg = edma3Id;
    	/* set the priority ID     */
    	hwiParams.priority = hwIntXferComp[edma3Id];
        
        hwiCCXferCompInt = Hwi_create( ccXferCompInt[edma3Id][gpp_num],
                    			(&lisrEdma3ComplHandler0),
                    			(const Hwi_Params *) (&hwiParams),
                    			NULL);
        /* Initialize the HWI parameters with user specified values */
        Hwi_Params_init(&hwiParams);
        /* argument for the ISR */
        hwiParams.arg = edma3Id;
    	/* set the priority ID     */
    	hwiParams.priority = hwIntCcErr[edma3Id];
    	
    	hwiCCErrInt = Hwi_create( ccErrorInt[edma3Id],
                    (&lisrEdma3CCErrHandler0),
                    (const Hwi_Params *) (&hwiParams),
                    NULL);
    
        while (numTc < numEdma3Tc[edma3Id])
    	    {
            /* Initialize the HWI parameters with user specified values */
            Hwi_Params_init(&hwiParams);
            /* argument for the ISR */
            hwiParams.arg = edma3Id;
        	/* set the priority ID     */
            hwiParams.priority = hwIntTcErr[edma3Id];
            
            hwiTCErrInt[numTc] = Hwi_create( tcErrorInt[edma3Id][numTc],
                        (ptrEdma3TcIsrHandler[numTc]),
                        (const Hwi_Params *) (&hwiParams),
                        NULL);
            numTc++;
        	}
       /**
        * Enabling the HWI_ID.
        * EDMA3 interrupts (transfer completion, CC error etc.)
        * correspond to different ECM events (SoC specific). These ECM events come
        * under ECM block XXX (handling those specific ECM events). Normally, block
        * 0 handles events 4-31 (events 0-3 are reserved), block 1 handles events
        * 32-63 and so on. This ECM block XXX (or interrupt selection number XXX)
        * is mapped to a specific HWI_INT YYY in the tcf file. So to enable this
        * mapped HWI_INT YYY, one should use the corresponding bitmask in the
        * API C64_enableIER(), in which the YYY bit is SET.
        */
        Hwi_enableInterrupt(hwIntXferComp[edma3Id]);
        Hwi_enableInterrupt(hwIntCcErr[edma3Id]);
        Hwi_enableInterrupt(hwIntTcErr[edma3Id]);
    
        /* Restore interrupts */
        Hwi_restore(cookie);
        }
    

    This code is for registering ISR with ARM , I believe the change for DSP will be the IRQ no . I am using IRQ no as 91 and using almost the same code , but I still wont get my ISR called.

  • I did a bit more debugging this time with DMA0 , I ve made proper changes to base address and the IRQ no is now 8. I am using channel #0 for a manually triggered event . I did a print from Event Flag Registers  (EVTFLAGn) and in (EVTFLAG0) I could see that bit 8 EF8 has been set but still my ISR function was not called. I am using this code to register ISR and IRQ_NO is 8.

    int edma_register_isr(void *isr_func, struct edma_prv_data *pdata)
    {
      /* TODO: User is required to define this function */
    
      Hwi_Params hwiParams;
      Hwi_Handle myHwi;
      Error_Block eb;
      System_printf("Registering ISR\n");
      System_printf("-->Event Flag0 = %x\n",REGR32(DSP_EVTFLAG0));
      System_printf("-->Event Mask0 = %x\n",REGR32(DSP_EVTMASK0));
      REGW32(DSP_INTMUX1,(IRQ_NO<<0)); //Should be IRQ_NO
      /* Initialize error block and hwiParams to default values */
      Error_init(&eb);
      Hwi_Params_init(&hwiParams);
      /* Set ISR parameters */
      hwiParams.arg =(unsigned int)pdata ;    /* Set your prvdata structure */
      //hwiParams.eventId =IRQ_NO;    /* INT Num*/
      hwiParams.enableInt = FALSE;
      //hwiParams.priority = 0x22;
      /* Create a Hwi object for interrupt number IRQ_NO
       * that invokes ISR with argument*/
      myHwi = Hwi_create(4,isr_func, &hwiParams, &eb);
    
      if (myHwi == NULL) {
        System_abort("Hwi create failed");
      }
      /* enable both interrupts */
      Hwi_enableInterrupt(4);
    
      return 0;
    }

    The mask register is 0xf.

  • Hi Karthick,

    The problem you are facing seems similar to sysbios and EDMA, where there is a while loop in the main which is obstructing the task scheduler of sysbios. Please look into it if it helps.

    All the best :)

  • Hi Abhijit,
    The link helped, I did not have a Task_create(); & BIOS_start(); in my code , in main() my code was waiting for a variable to be set in a while() loop which had to be set by ISR. After adding those the code started to work.