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 transfer problem (from EMIFA)

Other Parts Discussed in Thread: OMAP-L138

Hi all!

We are developing system which transfer data from EMIFA bus to I2S.

Our hardware:
LogicPD OMAP-L138 module, which is connected to FPGA over EMIFA bus (16 bit)
I2S bus connected to hardware which send and receive data to/from OMAP.

Software solution:
dev tool: CCS 3.3 + DSP/BIOS (but task manager is switched off)

I2S frame sync frequency 96kHz. We are using for transmitting/receiving data both of edges I2S FrameSync, 4 serializes for TX and 4 for RX. In this case total size  = 4 serializes  * 2 channels * 4 bytes (i2s channel size) = 32 bytes.

After each full Frame Sync we have TX and RX IRQ, in IRQ we fill buffer for next transfer

For I2S we use CSL with EDMA3 LLD library.  

Also, FPGA toggles GPIO 16,000 times per second (FPGA ND_INT). EDMA hardware channel connected to this GPIO and after GPIO event happends, EDMA starts to read from EMIFA 40 bytes automatically. (You can see that at screen shot). After transfer complete, transfer complete IRQ happed (FPGA EDMA callback).

But, strange thing is delay between real completion time and time when IRQ routine called.

Next strange thing, that EDMA reading from EMIFA bus holds all EDMA completion IRQs.  (see FPGA MEMREAD and I2S TX callback).

Can anybody helps us? How we can solve this problems?

 

