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.

TMS570LS3137: Issues with SCI DMA transfer

Part Number: TMS570LS3137

Hello everyone!

I'm having issues with SCI transfers over DMA in my application.  I'm using SCI over DMA as a logger and I'm spitting out quite a bit of data. When I do consecutive calls to the logger to write data over DMA, I typically only see the last message fully come out of the SCI module.  Whenever I'm logging something, I create a buffer and then send a pointer to that buffer as well as the length to the SendOverDma function which configures the DMA transfer:

SendOverDma(char * buffer, uint32_t length)
{
    uint32 sciTxData;
    g_dmaCTRL g_dmaCTRLPKT1;

    /*Initialize SCI*/
    sciInit();

    while (((sciREG->FLR & SCI_TX_INT) == 0U) || ((sciREG->FLR & 0x4) == 0x4))
    {
    } /* Wait */

    /*Assign DMA request SCI transmit to Channel 0*/
    dmaReqAssign(DMA_CH0, DMA_REQ);

    sciTxData = ((uint32_t)(&(sciREG->TD)) + 3);

    /*Configure control packet for Channel 0*/
    g_dmaCTRLPKT1.SADD      = (uint32_t)buffer;     /* source address             */
    g_dmaCTRLPKT1.DADD      = sciTxData;            /* destination  address       */
    g_dmaCTRLPKT1.CHCTRL    = 0;                    /* channel control            */
    g_dmaCTRLPKT1.FRCNT     = length;               /* frame count                */
    g_dmaCTRLPKT1.ELCNT     = 1;                    /* element count              */
    g_dmaCTRLPKT1.ELDOFFSET = 0;                    /* element destination offset */
    g_dmaCTRLPKT1.ELSOFFSET = 0;                    /* element destination offset */
    g_dmaCTRLPKT1.FRDOFFSET = 0;                    /* frame destination offset   */
    g_dmaCTRLPKT1.FRSOFFSET = 0;                    /* frame destination offset   */
    g_dmaCTRLPKT1.PORTASGN  = 4;
    g_dmaCTRLPKT1.RDSIZE    = ACCESS_8_BIT;         /* read size                  */
    g_dmaCTRLPKT1.WRSIZE    = ACCESS_8_BIT;         /* write size                 */
    g_dmaCTRLPKT1.TTYPE     = FRAME_TRANSFER;       /* transfer type              */
    g_dmaCTRLPKT1.ADDMODERD = ADDR_INC1;            /* address mode read          */
    g_dmaCTRLPKT1.ADDMODEWR = ADDR_FIXED;           /* address mode write         */
    g_dmaCTRLPKT1.AUTOINIT  = AUTOINIT_OFF;         /* autoinit                   */

    /*Set control packet for channel 0 and 1*/
    dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT1);

    /*Set dma channel 0 to trigger on hardware request*/
    dmaSetChEnable(DMA_CH0, DMA_HW);

    /*Enable DMA*/
    dmaEnable();

   /*Enable SCI Transmit and Receive DMA Request*/
    sciREG->SETINT = (1<<16);
}

If consecutive calls are too close to one another in time, then I typically only see the last string get fully transferred, and only one garbled character from the previous message.  Am I setting up the DMA transfers incorrectly? Do I need to buffer the messages? Should I wait for an event before transmitting a new message?  I thought the following takes care of the waiting:

    while (((sciREGx->FLR & SCI_TX_INT) == 0U) || ((sciREGx->FLR & 0x4) == 0x4))
    {
    } /* Wait */

Please help me figure out what's wrong. Thanks in advanced for you help!

  • Hi,

    Please use sciTxData = ((uint32_t)(&(sciREG->TD)) ); for DMA destination address
  • Hi,

    Thanks for the response.

    If I set sciTxData = ((uint32_t)(&(sciREG->TD)) ); for DMA destination address, I'm not getting any serial output whatsoever.

    I thought the +3 was there to compensate for the endianess of the device?  The attached example I used for the TMS570LS3137 adds 3 to the TX register address.0825.SCI_DMA_TMS570LS3137.ZIP

  • Hi,

    The DMA configuration is good. Since you don't use SCI receive, please remove the IDLE checking  in:

     while (((sciREG->FLR & SCI_TX_INT) == 0U) || ((sciREG->FLR & 0x4) == 0x4)) {

     } /* Wait */
     I got your code, and will do a quick test tomorrow.
  • Alright thanks.  Let me know what you get.

    Just FYI, I'm not sure if it's related to many messages trying to go out at close time intervals.  Try sending several consecutive messages to test my configuration, but again, I thought the following should take care of waiting for the transmit buffer to be ready:

    while ((sciREGx->FLR & SCI_TX_INT) == 0U) 

    Anyway, let me know what you find out.

    Thank you.

  • You are right,

    1
    while ((sciREGx->FLR & SCI_TX_INT) == 0U) is to wait for the transmit buffer to be ready.

    But

    ((sciREG->FLR & 0x4) == 0x4)) --> is to check if SCI receiver is in idle state

  • Hello,

    Just tested, the code works well. I transmitted 160 bytes data, and received the same data.

  • Thanks QJ, but I guess that I should elaborate that I'm able to successfully transmit over DMA when the messages are spaced out in time, but back to back messages are getting corrupt.  I have an instance when a calls to SendOverDMA occur within less than 100us from each other.  Only the last message in that sequence actually gets on out the port.  The first ones get courrupt and transmit an unknown variable.  See logic analyzer captures below:

     My questions is: why is it doing this? How is this even possible especially when I'm waiting for the transmit buffer to be ready?

    On a side note, when I remove ((sciREG->FLR & 0x4) == 0x4)) , I'm still getting garbled data, but it's garbled in a different way (different corrupt characters are showing up).

    Thanks

  • there is no problem on my side.