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.

TM4C129XNCZAD: Not able to configure UART5 for DMA

Part Number: TM4C129XNCZAD

the code is just a modification of dma_demo from TM4c129X lib, UART0 works fine.. not the UART5 though.. anything I am missing in configuration part?

I checked TX output pin and there is no signal out, always high (3.3V)

ISR for receiving

void UART5IntHandler(void)
{
    uint32_t ui32Status1;
       uint32_t ui32Mode1;

       //
       // Read the interrupt status of the UART.
       //
       ui32Status1 = ROM_UARTIntStatus(UART5_BASE, 1);
       //UARTIntDisable(UART0_BASE);

       if (ui32Status1 == 0x00020000)
       {

           // do something here..........
           ROM_UARTDMADisable(UART5_BASE, UART_DMA_TX);
           // Need this step to be able to exit the interrupt.
           ROM_UARTIntClear(UART5_BASE, ui32Status1);

           return;
       }

       //HWREG(UART0_BASE + UART_O_ICR) = 0x00020000;
       //ui32Status = ROM_UARTIntStatus(UART0_BASE, 1);

       //
       // Clear any pending status, even though there should be none since no UART
       // interrupts were enabled.  If UART error interrupts were enabled, then
       // those interrupts could occur here and should be handled.  Since uDMA is
       // used for both the RX and TX, then neither of those interrupts should be
       // enabled.
       //
       ROM_UARTIntClear(UART5_BASE, ui32Status1);
       ui32Status1 = ROM_UARTIntStatus(UART5_BASE, 1);

       //
       // Check the DMA control table to see if the ping-pong "A" transfer is
       // complete.  The "A" transfer uses receive buffer "A", and the primary
       // control structure.
       //
       ui32Mode1 = ROM_uDMAChannelModeGet(UDMA_CH6_UART5RX | UDMA_PRI_SELECT);

       //
       // If the primary control structure indicates stop, that means the "A"
       // receive buffer is done.  The uDMA controller should still be receiving
       // data into the "B" buffer.
       //
       if (ui32Mode1 == UDMA_MODE_STOP)
       {
           //
           // Increment a counter to indicate data was received into buffer A.  In
           // a real application this would be used to signal the main thread that
           // data was received so the main thread can process the data.
           // -------------------------> Set the data recieved flag in Buffer A--->>???

           //g_ui32RxBufACount++;

           //
           // Set up the next transfer for the "A" buffer, using the primary
           // control structure.  When the ongoing receive into the "B" buffer is
           // done, the uDMA controller will switch back to this one.  This
           // example re-uses buffer A, but a more sophisticated application could
           // use a rotating set of buffers to increase the amount of time that
           // the main thread has to process the data in the buffer before it is
           // reused.
           //
           ROM_uDMAChannelTransferSet(UDMA_CH6_UART5RX | UDMA_PRI_SELECT,
           UDMA_MODE_PINGPONG,
                                      (void *) (UART5_BASE + UART_O_DR),
                                      g_ui8pMeterRxBufA,
                                      sizeof(g_ui8pMeterRxBufA));
       }

       //
       // Check the DMA control table to see if the ping-pong "B" transfer is
       // complete.  The "B" transfer uses receive buffer "B", and the alternate
       // control structure.
       //
       ui32Mode1 = ROM_uDMAChannelModeGet(UDMA_CH6_UART5RX | UDMA_ALT_SELECT);

       //
       // If the alternate control structure indicates stop, that means the "B"
       // receive buffer is done.  The uDMA controller should still be receiving
       // data into the "A" buffer.
       //
       if (ui32Mode1 == UDMA_MODE_STOP)
       {
           //
           // Increment a counter to indicate data was received into buffer A.  In
           // a real application this would be used to signal the main thread that
           // data was received so the main thread can process the data.
           //
           //g_ui32RxBufBCount++;

           //// -------------------------> Set the data recieved flag--->>???

           // Set up the next transfer for the "B" buffer, using the alternate
           // control structure.  When the ongoing receive into the "A" buffer is
           // done, the uDMA controller will switch back to this one.  This
           // example re-uses buffer B, but a more sophisticated application could
           // use a rotating set of buffers to increase the amount of time that
           // the main thread has to process the data in the buffer before it is
           // reused.
           //
           ROM_uDMAChannelTransferSet(UDMA_CH6_UART5RX | UDMA_ALT_SELECT,
           UDMA_MODE_PINGPONG,
                                      (void *) (UART5_BASE + UART_O_DR),
                                      g_ui8pMeterRxBufB,
                                      sizeof(g_ui8pMeterRxBufB));
       }

       //
       // If the UART0 DMA TX channel is disabled, that means the TX DMA transfer
       // is done.
       //

       // The uDMA TX channel must be re-enabled.
       //

   }