,

 

  • First of all, thanks for the detailed description. It's way easier to help out when you provide level of detail that is needed for debug.

    SimpleSoft said:
    But, strange thing is delay between real completion time and time when IRQ routine called.

    I assume the IRQ you are referring to the is the IRQ from the completion of the EDMA3 Transfer (FPGA EDMA callback). Or are you referring to the I2S Tx/Rx IRQ?

    I assume that you would like to see the I2S Traffic on the next I2S frame immediately adjacent to the I2S frame in which the data is read from FPGA? Correct me if I'm wrong.

     

     

  • thanks for fast response

    yes, you are right, i mean FPGA EDMA callback.

    and also need to fix situation, that when we read from EMIFA over EDMA, other IRQs (like TX/RX I2S) cannot be happend. (while read not complete).

  • Ok.

      EDMA3 can be a bit tricky to debug sometimes. Internal to the OMAP-L138, I assume you have configured the Transfer Completion Code (TCC) of the EDMA to generate an Interrupt when it is complete. Is that what you are showing on your capture? Is (FPGA EMDA callback) a GPIO toggle when the interrupt occurs?

     

     

  • yes, its a GPIO.

    callback code:

     

    void EMDA_GPIO_FPGA_RX_callback (unsigned int tcc, EDMA3_RM_TccStatus status,

                            void *appData)

    {

    Uint32 timestamp;


    (void)tcc;

        (void)appData;



        switch (status)

        {

            case EDMA3_RM_XFER_COMPLETE:

    TestPinB0(8,1);


    TestPinB0(8,0);

      

                break;


            case EDMA3_RM_E_CC_DMA_EVT_MISS:

                break;


            case EDMA3_RM_E_CC_QDMA_EVT_MISS:

                break;


            default:

                break;

        }


    }

    code:

     

    void EMIFA_Init_EDMA_GPIO_Transfer( void* Dst )

    {

    unsigned int acnt = FPGA_EDMA_TRANSFER_LENGTH;

        unsigned int bcnt = 1u;

        unsigned int ccnt = 1u;

        EDMA3_DRV_Result result = EDMA3_DRV_SOK;

        unsigned int tcc = 0;

        int i;

        unsigned int numenabled = 0;

        unsigned int BRCnt = 0;

        int srcbidx = 0, desbidx = 0;

        int srccidx = 0, descidx = 0;


        /* Set B count reload as B count. */

        BRCnt = bcnt;


        /* Setting up the SRC/DES Index */

        srcbidx = (int)acnt;

        desbidx = (int)acnt;

        /* A Sync Transfer Mode */

        srccidx = (int)acnt;

        descidx = (int)acnt;


    /* for GPIO event */

        tcc = EDMA3_DRV_HW_CHANNEL_EVENT_22;

        chIFPGA_RX = EDMA3_DRV_HW_CHANNEL_EVENT_22;


        /* Request any DMA channel and any TCC */

        if (result == EDMA3_DRV_SOK)

            {

            result = EDMA3_DRV_requestChannel ( hEdma[0], &chIFPGA_RX, &tcc,

                                                (EDMA3_RM_EventQueue)1,

                                                &EMDA_GPIO_FPGA_RX_callback, NULL);

            }


        if (result == EDMA3_DRV_SOK)

            {


            /* Fill the PaRAM Set with transfer specific information */

            paramSetFPGA_RX.srcAddr    = (unsigned int)(0x60000000);

            paramSetFPGA_RX.destAddr   = (unsigned int)(Dst);


            /**

             * Be Careful !!!

             * Valid values for SRCBIDX/DSTBIDX are between –32768 and 32767

             * Valid values for SRCCIDX/DSTCIDX are between –32768 and 32767

             */

            paramSetFPGA_RX.srcBIdx    = 0;

            paramSetFPGA_RX.destBIdx   = 0;

            paramSetFPGA_RX.srcCIdx    = 0;

            paramSetFPGA_RX.destCIdx   = 0;

     

            paramSetFPGA_RX.aCnt       = acnt;

            paramSetFPGA_RX.bCnt       = bcnt;

            paramSetFPGA_RX.cCnt       = ccnt;


            /* For AB-synchronized transfers, BCNTRLD is not used. */

            paramSetFPGA_RX.bCntReload = BRCnt;


            paramSetFPGA_RX.linkAddr   = 0xffffu;


            /* Src and Dst is in INC modes */

            paramSetFPGA_RX.opt &= 0xFFFFFFFCu;

            /* Program the TCC */

            paramSetFPGA_RX.opt |= ((tcc << OPT_TCC_SHIFT) & OPT_TCC_MASK);


            /* Enable Intermediate & Final transfer completion interrupt */

    paramSetFPGA_RX.opt &= 0xFFCFFFFF;


            paramSetFPGA_RX.opt |= (1 << OPT_TCINTEN_SHIFT);


            paramSetFPGA_RX.opt &= 0xFFFFF8FBu;


    /* Static PaRAM */

    paramSetFPGA_RX.opt |= 0x08u;

    /* FIFO 16bit */

    paramSetFPGA_RX.opt |= 0x0100u;



            /* Now, write the PaRAM Set. */

            result = EDMA3_DRV_setPaRAM(hEdma[0], chIFPGA_RX, &paramSetFPGA_RX);

            }


        /*

         * Since the transfer is going to happen in Manual mode of EDMA3

         * operation, we have to 'Enable the Transfer' multiple times.

         * Number of times depends upon the Mode (A/AB Sync)

         * and the different counts.

         */

        if (result == EDMA3_DRV_SOK)

            {

            /*Need to activate next param*/

            numenabled = bcnt * ccnt;

            for (i = 0; i < numenabled; i++)

                {

                /*

                 * Now enable the transfer as many times as calculated above.

                 */

                result = EDMA3_DRV_enableTransfer (hEdma[0], chIFPGA_RX,

                                                    EDMA3_DRV_TRIG_MODE_EVENT);

                if (result != EDMA3_DRV_SOK)

                    {

                    break;

                    }

    }

    }

    }

     

  • Difficult to determine where is something is going wrong based upon your software. Is it possible that the IRQ is being delayed by something with higher precedence, but I don't have much insight on this since you are the expert at the code.

    I would recommend to save a snapshot of what you have, then start removing various levels of the code until you can determine where the delay is occurring. The first think I'd remove is the the servicing of the I2S interrupts in the CPU. Then continue to remove all the other interrupts to see if something doesn't change with regards to the timing. There might be some delay in the EMDA3 Low Level Drivers themselves, however I've always programmed the EDMA3 at the register level, and have subsequently never used the LLDs.

  • Thank you, Drew!

    I will try to do you recommendations, and that I will write result.

  • In code only 3 IRQs: I2S TX EDMA end, I2S RX EDMA end, EMIFA EDMA end.

    I do another screenshot with 128 bytes read. In this screenshot good to view how to EMIFA delays all other IRQs.

    I try to change priority of EDMA in Master Priority Registers (SYSCFG), but it not helps.

     

    Please, check this:

    but when i disable EMIFA EDMA routine - result is perfect:

    Whats wrong....

  • SimpleSoft said:


        /* Request any DMA channel and any TCC */

        if (result == EDMA3_DRV_SOK)

            {

            result = EDMA3_DRV_requestChannel ( hEdma[0], &chIFPGA_RX, &tcc,

                                                (EDMA3_RM_EventQueue)1,

                                                &EMDA_GPIO_FPGA_RX_callback, NULL);

            }

    Is the I2S RX/TX DMA channels sharing the same CC Queue, as the EMIFA/FPGA transfers, if so, please make sure you put the I2S transfers on a separate queue, and make the priority of that queue-TC higher then then one on which EMIFA transfers are being submitted (Q0 maps to TC0 , Q1 maps to TC1)

    What memory is being used for FPGA/EMIFA buffers and what memory location is being used for I2S buffers? If they share the same memory location (e.g both are on Shared RAM/IRAM), then please try moving buffers for one in another memory location to see if it helps.

    Regards

    Mukul

     

  • Mukul Bhatnagar said:

    Is the I2S RX/TX DMA channels sharing the same CC Queue, as the EMIFA/FPGA transfers, if so, please make sure you put the I2S transfers on a separate queue, and make the priority of that queue-TC higher then then one on which EMIFA transfers are being submitted (Q0 maps to TC0 , Q1 maps to TC1)

    What do you mean? I try this code:

     

            result = EDMA3_DRV_requestChannel ( hEdma[0], (unsigned int *)&chIdMcASP_TX, &tcc,

                                                (EDMA3_RM_EventQueue)0,

                                                &EMDA_McASP_TX_callback, NULL);

    ....

     

            result = EDMA3_DRV_requestChannel ( hEdma[0], (unsigned int *)&chIdMcASP_RX, &tcc,

                                                (EDMA3_RM_EventQueue)0,

                                                &EMDA_McASP_RX_callback, NULL);

    ...

     

            result = EDMA3_DRV_requestChannel ( hEdma[0], (unsigned int *)&chIFPGA_RX, &tcc,

                                                (EDMA3_RM_EventQueue)1,

                                                &EMDA_GPIO_FPGA_RX_callback, NULL);

     

    ...

     

    CSL_SyscfgRegsOvly syscfgRegs  = (CSL_SyscfgRegsOvly)CSL_SYSCFG_0_REGS;

     

    System_KickUnlock();

    syscfgRegs->MSTPRI1 &= (~0x77700);

    syscfgRegs->MSTPRI1 |= ( 0x00100);


    Mukul Bhatnagar said:

    What memory is being used for FPGA/EMIFA buffers and what memory location is being used for I2S buffers? If they share the same memory location (e.g both are on Shared RAM/IRAM), then please try moving buffers for one in another memory location to see if it helps.

     

    #pragma DATA_SECTION(dwEMIFA_Recv,"DDR");

    Uint16 dwEMIFA_Recv[128];

     

    After this code - nothing changes. I have same problem. Also i move buffer for EMIFA to SDRAM, I2S buffers to IRAM - but problem persists.


     

     

     

     

  • I did AB-transfer (early it be A-transfer) with A = 2. The situation became a bit better, but not a problem hasn't solved.

  • From the above screen shot, the McASP Rx/Tx Callback functions do not seem to be run until after the EMIF read, and are both called soon after the  EMIF transfer is complete. This seems to point to the fact that the EMIF EDMA3 transfer & the McASP EDMA3 transfers are on the same queue (even though I see the code initializes the McASP Tx/Rx to queue 0 and EMIF to queue 1).

     

    Can you verify (using the emulator) to read the DMA Queue Number Registers (DMAQNUM) to verify that the McASP Events are queue'd in queue 0 and EMIF is queue'd in queue 1 after you have accessed the resources using the EDMA3 LLDs. (You could set up a break point to halt the CPU after the EMDA_DRV_requestChannel functions return).

    Another debug option is to move the EMIF transfers to the second EDMA3 instance on the device (EDMA3_1). This way you will serve the McASP Rx/Tx events on EDMA3_0 and the EMIF events on EDMA3_1.