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.

Synchronizing between multiple DMA channels?

Other Parts Discussed in Thread: TMS320C5515

I am working on a c5535 design that uses multiple AIC3204 codecs on multiple I2S ports.  My signal processing is done on a 10 ms frame basis so I am using DMA to transfer the audio data to and from the I2S ports.

I’m using DMA’s that are synchronized to the I2S ports, with ping/pong transfer mode.

In order for the audio data from the multiple codecs to “line up” for the frame processing, I need all DMA “frames” to start and complete at the same time ( being “synchronized” to each other, at least within a few sample times ).  In following the initialization instructions on page 18 of the “TMS320C5515/14/05/04 DSP Direct Memory Access (DMA) Controller – User’s Guide” ( Literature Number SPRUFT2A ) ( And as also documented on page 146 of SPRUH87CC ),

I first configure the codec ICs ( AIC3204 ),

configure the DMA transfers as described in instructions 1 through 11 of page 18 of the above mentioned document,

and finally perform instruction 12 from page 18 in “enabling peripheral being serviced the DMA channel” in this case the multiple I2S ports, which should start the DMA transfers relatively at the same time.

 

The problem is, the DMA transfers complete at random times relative to each other and do not “line up” so I can run the frame processing.  For example, the DMA from the I2S0 port might occur 2, 5, or 8 ms after the DMA transfer from the I2S2 port.  ( I’m using 10 ms frames ).  So apparently, the individual DMA channels are not starting out in the same internal states, even though I am resetting them in the PRCR register before I start the configuration, and enabling the associated I2S ports at the same time.

 

In debugging this I was setting a breakpoint between when the DMA channels are configured and when the I2S ports are enabled, and “magically” when I continue the DMA the channels are aligned.  So I put a delay loop between the DMA configuration and the I2S ports being enabled and when the delay is greater than 10 ms, the channels do align, with less delay they don’t and they start out in a random alignment.

 

So my question is, do you know why the DMA channels do NOT start out in the same state until x number of clock cycles after being configured and what is that exact number of cycles ( or delay time ) to get them to the same state?  Or, is there something else I need to do that I don't see in the documentation?

Any feedback would greatly be appreciated as I don’t see any other information on this in TI’s documents or forum.

 

Regards,

 