// function to configure the UART 5 for write and read using DMA

void InitUART5Transfer(void)
{

    // Configure Device pins for Meter UART
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

            ROM_GPIOPinConfigure(GPIO_PC6_U5RX);
            ROM_GPIOPinConfigure(GPIO_PC7_U5TX);
            ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);

        // Enable the UDMA UART & configure it to operate even if the CPU is in sleep
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
            ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);

            ROM_IntEnable(INT_UDMAERR);

             //
             // Enable the uDMA controller.
             //
            ROM_uDMAEnable();


            ROM_uDMAControlBaseSet(pui8ControlTable);

            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
            ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART5);

            // Configure the UART communication parameters.
            //
            ROM_UARTConfigSetExpClk(UART5_BASE, ui32SysClock, 9600,
            UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
            UART_CONFIG_PAR_NONE);

    //Enable the uDMA controller error interrupt.  This interrupt will occur
    // if there is a bus error during a transfer.
    //

    //
    // Point at the control table to use for channel control structures.
       //

    //
    // Set both the TX and RX trigger thresholds to 4.  This will be used by
    // the uDMA controller to signal when more data should be transferred.  The
    // uDMA TX and RX channels will be configured so that it can transfer 4
    // bytes in a burst when the UART is ready to transfer more data.
    //
    ROM_UARTFIFOLevelSet(UART5_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

    //
    // Enable the UART for operation, and enable the uDMA interface for both TX
    // and RX channels.
    //
    ROM_UARTEnable(UART5_BASE);
    //ROM_UARTDMAEnable(UART0_BASE, UART_DMA_RX );
    ROM_UARTDMAEnable(UART5_BASE, UART_DMA_RX | UART_DMA_TX);
    //
    // This register write will set the UART to operate in write mode.
    //
    //HWREG(UART0_BASE + UART_O_CTL) |= UART_CTL_TXE;

    //
    // Put the attributes in a known state for the uDMA UART0RX channel.  These
    // should already be disabled by default.
    //
    ROM_uDMAChannelAttributeDisable(UDMA_CH6_UART5RX,
    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);

    //
    // Configure the control parameters for the primary control structure for
    // the UART RX channel.  The primary contol structure is used for the "A"
    // part of the ping-pong receive.  The transfer data size is 8 bits, the
    // source address does not increment since it will be reading from a
    // register.  The destination address increment is byte 8-bit bytes.  The
    // arbitration size is set to 4 to match the RX FIFO trigger threshold.
    // The uDMA controller will use a 4 byte burst transfer if possible.  This
    // will be somewhat more effecient that single byte transfers.
    //
    ROM_uDMAChannelControlSet(UDMA_CH6_UART5RX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_1);

    //
    // Configure the control parameters for the alternate control structure for
    // the UART RX channel.  The alternate contol structure is used for the "B"
    // part of the ping-pong receive.  The configuration is identical to the
    // primary/A control structure.
    //
    ROM_uDMAChannelControlSet(UDMA_CH6_UART5RX | UDMA_ALT_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_1);

    //
    // Set up the transfer parameters for the UART RX primary control
    // structure.  The mode is set to ping-pong, the transfer source is the
    // UART data register, and the destination is the receive "A" buffer.  The
    // transfer size is set to match the size of the buffer.
    //
    ROM_uDMAChannelTransferSet(UDMA_CH6_UART5RX | UDMA_PRI_SELECT,
    UDMA_MODE_PINGPONG,
                               (void *) (UART5_BASE + UART_O_DR),
                               g_ui8pMeterRxBufA, sizeof(g_ui8pMeterRxBufA));

    //
    // Set up the transfer parameters for the UART RX alternate control
    // structure.  The mode is set to ping-pong, the transfer source is the
    // UART data register, and the destination is the receive "B" buffer.  The
    // transfer size is set to match the size of the buffer.
    //
    ROM_uDMAChannelTransferSet(UDMA_CH6_UART5RX | UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
                               (void *) (UART5_BASE + UART_O_DR),
                               g_ui8pMeterRxBufB, sizeof(g_ui8pMeterRxBufB));

    //
    // Put the attributes in a known state for the uDMA UART0TX channel.  These
    // should already be disabled by default.
    //
    ROM_uDMAChannelAttributeDisable(UDMA_CH7_UART5TX,
    UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_HIGH_PRIORITY |
    UDMA_ATTR_REQMASK);

    //
    // Set the USEBURST attribute for the uDMA UART TX channel.  This will
    // force the controller to always use a burst when transferring data from
    // the TX buffer to the UART.  This is somewhat more effecient bus usage
    // than the default which allows single or burst transfers.
    //
    ROM_uDMAChannelAttributeEnable(UDMA_CH7_UART5TX, UDMA_ATTR_USEBURST);

    //
    // Configure the control parameters for the UART TX.  The uDMA UART TX
    // channel is used to transfer a block of data from a buffer to the UART.
    // The data size is 8 bits.  The source address increment is 8-bit bytes
    // since the data is coming from a buffer.  The destination increment is
    // none since the data is to be written to the UART data register.  The
    // arbitration size is set to 4, which matches the UART TX FIFO trigger
    // threshold.
    //
    ROM_uDMAChannelControlSet(UDMA_CH7_UART5TX | UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_8 |
    UDMA_DST_INC_NONE |
    UDMA_ARB_1);

    //
    // Set up the transfer parameters for the uDMA UART TX channel.  This will
    // configure the transfer source and destination and the transfer size.
    // Basic mode is used because the peripheral is making the uDMA transfer
    // request.  The source is the TX buffer and the destination is the UART
    // data register.
    ROM_uDMAChannelTransferSet(UDMA_CH7_UART5TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC,
                                g_ui8pMeterTxBuf,
                               (void *) (UART5_BASE + UART_O_DR),
                               sizeof(g_ui8pMeterTxBuf));

    // Now both the uDMA UART TX and RX channels are primed to start a
    // transfer.  As soon as the channels are enabled, the peripheral will
    // issue a transfer request and the data transfers will begin.
    //
    ROM_uDMAChannelEnable(UDMA_CH6_UART5RX);
    ROM_uDMAChannelEnable(UDMA_CH7_UART5TX);

    //
    // Enable the UART DMA TX/RX interrupts.
    //

    //ROM_UARTIntEnable(UART0_BASE, UART_INT_DMATX | UART_INT_DMARX);
    ROM_UARTIntEnable(UART5_BASE, UART_INT_DMARX);
    //
    // Enable the UART peripheral interrupts.
    //
    ROM_IntEnable(INT_UART5);

}

  • I think this post will answer your question.

    e2e.ti.com/.../1938755
  • Dear Charles,

    I read through the forum and it was about enabling the UART3 and 5 in normal mode. in my case, normal mode (Interrupt based) is working fine for the UART5 however, DMA is not working for UART5.

    hope you could shed some light on specific steps I need to enable it with reference to the udma_demo ( which uses UART0).

    I could see that UART5 is in channel 2 ( page 713), and I do understand that this might affect the priority, but other than that, does this needs to be enabled or configured differently? 

    is there any special steps needs to be taken, if we are using more than 1 peripheral for DMA.

    correct me, if I am wrong, we need to enable only one base control structure and location for the dma regardless of peripherals used, correct?

    how do we use encoding? any sample usage for using peripherals from channel 2 or 3, and how different it is from using channel 0 peripherals.

    I believe, the issue that is stoping me from implementing DMA on UART5 is more DMA related than UART5 related, like I mentioned, this is my first attempt with DMA and I am yet to get full grasp of it.

    I would really appreciate if you could take a look into my code and see if I am missing any configuration steps to enable DMA for UART5.

    thank you so much for reading such a long post, appreciate your patience with newbie like me.

  • I went through your code and didn't really spot anything wrong and yet you are showing only partially your code. One thing to analyze further is the burst setting. You have used UDMA_ATTR_USEBURST while your arbitration size is only 1. This is the difference I see compared to the TivaWare udma_demo. I will suggest you use the identical configuration as in the example with only thing change from UART0 to UART5. If you can get this working then you can gradually adapt to your final specific setting.

    Please also look at the uDMA DMAWAITSTAT register. Is it waiting for a request to come?
    Look at the UART module UARTDR register and do you see any errors and if the data is written to the DR register? Check other registers as well. Since you said the normal mode without DMA is working, you can capture the register settings of the UART5 and compare them with your DMA code. If there is any major differences then you can investigate further.