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.

CCS/TM4C129XNCZAD: uDMA not exiting the ISR

Part Number: TM4C129XNCZAD

Tool/software: Code Composer Studio

i am trying to send and receive data through DMA - UART and started with modifying the udma_demo and i am encountering this issue where by the UART Interrupt service routine is always triggered.

my doubt is as below:

ui32Status = ROM_UARTIntStatus(UART0_BASE, 1); returns 0x00020000 ; and i tried clearing the fault ( which keeps getting triggered, i didnt see it cleared).

this is the DMA Transmission completed bit, any suggestions.

void
InitUART0Transfer(uint32_t ui32SysClock)
{

// Enable the UART peripheral, and configure it to operate even if the CPU
// is in sleep.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);

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

//
// 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(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

//
// Enable the UART for operation, and enable the uDMA interface for both TX
// and RX channels.
//
ROM_UARTEnable(UART0_BASE);
ROM_UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX);

//

//
// Put the attributes in a known state for the uDMA UART0RX channel. These
// should already be disabled by default.
//
ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX,
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_CHANNEL_UART0RX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);

//
// 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_CHANNEL_UART0RX | UDMA_ALT_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
UDMA_ARB_4);

//
// 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_CHANNEL_UART0RX | UDMA_PRI_SELECT,
UDMA_MODE_PINGPONG,
(void *)(UART0_BASE + UART_O_DR),
g_ui8RxBufA, sizeof(g_ui8RxBufA));

//
// 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_CHANNEL_UART0RX | UDMA_ALT_SELECT,
UDMA_MODE_PINGPONG,
(void *)(UART0_BASE + UART_O_DR),
g_ui8RxBufB, sizeof(g_ui8RxBufB));

//
// Put the attributes in a known state for the uDMA UART0TX channel. These
// should already be disabled by default.
//
ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0TX,
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_CHANNEL_UART0TX, 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_CHANNEL_UART0TX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 |
UDMA_DST_INC_NONE |
UDMA_ARB_4);

//
// 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_CHANNEL_UART0TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, g_ui8TxBuf,
(void *)(UART0_BASE + UART_O_DR),
sizeof(g_ui8TxBuf));

//
// 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_CHANNEL_UART0RX);
ROM_uDMAChannelEnable(UDMA_CHANNEL_UART0TX);

//
// Enable the UART DMA TX/RX interrupts.
//
ROM_UARTIntEnable(UART0_BASE, UART_INT_DMATX | UART_INT_DMARX);

//
// Enable the UART peripheral interrupts.
//

}

  • Hi,
    I don't spot anything wrong with InitUART0Transfer(). It is much the same as the TivaWare example except you remove the loopback mode.

    How did you clear the UART0 interrupt flag?

    Inside the UART0IntHandler did you continue to trigger the UART DMA transfer? If you don't want to continue DMA transfer then you should not restart another DMA tranfer after the DMA transfer is complete.
  • Dear Charles,

    Thank you so much for replying, I have removed the DMA send again part of it...

    and I am clearing the flag as below:

    do I need to disable the TX interrupt? I tried disabling DMA and Disabled the TX interrupt by adding these lines, but it took me to FaultISR(void)

     ROM_UARTDMADisable(UART0_BASE, UART_DMA_TX);
     ROM_UARTIntDisable(UART0_BASE, UART_INT_DMATX);

    I am reading interrupt status and it is 0x00020000; and I tried to clear it, but it didn't get cleared.

    The purpose of my code is just to be able to send some string of data when I write it to a buffer and enable the DMA... and receive any reponse from the other end as and when I get.

    issue now is, system is always in the ISR and never leaves the ISR, am I missing something here?

    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
        uint32_t ui32Mode;

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

        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(UART0_BASE, ui32Status);
        ui32Status = ROM_UARTIntStatus(UART0_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.
        //
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART0RX | 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(ui32Mode == 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_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(UART0_BASE + UART_O_DR),
                                       g_ui8RxBufA, sizeof(g_ui8RxBufA));
        }

        //
        // 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.
        //
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART0RX | 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(ui32Mode == 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++;

            //// -------------------------> Buffer is full... Move the data to memory location in core----- set a flag here-------

            //
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_ALT_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(UART0_BASE + UART_O_DR),
                                       g_ui8RxBufB, sizeof(g_ui8RxBufB));
        }

                    // The uDMA TX channel must be re-enabled next time I want to do a transfer.

                //


    }

  • You claim that you are, "Not exiting the Interrupt" - yet is it not possible that your "clear of the interrupt" occurs "too late w/in the ISR service" - thus fails to fully/properly execute - causing the "endless return" to that ISR?

    Would not different bit "toggles" - upon entry into - and exit therefrom - that ISR - prove more definitive/insightful?       I do not believe you've (yet), "Made the case" for  "failing to exit the ISR."

  • Dear cb1_mobile,

    actually, I figured what was going wrong in the code and it was according to my suspicion that keep coming back to ISR was due an interrupt not being cleared and indeed it was the case.

    before clearing the DMATXIC interrupt I should disable the channel in the UARTDMACTL and I achieved that using this,

    ui32Status = ROM_UARTIntStatus(UART0_BASE, 1);
    //UARTIntDisable(UART0_BASE);

    if (ui32Status == 0x00020000)
    {

    // do something here..........
    ROM_UARTDMADisable(UART0_BASE, UART_DMA_TX);
    ROM_UARTIntClear(UART0_BASE, ui32Status);

    }