Tom

  • Hello Tom,

    Are you following the below instruction

    When using synchronization events, you must set EN = 1 and SYNCMODE = 1 during the same write cycle to DMACHmTCR2. The DMA channel will transfer the first data value when it receives the synchronization event specified by CHnEVT in DMACESR1 and DMACESR2. Also, when disabling the channel,you must set EN = 0 and SYNCMODE = 0 during the same write cycle to DMACHmTCR2. The amount of data (in bytes) to be transferred as programmed in the LENGTH field in DMACHmTCR1 should be a multiple of 4 bytes x 2BURSTMODE  field in DMACHmTCR2, i.e., LENGTH = (4 x 2BURSTMODE) bytes.

     As I understand DMA will not consume the amount of time you are mentioned after configuration.

    Please let us know. 

    Regards

     Vasanth 

  • Hi Vasanth,

    Thanks for getting back to me!

    First, I configure the AIC3204 codecs as “masters”, generating the clock and framing that are connected to the I2S0, I2S3, and I2S2 ports.

    Second, as shown in lines 2 through 10 of the “clip” below I configure the DMA channels.  The second “code clip” shows what this DMA configuration typically consists of.

    Within this second “clip” the EN and SYNCMODE bits you mentioned are cleared and set on lines 353 and 371.  ( This code is based upon “example code” from TI, and for some reason the register names do not match what is in the documentation, but I have verified they do address the correct registers by their address in their definitions.  )  In addition, the “LENGTH” field you mentioned is set on line 350.

    Then to start the DMA transfers, I start the I2S ports, as shown in lines 20, 25, and 30 by writing directly to the I2S registers’ EN bit ( bit 15 ).

    To avoid any confusion, the “synchronization” problem I’m having is NOT the “synchronization” between the DMA and I2S ports as mentioned in the TI documents.  What my “synchronization problem” is in getting the “frames” of ping/pong buffers to occur at relatively the same time ( within a few samples ) between the I2S0, I2S3, and I2S2 ports.

    As I previously mentioned in my first posting, the delay on line 14 is needed to get the DMA channels to start up at the same time and generate “frames” of data that are aligned between the I2S0, I2S3, and I2S2 ports.  This loop with a count of 64000 amounts to around 11 ms at the 100 MHz clock rate I’m using.  ( I measured this by toggling a GPIO pin before and after this delay and measured it on a scope. )

    With my current code, the DMA transfers through the I2S ports do work with the correct number of bytes being transferred.  The problem is in getting the frames of data aligned between the multiple I2S channels so I have the data at the right time to perform the frame based processing.

    So my original questions basically are: Why do I need the delay on line 14, for the DMA circuitry to apparently get “set” to the correct ( same ) state for all the DMA channels?  What should this delay really be to make sure this is not a problem?  Or am I doing something wrong and/or should I try something else?

     

    Thanks again,

     

    Tom

     

     

     

  • I previously posted my "code clips" as JPEG pictures, but apparently they didn't get included in this posting so I'm now posting them as text, with the referenced line numbers edited in.  So please see previous post for discussion of this code.

    Tom

    1
    2    set_dma0_ch0_i2s0_Lout(); // to Radio
    3    set_dma0_ch2_i2s0_Lin(); // from Radio
    4         set_dma0_ch3_i2s0_Rin(); // from Mic
    5
    6    set_dma2_ch0_i2s3_Lout(); // to Left Speaker
    7
    8    set_dma1_ch1_i2s2_Rout(); // to Right Speaker
    9    set_dma1_ch2_i2s2_Lin(); // Left Mic
    10   set_dma1_ch3_i2s2_Rin(); // Right Mic
    11
    12
    13   // Delay so that DMA comes up synchronized between I2S 0 2, & 3.
    14     for( i32 = 0 ; i32 < 64000; i32++ );
    15
    16
    17   // Start I2S0
    18       I2S0_SRATE = 0x0;
    19       I2S0_INTMASK = 0x00;    // Disable interrupts for DMA
    20       I2S0_SCTRL = 0x8010;    // 16-bit word, slave, enable I2S
    21
    22   // Start I2S2
    23     I2S2_SRATE = 0x0;
    24     I2S2_INTMASK = 0x00;    // Disable interrupts for DMA
    25     I2S2_SCTRL = 0x8010;    // 16-bit word, slave, enable I2S
    26      
    27   // Start I2S3
    28     I2S3_SRATE = 0x0;
    29     I2S3_INTMASK = 0x00;    // Disable interrupts for DMA
    30     I2S3_SCTRL = 0x8010;    // 16-bit word, slave, enable I2S

    346    Uint16 set_dma0_ch2_i2s0_Lin(void)
    347    {
    348        Uint16 temp;
    349
    350        DMA0_CH2_TC_LSW = BLOCK_SIZE * 8;
    351
    352    #if(AUTO_RELOAD ==1)        
    353        DMA0_CH2_TC_MSW = 0x3081;     //src fix, destination increase, sync, auto, int
    354    #else
    355        DMA0_CH2_TC_MSW = 0x2084;     //src fix, destination increase,, No auto, int
    356    #endif
    357                
    358        temp = DMA0_CH32_EVENT_SRC;
    359        DMA0_CH32_EVENT_SRC = temp | 0x0002;   // I2S0 receive event
    360
    361        DMA0_CH2_DST_LSW = (Uint16)RadRx1_DMA_address;
    362        DMA0_CH2_DST_MSW = 0xFFFF & (RadRx1_DMA_address >> 16);
    363    
    364        DMA0_CH2_SRC_LSW = 0x2828;      // I2S0 receive left data register lsw
    365        DMA0_CH2_SRC_MSW = 0;
    366
    367        // CurrentRxL_DMA0Channel = 2;
    368    //  DMA starts   
    369        temp = DMA0_CH2_TC_MSW;
    370        temp |= 0x8004;
    371        DMA0_CH2_TC_MSW = temp;
    372
    373        return SUCCESS;
    374    }

  • Tom,

       Did you try using CSL code.

       The snapshot of code looks ok , but also doesn't provide much information on the configuration details.

       Suggestion is to try the same using CSL approach.

     Regards

     Vasanth

     

  • Thanks for getting back to me again!

    I have not used the CSL for this function and I absolutely will NOT do so.  I have found that bringing in any functionality from the the CSL adds a level of abstraction that just makes it harder to figure out what is actually being set in the DSP's registers.  In addition, I have found that the CSL will reconfigure your system every time you bring in new code.  For example, within the typical "init" function for a particular port, the individual bits within the EBSR register gets set/cleared without any regards to what the previous configuration was, resulting in changing the DSP's pin configuration.  In my case it put the EBSR register into an invalid state and reconfigured the DSP's IO pins where something else in my design simply stoped working.  It took days to figure that problem out and I absolutly refuse to use any code that makes my work harder, just wastes time, and uses additional code space.

    In addition, simply reading and writing directly to the registers is easier to understand, code, and debug and in reading the DSP's documentation which describes the registers, not the CSL.

    Could you please let me know what "configuration details" you might want to know?  I assume you would need to know this information, independant of whether I'm using the CSL or writing to registers directly, as my system will not work if I just use the default CSL settings. 

    The code does work in my system, except for having the DMA ping/pong transfers alligned.  So I'm not sure that anything is wrong at the "system level" and would think it's only at the DMA initialization and/or I2S initialization which is shown in the register settings I've listed.  But let me know if you can think of any other settings you may want to know.

    Thanks again,

    Tom

  •   Tom,

     Yeah, I don't use CSL either.

    10 ms is like an eternity.  Are all your buffers the same size?  Are they in different blocks of memory?  Are they all the same type of memory?  Perhaps some DMA channels are conflicting with others, leading to differential timing.

    Regards,

    Bill