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.

DMA Events for I2S port 2 are missing in action

Other Parts Discussed in Thread: TMS320C5515

I have an embedded application that uses a TMS320C5515.

I make use of I2S port 2 which will be configured as an I2S slave and the parallel port is configured for mode 1 (yields one SPI port, one I2S port (I2S port 2) one UART port and six general purpose IO ports).

When I associate DMA controller 1 to support the I2S port 2 I never see any DMA events being triggered.

I have attempted to use a simple loop back test and I see nothing being transferred from the source buffer to the destination buffer. I have verified that the I2S2_CLK and I2S2_FS clocks are provided by the external I2S master (these clocks are visible at the N10 and P11 at the TMS320C5515).

Has anyone made use of an I2S slave on port 2 and have you been able to make use of DMA Controller 1 to facilitate the transfer of data from the I2S logic to internal data buffers?

Thanks for the help....

                                          David

  • David,

    It sounds that you did everything correctly. Yes, you should be able to use DMA1 for I2S2 port. Please check following things.

    1) How did you check the DMA event? First of all, please enable I2S2 port only (DMA is disabled) and check if you get I2S receive interrupt.

    2) If you get the I2S receive interrupt, then configure DMA2 to take the event

    3) Make sure you enalbe the appropriate interrupt source. (Peripheral level, CPU level, and Global interrupt enable).

    Let me know how it goes.

     

    Best Regards,

    Peter Chung

     

     

     

  • Hello Peter,

    My test setup is as follows:

    (1) Create four arrays named I2SleftTx, I2SRightTx, I2SLeftRx and I2SRightRx, each array is 128 long words.

    (2) Use four DMA channels associated with DMA controller 1 (Channels 4,5,6 and 7).

    (3) DMA Channel 4 is bound to the I2SLeftTx array and it is configured to transfer the 32 bit data from memory to the I2S LT0 and LT1 registers (mapped at address 0x2A08.

    (4) DMA Channel 5 is bound to the I2SRightTx array and is configured to transfer the 32 bits of data from the array to the RT0 and RT1 registers at address 0x2A0C).

    (5) DMA Channel 6 is bound to the I2SLeftRx array and it is configured to transfer the LR0 and LR1 registers (mapped at address 0x2A28) to the array.

    (6) DMA Channel 7 is bound to the I2SRightRx array and it is configured to transfer the receive data received at RR0 and RR1 registers (mapped at locations 0x2A2C).

    The code makes extensive use of the Chip Support Library functions and I based it on one of the examples provided in the library called CSL_I2S_DMAExample. Note that I can not use this routine because the pin mapping that I use requires me to set the EBSR register differently from the example.

    Here is the code that I use......

            my_ebsr = CSL_SYSCTRL_REGS->EBSR;
            printf("%s%x%s","The EBSR value sampled in function I2S = ",my_ebsr," ! \n");
       
        /** Open the device with instance 2                            */
        hI2s = I2S_open(I2S_INSTANCE2, DMA_POLLED, I2S_CHAN_STEREO);
        if(NULL == hI2s)
        {
            status = CSL_TEST_FAILED;
        }
        else
        {
            printf ("I2S Module Instance 2 opened successfully\n");
        }

        /** Set the value for the configure structure                */
        hwConfig.dataType             = I2S_STEREO_ENABLE;
        hwConfig.loopBackMode         = I2S_LOOPBACK_ENABLE; // Loopback to test the setup
        hwConfig.fsPol                 = I2S_FSPOL_LOW;
        hwConfig.clkPol                = I2S_FALLING_EDGE;
        hwConfig.datadelay            = I2S_DATADELAY_ONEBIT;
        hwConfig.datapack            = I2S_DATAPACK_DISABLE;
        hwConfig.signext            = I2S_SIGNEXT_DISABLE;
        hwConfig.wordLen            = I2S_WORDLEN_24;
        hwConfig.i2sMode            = I2S_SLAVE;
        hwConfig.dataFormat         = I2S_DATAFORMAT_LJUST;
        hwConfig.clkDiv                = I2S_CLKDIV4; // Dont care for SLAVE MODE
        hwConfig.fsDiv                = I2S_FSDIV32; // Dont care for SLAVE MODE
        hwConfig.FError                = I2S_FSERROR_DISABLE;
        hwConfig.OuError            = I2S_OUERROR_DISABLE;

        /** Configure hardware registers                            */
        result = I2S_setup(hI2s, &hwConfig);
        if(result != CSL_SOK)
        {
            status = CSL_TEST_FAILED;
        }
        else
        {
            printf ("I2S Module Configured successfully\n");
        }
       
        /* Configure DMA channel  for I2S write */
    #if (defined(CHIP_C5505_C5515) || defined(CHIP_C5504_C5514))
        dmaConfigI2S.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
    #endif
        dmaConfigI2S.autoMode     = CSL_DMA_AUTORELOAD_DISABLE;
        dmaConfigI2S.burstLen     = CSL_DMA_TXBURST_1WORD;
        dmaConfigI2S.trigger      = CSL_DMA_EVENT_TRIGGER;
        dmaConfigI2S.dmaEvt       = CSL_DMA_EVT_I2S2_TX;
        dmaConfigI2S.dmaInt       = CSL_DMA_INTERRUPT_DISABLE;
        dmaConfigI2S.chanDir      = CSL_DMA_WRITE;
        dmaConfigI2S.trfType      = CSL_DMA_TRANSFER_IO_MEMORY;
        dmaConfigI2S.dataLen      = 512;
        dmaConfigI2S.srcAddr      = (Uint32)i2sDmaWriteLeftBuff;
        dmaConfigI2S.destAddr     = (Uint32)(0x2A08); // I2S2 Tx Left Channel register
       
        dmaLeftTxHandle = CSL_configDmaForI2s(CSL_DMA_CHAN4);   
        if(dmaLeftTxHandle == NULL)
        {
            printf("DMA Config for I2S Write Failed!\n!");
        }

        I2S_transEnable(hI2s, TRUE);

        status = DMA_start(dmaLeftTxHandle);
        if(status != CSL_SOK)
        {
            printf("I2S Dma Write Failed!!\n");
        }
        while(DMA_getStatus(dmaLeftTxHandle));

        /* Configure DMA channel  for I2S write */
    #if (defined(CHIP_C5505_C5515) || defined(CHIP_C5504_C5514))
        dmaConfigI2S.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
    #endif
        dmaConfigI2S.autoMode     = CSL_DMA_AUTORELOAD_DISABLE;
        dmaConfigI2S.burstLen     = CSL_DMA_TXBURST_1WORD;
        dmaConfigI2S.trigger      = CSL_DMA_EVENT_TRIGGER;
        dmaConfigI2S.dmaEvt       = CSL_DMA_EVT_I2S2_TX;
        dmaConfigI2S.dmaInt       = CSL_DMA_INTERRUPT_DISABLE;
        dmaConfigI2S.chanDir      = CSL_DMA_WRITE;
        dmaConfigI2S.trfType      = CSL_DMA_TRANSFER_IO_MEMORY;
        dmaConfigI2S.dataLen      = 512;
        dmaConfigI2S.srcAddr      = (Uint32)i2sDmaWriteRightBuff;
        dmaConfigI2S.destAddr     = (Uint32)(0x2A0C); // I2S2 Tx Right Channel register
       

            dmaRightTxHandle = CSL_configDmaForI2s(CSL_DMA_CHAN5);
        if(dmaRightTxHandle == NULL)
        {
            printf("DMA Config for I2S Write Failed!\n!");
        }

        I2S_transEnable(hI2s, TRUE);

        status = DMA_start(dmaRightTxHandle);
        if(status != CSL_SOK)
        {
            printf("I2S Dma Write Failed!!\n");
        }
        while(DMA_getStatus(dmaRightTxHandle));

        /* Configure DMA channel  for I2S Read */
    #if (defined(CHIP_C5505_C5515) || defined(CHIP_C5504_C5514))
        dmaConfigI2S.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
    #endif
        dmaConfigI2S.autoMode     = CSL_DMA_AUTORELOAD_DISABLE;
        dmaConfigI2S.burstLen     = CSL_DMA_TXBURST_1WORD;
        dmaConfigI2S.trigger      = CSL_DMA_EVENT_TRIGGER;
        dmaConfigI2S.dmaEvt       = CSL_DMA_EVT_I2S2_RX;
        dmaConfigI2S.dmaInt       = CSL_DMA_INTERRUPT_DISABLE;
        dmaConfigI2S.chanDir      = CSL_DMA_READ;
        dmaConfigI2S.trfType      = CSL_DMA_TRANSFER_IO_MEMORY;
        dmaConfigI2S.dataLen      = 512;
        dmaConfigI2S.srcAddr      = (Uint32)(0x2A28); // I2S2 Receive Left Channel
        dmaConfigI2S.destAddr     = (Uint32)i2sDmaReadLeftBuff;
       

        dmaLeftRxHandle = CSL_configDmaForI2s(CSL_DMA_CHAN6);   
       
        if(dmaLeftRxHandle == NULL)
        {
            printf("DMA Config for I2S Read Failed!\n!");
        }

        status = DMA_start(dmaLeftRxHandle);
        if(status != CSL_SOK)
        {
            printf("I2S Dma Read Failed!!\n");
        }
        while(DMA_getStatus(dmaLeftRxHandle));

        /* Configure DMA channel  for I2S Read */
    #if (defined(CHIP_C5505_C5515) || defined(CHIP_C5504_C5514))
        dmaConfigI2S.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
    #endif
        dmaConfigI2S.autoMode     = CSL_DMA_AUTORELOAD_DISABLE;
        dmaConfigI2S.burstLen     = CSL_DMA_TXBURST_1WORD;
        dmaConfigI2S.trigger      = CSL_DMA_EVENT_TRIGGER;
        dmaConfigI2S.dmaEvt       = CSL_DMA_EVT_I2S2_RX;
        dmaConfigI2S.dmaInt       = CSL_DMA_INTERRUPT_DISABLE;
        dmaConfigI2S.chanDir      = CSL_DMA_READ;
        dmaConfigI2S.trfType      = CSL_DMA_TRANSFER_IO_MEMORY;
        dmaConfigI2S.dataLen      = 512;
        dmaConfigI2S.srcAddr      = (Uint32)(0x2A2C); // I2S2 Receive Right Channel
        dmaConfigI2S.destAddr     = (Uint32)i2sDmaReadRightBuff;
       

        dmaRightRxHandle = CSL_configDmaForI2s(CSL_DMA_CHAN7);   
        if(dmaRightRxHandle == NULL)
        {
            printf("DMA Config for I2S Read Failed!\n!");
        }

        I2S_transEnable(hI2s, TRUE);

        status = DMA_start(dmaRightRxHandle);
        if(status != CSL_SOK)
        {
            printf("I2S Dma Read Failed!!\n");
        }
        while(DMA_getStatus(dmaRightRxHandle));



        /** Close the operation                                        */
        result = I2S_close(hI2s);

    I know that the DMAC controllers are out of reset since I (previously to calling this routine) make use of the DMA controller to read and write various external registers via the I2C peripheral built into the TMS320C5515.

    If I put a break point at the end of this routine and examine the memory arrays I2SReadRightBuff and I2SReadLeftBuff, I fail to see that the DMA has transferred the 32 bit values from the Trasnmit arrays to the Read Buffers.......

    It is from this observation that I conclude that the DMA events associated with I2S port 2 are not being received by DMA Controller 1.

     

    Any help will be greatfuly received......

     

  • Hi,

     

    I tried starting from CSL2.10 CSL_I2S_DMAExample_out project. I modified to use I2S2 port and DMA channel 4,5,6, and 7. All other are untouched.

    Also it's I2S master on DSP side. It worked ok. I think this is worth to try it for you to get a starting point.

    Regards,

    Hyun

  • Hello Hyun,

           thanks for the quick reply.

    If you look at the code that I included, you will see that it is almost a carbon copy of the CSL example that you state.

    Two other facts make it problematic to run the code as is:

    (1) the CSL example sets the PPMODE to mode 6 while I require it to be mode 1.

    (2) The I2S interface in my application is acting as a slave and I can NOT disable the external master from generating the clocks.

    Can you see anything that looks remiss in the section of code that I posted?

    Best regards,

                             David

     

  • Hi,

     

    In addition to previous try, I updated #define CSL_I2S_DMA_BUF_LEN (512) from (1).

    And dmaConfig.dataLen      = 4 * CSL_I2S_DMA_BUF_LEN; from 4. This configuration also worked.

     

    In your case CSL_I2S_DMA_BUF_LEN = 128 right?


    Only concern is loopback mode with slave mode. This is not checked.

    Regards,

    Hyun

  • Hello Hyun,

                           I set the dmaConfig.datalen to 512 (4 x 128) : dmaConfigI2S.dataLen      = 512;

    There is another difference between the two tests. Unless you modified the I2S_open function, then I2S instance 2 would redefine the EBSR PMODE bits to select mode 6 as seen below:

    CSL_I2sHandle I2S_open(I2S_Instance        i2sInstNum,
                           I2S_OpMode        opMode,
                           I2S_ChanType     chType)
    {
        CSL_I2sHandle hI2s;
        ioport volatile CSL_SysRegs        *sysRegs;

        hI2s = NULL;
        /* Check device is already in used*/
        if(i2sInstNum == I2S_INVALID)
        {
            return (NULL);
        }

        hI2s = &I2S_InstanceNum[i2sInstNum];

        if((i2sInstNum >= 0) & (i2sInstNum <= 3))
        {
            hI2s->i2sNum    = i2sInstNum;
            hI2s->chType    = chType;
            hI2s->opMode    = opMode;
            hI2s->firstRead = TRUE;

            sysRegs = (CSL_SysRegs *)CSL_SYSCTRL_REGS;
            /* Configure the Peripheral Reset Control Register */
            CSL_FINS(sysRegs->PRCR, SYS_PRCR_PG3_RST, CSL_SYS_PRCR_PG3_RST_NRST);
            CSL_FINS(sysRegs->PRCR, SYS_PRCR_PG4_RST, CSL_SYS_PRCR_PG4_RST_NRST);

            /* Set Instance hardware registers*/
            switch(i2sInstNum)
            {
                case I2S_INSTANCE0:
                    hI2s->hwRegs = (CSL_I2sRegs *)(CSL_I2S0_REGS);
                    CSL_FINS(sysRegs->PCGCR1, SYS_PCGCR1_I2S0CG,
                                            CSL_SYS_PCGCR1_I2S0CG_ACTIVE);
                    CSL_FINS(sysRegs->EBSR, SYS_EBSR_SP0MODE,
                                            CSL_SYS_EBSR_SP0MODE_MODE1);
                    break;
                case I2S_INSTANCE1:
                    hI2s->hwRegs = (CSL_I2sRegs *)(CSL_I2S1_REGS);
                    CSL_FINS(sysRegs->PCGCR1, SYS_PCGCR1_I2S1CG,
                                            CSL_SYS_PCGCR1_I2S1CG_ACTIVE);
                    CSL_FINS(sysRegs->EBSR, SYS_EBSR_SP1MODE,
                                            CSL_SYS_EBSR_SP1MODE_MODE1);
                    break;
                case I2S_INSTANCE2:
                    hI2s->hwRegs = (CSL_I2sRegs *)(CSL_I2S2_REGS);
                    CSL_FINS(sysRegs->PCGCR1, SYS_PCGCR1_I2S2CG,
                                            CSL_SYS_PCGCR1_I2S2CG_ACTIVE);
                    // MODIFIED BY dvine SHOULD NOT UPDATE THE EBSR   CSL_FINS(sysRegs->EBSR, SYS_EBSR_PPMODE,
                    //                        CSL_SYS_EBSR_PPMODE_MODE6);
                    break;
                case I2S_INSTANCE3:
                    hI2s->hwRegs = (CSL_I2sRegs *)(CSL_I2S3_REGS);
                    CSL_FINS(sysRegs->PCGCR1, SYS_PCGCR1_I2S3CG,
                                            CSL_SYS_PCGCR1_I2S3CG_ACTIVE);
                    CSL_FINS(sysRegs->EBSR, SYS_EBSR_PPMODE,
                                            CSL_SYS_EBSR_PPMODE_MODE6);
                    break;
                default:
                    break;
            }
        }
        hI2s->configured = FALSE;
        return(hI2s);
    }

    I also noted that the DMA test calls I2S_setup that enables interrupts to the CPU:

    Please also note that the Mono/Stereo setting configures the I2S format to be either left justified or DSP mode....I think that this is a bad way to set up the I2S hardware......

    CSL_Status I2S_setup(CSL_I2sHandle    hI2s,
                         I2S_Config     *i2sHwConfig)
    {
        ioport CSL_I2sRegs      *regs;

        if(NULL == hI2s)
        {
            return (CSL_ESYS_BADHANDLE);
        }

        if(NULL == i2sHwConfig)
        {
            return (CSL_ESYS_INVPARAMS);
        }

        if(TRUE != hI2s->configured)
        {
            regs = hI2s->hwRegs;

            hI2s->fsDiv        = i2sHwConfig->fsDiv;
            hI2s->loopBackMode = i2sHwConfig->loopBackMode;
            hI2s->datapack     = i2sHwConfig->datapack;
            hI2s->wordLen      = i2sHwConfig->wordLen;

            /* Reset All the registers*/
            regs->I2SSCTRL   &= (Uint16)CSL_I2S_I2SSCTRL_RESETVAL;
            regs->I2SSRATE   &= (Uint16)CSL_I2S_I2SSRATE_RESETVAL;

            regs->I2STXLT0   &= (Uint16)CSL_I2S_I2STXLT0_RESETVAL;
            regs->I2STXLT1   &= (Uint16)CSL_I2S_I2STXLT1_RESETVAL;
            regs->I2STXRT0   &= (Uint16)CSL_I2S_I2STXRT0_RESETVAL;
            regs->I2STXRT1   &= (Uint16)CSL_I2S_I2STXRT1_RESETVAL;

            regs->I2SINTFL   &= (Uint16)CSL_I2S_I2SINTFL_RESETVAL;
            regs->I2SINTMASK &= (Uint16)CSL_I2S_I2SINTMASK_RESETVAL;

            regs->I2SRXLT0   &= (Uint16)CSL_I2S_I2SRXLT0_RESETVAL;
            regs->I2SRXLT1   &= (Uint16)CSL_I2S_I2SRXLT1_RESETVAL;
            regs->I2SRXRT0   &= (Uint16)CSL_I2S_I2SRXRT0_RESETVAL;
            regs->I2SRXRT1   &= (Uint16)CSL_I2S_I2SRXRT1_RESETVAL;


            /* Data transmit/receive is Mono/Stereo type*/
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_MONO, i2sHwConfig->dataType);

            /* Enable/disable the loopback bit */
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_LOOPBACK, i2sHwConfig->loopBackMode);

            /* Set FSYNC polarity is High/Low */
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_FSPOL, i2sHwConfig->fsPol);

            /* Set the clock polarity FALLING/RESING */
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_CLKPOL, i2sHwConfig->clkPol);

            /* Data delay set to ONE/TWo bit*/
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_DATADLY, i2sHwConfig->datadelay);

            /* Data packing Enable/Disable */
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_PACK, i2sHwConfig->datapack);

            /* Set data sign extension*/
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_SIGN_EXT, i2sHwConfig->signext);

            /* Set Word length for a word */
            CSL_FINS(regs->I2SSCTRL, I2S_I2SSCTRL_WDLNGTH, i2sHwConfig->wordLen);

            /* Set the Mode of transmission */
            if(i2sHwConfig->i2sMode == I2S_SLAVE)
            {
                CSL_FINST(regs->I2SSCTRL, I2S_I2SSCTRL_MODE, CLEAR);
            }
            else
            {
                CSL_FINST(regs->I2SSCTRL, I2S_I2SSCTRL_MODE, SET);
            }

            /* Channel type is Mono/Stereo, Set the dependant bit*/
            if(hI2s->chType == I2S_CHAN_MONO)
            {
                CSL_FINST(regs->I2SSCTRL, I2S_I2SSCTRL_FRMT, SET);
                /* Left transmit & recv channel disable */
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_XMITST, DISABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_XMITMON, ENABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_RCVST, DISABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_RCVMON, ENABLE);
            }
            else
            {
                CSL_FINST(regs->I2SSCTRL, I2S_I2SSCTRL_FRMT, CLEAR);
                /* Right transmit & recv channel disable */
                /* DMA Control hence disable interrupts  */
    //            CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_XMITST, ENABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_XMITST, DISABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_XMITMON, DISABLE);
    //            CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_RCVST, ENABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_RCVST, DISABLE);
                CSL_FINST(regs->I2SINTMASK, I2S_I2SINTMASK_RCVMON, DISABLE);
            }

            /* Set the bit for the frame sync devider */
            CSL_FINS(regs->I2SSRATE, I2S_I2SSRATE_FSDIV, i2sHwConfig->fsDiv);

            /* Set bit for the serializer clock divider */
            CSL_FINS(regs->I2SSRATE, I2S_I2SSRATE_CLKDIV, i2sHwConfig->clkDiv);

            /* Frame-sync error enable/disable    */
            CSL_FINS(regs->I2SINTMASK, I2S_I2SINTMASK_FERR, i2sHwConfig->FError);

            /* Overrun or under-run error enable/disable    */
            CSL_FINS(regs->I2SINTMASK, I2S_I2SINTMASK_OUERR, i2sHwConfig->OuError);

            /* Reset the IR*/
            regs->I2SINTFL &= (Uint16)CSL_I2S_I2SINTFL_RESETVAL;

            hI2s->configured = TRUE;
        }
        return(CSL_SOK);
    }

     

  • Hi David,

    If you are able to see that the program is reaching end of routine, means DMA is receiving events from I2S. Otherwise code hangs at first DMA_getStatus call. You may need to re-arrange your program slightly. 

    Try below steps…

    1. Open and configure I2S channel
    2. Configure DMA for I2S Left Tx (Do not start DMA)
    3. Configure DMA for I2S right Tx (Do not start DMA)
    4. Configure DMA for I2S Left Rx (Do not start DMA)
    5. Configure DMA for I2S Right Rx (Do not start DMA)
    6. Start DMA Rx channels
    7. Start DMA Tx channels
    8. Enable I2S transfer (Using I2S_transEnable)
    9. Wait for the DMA to complete all the channel transfers (Using DMA_getStatus)

    Pratap.