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/TM4C123GH6PM: Communication between 2 TM4C123G sing uDMA UART

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL

Tool/software: Code Composer Studio

Hello everyone,

I'm working on a project that requires developing a communication method between 2 TM4C123G, kit A handles power process (ADC, PWM, etc.), kit B handles MODBUS through RS-485 to the PC. The target is frequently communication without interrupt the power process of A and MODBUS communication of B, I have gone through I2C, SPI communication. These two methods is fast and accurate, but still have flaws since the I2C don't have any FIFO and SPI communication is hard to synchronize without interrupted. I found out that the uDMA can independently process without interrupt the main program, thus, I try using the uDMA UART in order to make the communication data always accessible. I'm a newbie in the uDMA field, but I did do some studies and researches. Currently, I understand the way uDMA working, unfortunately, I can't figure out how to set up it properly. I tried to modified some code I found online but so far nothing happens yet (the code is attached below).

My idea is when data go to the Rx pin of any kit, it will trigger the uDMA so that all the data will go straight to register of uDMA and trigger a flag. In the while(1) loop, if the flag is ON, the data will be processed and response to the other kit (this is also the reason why I choose UART instead of I2C and SPI). For more details, kit B send a request package of 8 byte unsigned char to kit A, kit A after finishing the power process will check the flag. If the flag is ON, kit A will gather data and send a package of 16 (or 32 bytes) of ADC information to kit B. Which type of mode and data should I set up to satisfy these requirements?

The code online using the UART FIFO to trigger the uDMA. Is there any way to transfer data directly to the uDMA without using the UART FIFO?

Thank you.

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_uart.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"

static char uDMAControlTable[1024];

char buffer[] = {0,1,2,3,4,5,6,7,8,9};

void initUART0(void)
{
    // Enable GPIO port A
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    // Enable DMA
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    IntEnable(INT_UDMAERR);
    uDMAEnable();
    uDMAControlBaseSet(uDMAControlTable);


    // Enable UART 0 peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


    // Setup A0 and A1 as the RX and TX pins for UART 0
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0);
    GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_1);


    // Configure UART (clock from PIOSC, 115.2k 8-N-1)
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_EVEN));

    // Trigger interrupt when FIFOs at 1/8 capacity
    UARTFIFOLevelSet(UART0_BASE,UART_FIFO_TX1_8,UART_FIFO_RX1_8);

    // Make sure interrupts are clear
    UARTIntClear(UART0_BASE, (UART_INT_RX | UART_INT_RT | UART_INT_TX | UART_INT_OE | UART_INT_BE | UART_INT_PE | UART_INT_FE));

    // Enable UART 0
    UARTEnable(UART0_BASE);

    // Enable DMA on UART RX
    UARTDMAEnable(UART0_BASE, UART_DMA_RX);

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

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

    uDMAChannelAttributeEnable(UDMA_CHANNEL_UART0TX, UDMA_ATTR_USEBURST);

    uDMAChannelControlSet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_8);

    uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_8);

    // Enable DMA interrupts on this UART
    UARTIntEnable(UART0_BASE, UART_INT_DMARX | UART_INT_DMATX);

    // Enable interrupts on this UART
    IntEnable(INT_UART0);
}

void uartInterruptHandler(void)
{
    // If an RX interrupt
    if (UARTIntStatus(UART0_BASE, true) & UART_INT_DMARX)
    {
        // Disable DMA on UART RX, and clear the interrupt
        UARTDMADisable(UART0_BASE, UART_DMA_RX);
        UARTIntClear(UART0_BASE, UART_INT_DMARX );
    }

    // If an TX interrupt
    if (UARTIntStatus(UART0_BASE, true) & UART_INT_DMATX)
    {
        // Disable DMA on UART TX, and clear the interrupt
        UARTDMADisable(UART0_BASE, UART_DMA_TX);
        UARTIntClear(UART0_BASE, UART_INT_DMATX );
    }
}

int main()
{
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    // Initialize UART
    initUART0();
    for(;;)
    {
        /*******************************************************************************
        * Receive
        */
        // Setup to receive buffer
        uDMAChannelTransferSet( UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(UART0_BASE + UART_O_DR), &buffer, sizeof(buffer));
        // Enable DMA channel to begin receive
        uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
        // Enable DMA on UART RX
        UARTDMAEnable(UART0_BASE, UART_DMA_RX);
        /*******************************************************************************
        * Transmit
        */
        // Setup to send buffer
        uDMAChannelTransferSet( UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, &buffer, (void *)(UART0_BASE + UART_O_DR), sizeof(buffer));
        // DMA channel must be enabled first, or an interrupt will occur immediately
        uDMAChannelEnable(UDMA_CHANNEL_UART0TX);
        // Enable DMA on UART TX
        UARTDMAEnable(UART0_BASE, UART_DMA_TX);
        while (uDMAChannelIsEnabled(UDMA_CHANNEL_UART0RX))
        {
            // Wait for the response before sending more
        }
    }

}

  • Hi,
    Why don't you try disabling the UART FIFO?

    Go to the TivaWare library and you can find uDMA example in <TivaWare_installation>/examples/boards/ek-tm4c123gxl/udma_demo. This demo example uses ping-pong mode. But for you application you can make it even simpler without the ping-pong mode.
  • Hello Charles,

    It must be my mistake for missing the UARTFIFODisable() function (I don't know how I did not see it) so I really sorry for the FIFO excessive question.

    Anyway, about the uDMA, I did try the demo and see the change in the data. But like I said, I don't know how to set up properly for the auto-request mode because I'm not familiar with the terminologies in the instruction. I think working with a more complex example without understanding a simple one is not a good way to begin learning sth. Hence, I asked for some explanations or instruction in order to understand deeper (which my knowledge is pretty shallow). So, I would really appreciate if you can be gentle with me.

    Can you explain me the flow of data, I see that there is DST and SRC which is a registers of uDMA. But I can not figure it out where will the data come in, and by which function we will know that the data is done receiving or transmitting in uDMA.

    Thank you so much.

    Regards,

  • Hi,
    Sorry, I'm out of office until Wednesday. Therefore, my response will be delayed. In addition, I don't have a PC with me at the moment to access the uDMA example code. I'm currently typing with my phone. With that much said, I can briefly explain how uDMA works. First you need to configure the uDMA control structure by setting up the source and destination addresses and the transfer size. I think you can find this level of details in the datasheet and in the example. The uDMA waits for a DMA request trigger signal from the respective peripheral (i.e. UART). Once the trigger is received the uDMA starts to transfer data from the UART to the memory. In the TivaWAre example, it sets up a ping-pong buffer structure where CPU can read and process from one buffer while the uDMA transfers data to the other buffer and then alternates. The CPU is notified using uDMA interrupt. When uDMA finishes the amount of data requested per the control structure during the initialization, it will generate interrupt to the CPU. You don't have to use the ping-pong buffer structure but it is a more efficient method in moving data. You can reference the TivaWAre example and remove the alternate control structure setup to simplify the operation. I think if you go through the example you should be able to find out the flow of the uDMA transfer. I don't know what else to say besides asking you to read the datasheet and the example code.
  • Dear Charles,

    I really appreciate you for the detail explaination and suggestion. It will take me a little time to figure it out, so I will try to read your reply and all the documents again and again in order to understand what is going on here. After that, I will try to program based on that knowledge. Until then,  can you check my new code and results to see whether I'm on the right direction or not?

    Sincerely,

    Nam

  • Hello Charles,

    I have done some code in order to achieve my main target. But I don't know why the code is not working, please help me out. The main idea is the uDMA will direct the Rx data to Rx Buffer without using Rx FIFO, the LED is ON and OFF every 1s. The request will be processed and responded only when the LED is OFF.  So I tried to direct the data from UART0_BASE to g_ui8RxBuf[], and if data is received, the MODE is switch from AUTO to STOP (I don't know if I understand this correctly or not, please tell me if I'm wrong). Only then, the Data is processed and responded.

    Here is my code.

    /******************************************
     *          Libraries Include
     ******************************************/
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_uart.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/udma.h"
    #include "driverlib/timer.h"
    
    /******************************************
     *          Constants Define
     ******************************************/
    #define MEM_BUFFER_SIZE         1024
    #define UART_BUF_SIZE           16
    
    /******************************************
     *          Variables
     ******************************************/
    uint8_t ui8ControlTable[MEM_BUFFER_SIZE];
    static unsigned char g_ui8TxBuf[UART_BUF_SIZE];
    static unsigned char g_ui8RxBuf[UART_BUF_SIZE];
    static uint32_t g_ui32uDMAErrCount = 0;
    static uint32_t g_ui32Timer = 0;
    static uint8_t g_ui8Mode = 0;
    
    /******************************************
     *          Functions Call
     ******************************************/
    void uDMAErrorHandler();
    void InituDMAnUARTTransfer();
    void ConfigureUART();
    void TIMERISR();
    void ConfigureTIMER();
    void SendUART(unsigned char X);
    
    /******************************************
     *          Main Program
     ******************************************/
    int main(void)
    {
        uint32_t ui32Mode;
        uint8_t ui8Index;
        SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
        g_ui32Timer = SysCtlClockGet();
        g_ui8Mode = 1;
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
        SysCtlDelay(g_ui32Timer/10);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);
        SysCtlDelay(g_ui32Timer/10);
        ConfigureUART();
        InituDMAnUARTTransfer();
        ConfigureTIMER();
    
        while(1)
        {
            if(g_ui8Mode)
            {
                GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
                SysCtlDelay(g_ui32Timer);
                GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);
                TimerIntRegister(TIMER0_BASE, TIMER_A, &TIMERISR);
                IntEnable(INT_TIMER0A);
                TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
                TimerEnable(TIMER0_BASE, TIMER_A);
                TimerLoadSet(TIMER0_BASE, TIMER_A, g_ui32Timer);
                g_ui8Mode = 0;
            }
            else
            {
                ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT);
                if(ui32Mode == UDMA_MODE_STOP)
                {
                    for(ui8Index = 0; ui8Index < UART_BUF_SIZE; ui8Index++)
                    {
                        g_ui8TxBuf[ui8Index] = g_ui8RxBuf[ui8Index] + 1;
                    }
                    for(ui8Index = 0; ui8Index < UART_BUF_SIZE; ui8Index++)
                    {
                        SendUART(g_ui8TxBuf[ui8Index]);
                    }
                    uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, (void *)(UART0_BASE + UART_O_DR), g_ui8RxBuf, sizeof(g_ui8RxBuf));
                    uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
                }
            }
        }
    }
    
    /******************************************
     *          Functions Define
     ******************************************/
    void uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        ui32Status = uDMAErrorStatusGet();
    
        if(ui32Status)
        {
            uDMAErrorStatusClear();
            g_ui32uDMAErrCount++;
        }
    }
    
    void TIMERISR(void)
    {
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        TimerDisable(TIMER0_BASE,TIMER_A);
        TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        g_ui8Mode = 1;
    }
    
    void InituDMAnUARTTransfer(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        IntEnable(INT_UDMAERR);
        uDMAEnable();
        uDMAControlBaseSet(ui8ControlTable);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        IntEnable(INT_UART0);
        UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_EVEN);
        UARTFIFODisable(UART0_BASE);
        UARTEnable(UART0_BASE);
        uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
        uDMAChannelAttributeEnable(UDMA_CHANNEL_UART0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
        uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_8);
        uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, (void *)(UART0_BASE + UART_O_DR), g_ui8RxBuf, sizeof(g_ui8RxBuf));
        uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
        UARTDMAEnable(UART0_BASE, UART_DMA_RX);
    
    }
    
    void ConfigureUART(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    }
    
    void ConfigureTIMER(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
        TimerConfigure(TIMER0_BASE, TIMER_CFG_A_ONE_SHOT);
        TimerLoadSet(TIMER0_BASE, TIMER_A, g_ui32Timer);
        TimerIntRegister(TIMER0_BASE, TIMER_A, &TIMERISR);
        IntEnable(INT_TIMER0A);
        TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        TimerEnable(TIMER0_BASE, TIMER_A);
        g_ui8Mode = 1;
    }
    
    void SendUART(unsigned char X)
    {
        UARTCharPut(UART0_BASE, X);
        if(UARTCharsAvail(UART0_BASE))
        {
            UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE));
        }
    }
    

  • Hi,

     I have modified the exisiting TivaWare uDMA example and make it a simple DMA transfer using basic mode. After you run it you can look at the g_ui32RxBufA and you should see the Rx buffer with the values the same as the g_ui8TxBuf. I will suggest you get the uDMA working first before you incorporate other code such as Timer into your application to make your debug easier. 

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_uart.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "driverlib/udma.h"
    #include "utils/cpu_usage.h"
    #include "utils/uartstdio.h"
    #include "utils/ustdlib.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>uDMA (udma_demo)</h1>
    //!
    //! This example application demonstrates the use of the uDMA controller to
    //! transfer data between memory buffers, and to transfer data to and from a
    //! UART.  The test runs for 10 seconds before exiting.
    //!
    //! UART0, connected to the ICDI virtual COM port and running at 115,200,
    //! 8-N-1, is used to display messages from this application.
    //
    //*****************************************************************************
    
    //****************************************************************************
    //
    // System clock rate in Hz.
    //
    //****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // The number of SysTick ticks per second used for the SysTick interrupt.
    //
    //*****************************************************************************
    #define SYSTICKS_PER_SECOND     100
    
    //*****************************************************************************
    //
    // The size of the memory transfer source and destination buffers (in words).
    //
    //*****************************************************************************
    #define MEM_BUFFER_SIZE         1024
    
    //*****************************************************************************
    //
    // The size of the UART transmit and receive buffers.  They do not need to be
    // the same size.
    //
    //*****************************************************************************
    #define UART_TXBUF_SIZE         256
    #define UART_RXBUF_SIZE         256
    
    
    //*****************************************************************************
    //
    // The transmit and receive buffers used for the UART transfers.
    //
    //*****************************************************************************
    static uint8_t g_ui8TxBuf[UART_TXBUF_SIZE];
    static uint8_t g_ui8RxBufA[UART_RXBUF_SIZE];
    
    //*****************************************************************************
    //
    // The count of uDMA errors.  This value is incremented by the uDMA error
    // handler.
    //
    //*****************************************************************************
    static uint32_t g_ui32uDMAErrCount = 0;
    
    
    //*****************************************************************************
    //
    // The count of UART buffers filled
    //
    //*****************************************************************************
    static uint32_t g_ui32RxBufACount = 0;
    
    //*****************************************************************************
    //
    // The control table used by the uDMA controller.  This table must be aligned
    // to a 1024 byte boundary.
    //
    //*****************************************************************************
    #if defined(ewarm)
    #pragma data_alignment=1024
    uint8_t pui8ControlTable[1024];
    #elif defined(ccs)
    #pragma DATA_ALIGN(pui8ControlTable, 1024)
    uint8_t pui8ControlTable[1024];
    #else
    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
    #endif
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    //*****************************************************************************
    //
    // The interrupt handler for uDMA errors.  This interrupt will occur if the
    // uDMA encounters a bus error while trying to perform a transfer.  This
    // handler just increments a counter if an error occurs.
    //
    //*****************************************************************************
    void
    uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Check for uDMA error bit
        //
        ui32Status = ROM_uDMAErrorStatusGet();
    
        //
        // If there is a uDMA error, then clear the error and increment
        // the error counter.
        //
        if(ui32Status)
        {
            ROM_uDMAErrorStatusClear();
            g_ui32uDMAErrCount++;
        }
    }
    
    
    
    //*****************************************************************************
    //
    // The interrupt handler for UART1.  This interrupt will occur when a DMA
    // transfer is complete using the UART1 uDMA channel.  It will also be
    // triggered if the peripheral signals an error.
    //
    //*****************************************************************************
    void
    UART1IntHandler(void)
    {
        uint32_t ui32Status;
        uint32_t ui32Mode;
    
        //
        // Read the interrupt status of the UART.
        //
        ui32Status = ROM_UARTIntStatus(UART1_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(UART1_BASE, ui32Status);
    
        g_ui32RxBufACount = 1;
    
        ROM_IntDisable(INT_UART1);
        ROM_IntDisable(INT_UDMA);
    
    }
    
    //*****************************************************************************
    //
    // Initializes the UART1 peripheral and sets up the TX and RX uDMA channels.
    // The UART is configured for loopback mode so that any data sent on TX will be
    // received on RX.  The uDMA channels are configured so that the TX channel
    // will copy data from a buffer to the UART TX output.  And the uDMA RX channel
    // will receive any incoming data into the buffers.
    //
    //*****************************************************************************
    void
    InitUART1Transfer(void)
    {
        uint_fast16_t ui16Idx;
    
        //
        // Fill the TX buffer with a simple data pattern.
        //
        for(ui16Idx = 0; ui16Idx < UART_TXBUF_SIZE; ui16Idx++)
        {
            g_ui8TxBuf[ui16Idx] = ui16Idx;
        }
    
        //
        // Enable the UART peripheral, and configure it to operate even if the CPU
        // is in sleep.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART1);
    
        //
        // Configure the UART communication parameters.
        //
        ROM_UARTConfigSetExpClk(UART1_BASE, g_ui32SysClock, 115200,
                                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(UART1_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(UART1_BASE);
        ROM_UARTDMAEnable(UART1_BASE, UART_DMA_RX | UART_DMA_TX);
    
        //
        // This register write will set the UART to operate in loopback mode.  Any
        // data sent on the TX output will be received on the RX input.
        //
        HWREG(UART1_BASE + UART_O_CTL) |= UART_CTL_LBE;
    
        //
        // Put the attributes in a known state for the uDMA UART1RX channel.  These
        // should already be disabled by default.
        //
        ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1RX,
                                         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 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 efficient that single byte transfers.
        //
        ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_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
        // transfer size is set to match the size of the buffer.
        //
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX | UDMA_PRI_SELECT,
        							UDMA_MODE_BASIC,
                                   (void *)(UART1_BASE + UART_O_DR),
                                   g_ui8RxBufA, sizeof(g_ui8RxBufA));
    
    
        //
        // Put the attributes in a known state for the uDMA UART1TX channel.  These
        // should already be disabled by default.
        //
        ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1TX,
                                        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 efficient bus usage
        // than the default which allows single or burst transfers.
        //
        ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_UART1TX, 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_UART1TX | 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_UART1TX | UDMA_PRI_SELECT,
                                   UDMA_MODE_BASIC, g_ui8TxBuf,
                                   (void *)(UART1_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_UART1RX);
        ROM_uDMAChannelEnable(UDMA_CHANNEL_UART1TX);
    
        //
        // Enable the UART DMA TX/RX interrupts.
        //
        ROM_UARTIntEnable(UART1_BASE, UART_INT_DMATX | UART_INT_DMATX);
    
        //
        // Enable the UART peripheral interrupts.
        //
        ROM_IntEnable(INT_UART1);
    }
    
    
    
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, g_ui32SysClock);
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to use the uDMA controller to transfer data
    // between memory buffers and to and from a peripheral, in this case a UART.
    // The uDMA controller is configured to repeatedly transfer a block of data
    // from one memory buffer to another.  It is also set up to repeatedly copy a
    // block of data from a buffer to the UART output.  The UART data is looped
    // back so the same data is received.
    //
    //*****************************************************************************
    int
    main(void)
    {
    
        //
        // Set the clocking to run directly from the crystal at 120MHz.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Enable peripherals to operate when CPU is in sleep.
        //
        ROM_SysCtlPeripheralClockGating(true);
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    
        //
        // Enable the GPIO pins for the LED (PN0).
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
    
        //
        // Initialize the UART.
        //
        ConfigureUART();
    	UARTprintf("\033[2J\033[H");
        UARTprintf("uDMA Example\n");
    
        //
        // Show the clock frequency on the display.
        //
        UARTprintf("Tiva C Series @ %u MHz\n\n", g_ui32SysClock / 1000000);
    
    
        //
        // Enable the uDMA controller at the system level.  Enable it to continue
        // to run while the processor is in sleep.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
    
        //
        // Enable the uDMA controller error interrupt.  This interrupt will occur
        // if there is a bus error during a transfer.
        //
        ROM_IntEnable(INT_UDMAERR);
    
        //
        // Enable the uDMA controller.
        //
        ROM_uDMAEnable();
    
        //
        // Point at the control table to use for channel control structures.
        //
        ROM_uDMAControlBaseSet(pui8ControlTable);
    
        //
        // Initialize the uDMA UART transfers.
        //
        InitUART1Transfer();
    
        //
        // Wait in the while until the DMA transfer has completed
        //
        while(g_ui32RxBufACount == 0x0){
    
        }
    
        UARTprintf("uDMA Example done\n");
    
        //
        // Disable uDMA and UART interrupts now that the test is complete.
        //
        ROM_IntDisable(INT_UART1);
        ROM_IntDisable(INT_UDMA);
    
        //
        // Loop forever with the CPU not sleeping, so the debugger can connect.
        //
        while(1)
        {
    			  //
            // Turn on the LED.
            //
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock / 20 / 3);
    
            //
            // Turn off the LED.
            //
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock / 20 / 3);
        }
    }

  • Hi Charles,

    I really appreciate your code, it's really helpful. I can understand uDMA deeper now, thank you so much.

    However, I still have a question about the data in UART0_BASE. Currently, I assigned data to be read from UART0_BASE and it occurred exactly like I expected. I'm now able to control the time for processing data. But when I send data into the MCU, the pointer of g_ui8RxBuf keeps increasing. So If want to reset the pointer to the beginning of the array,  what should I do? Should I clear it by set all the elements of g_ui8RxBuf array to 0x00? Is there any optimal solution for this situation?

    Regards,

    Nam

  • Dear Charles,

    I tried some methods in order to reset the pointer of Rx Buffer. Currently, I came up with the solution that I recall 3 functions

                uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX,
                                                 UDMA_ATTR_USEBURST |
                                                UDMA_ATTR_HIGH_PRIORITY |
                                                UDMA_ATTR_REQMASK);
                uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                          UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                                          UDMA_ARB_4);
                uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                            UDMA_MODE_BASIC,
                                           (void *)(UART0_BASE + 0),
                                           g_ui8RxBuf, sizeof(g_ui8RxBuf));
    

    Is this an effective way to reset the buffer? 

    Regards,

    Nam

  • Hi Nam,
    I think it should be enough to just call uDMAChannelTransferSet.
  • Dear Charles,

    I found out that I set the size of Rx Buffer array is just enough to fit 1 frame of 8 unsigned chars. So when I send more than 8 chars, overflow will occur (I didn't recognize this so I thought the problem was the pointer). To solve that problem, I increased the size of Buffer and use a flag to control the flow of data. Whenever the received data is processed and responded, all the buffer will be cleared; thus, the process will check the buffer to see whether it matches with the frame or not. Only when the frame matches, the flag will be turned on in order to transmit the next packet. This method will prevent device sends more than 1 packet without receive any response. I also increase the size of Rx Buffer to 64 as a second defend, I tried to increased it to 256 but don't know why the program doesn't work anymore. The code I use is modified from your example, I think I understand a little bit more about uDMA but I'm not sure, can you check the code to make sure that I don't mess it up? Thank you so much!

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_uart.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "driverlib/udma.h"
    #include "utils/cpu_usage.h"
    #include "utils/uartstdio.h"
    #include "utils/ustdlib.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>uDMA (udma_demo)</h1>
    //!
    //! This example application demonstrates the use of the uDMA controller to
    //! transfer data between memory buffers, and to transfer data to and from a
    //! UART.  The test runs for 10 seconds before exiting.
    //!
    //! UART0, connected to the ICDI virtual COM port and running at 115,200,
    //! 8-N-1, is used to display messages from this application.
    //
    //*****************************************************************************
    
    //****************************************************************************
    //
    // System clock rate in Hz.
    //
    //****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // The number of SysTick ticks per second used for the SysTick interrupt.
    //
    //*****************************************************************************
    #define SYSTICKS_PER_SECOND     100
    
    //*****************************************************************************
    //
    // The size of the memory transfer source and destination buffers (in words).
    //
    //*****************************************************************************
    #define MEM_BUFFER_SIZE         1024
    
    //*****************************************************************************
    //
    // The size of the UART transmit and receive buffers.  They do not need to be
    // the same size.
    //
    //*****************************************************************************
    #define UART_BUF_SIZE        64
    
    
    //*****************************************************************************
    //
    // The transmit and receive buffers used for the UART transfers.
    //
    //*****************************************************************************
    static uint8_t g_ui8TxBuf[UART_BUF_SIZE];
    static uint8_t g_ui8RxBuf[UART_BUF_SIZE];
    
    //*****************************************************************************
    //
    // The count of uDMA errors.  This value is incremented by the uDMA error
    // handler.
    //
    //*****************************************************************************
    static uint32_t g_ui32uDMAErrCount = 0;
    
    //*****************************************************************************
    //
    // The count of UART buffers filled
    //
    //*****************************************************************************
    static uint32_t g_ui32RxBufCount = 0;
    
    //*****************************************************************************
    //
    // The control table used by the uDMA controller.  This table must be aligned
    // to a 1024 byte boundary.
    //
    //*****************************************************************************
    #if defined(ewarm)
    #pragma data_alignment=1024
    uint8_t pui8ControlTable[1024];
    #elif defined(ccs)
    #pragma DATA_ALIGN(pui8ControlTable, 1024)
    uint8_t pui8ControlTable[1024];
    #else
    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
    #endif
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    //*****************************************************************************
    //
    // The interrupt handler for uDMA errors.  This interrupt will occur if the
    // uDMA encounters a bus error while trying to perform a transfer.  This
    // handler just increments a counter if an error occurs.
    //
    //*****************************************************************************
    void
    uDMAErrorHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Check for uDMA error bit
        //
        ui32Status = uDMAErrorStatusGet();
    
        //
        // If there is a uDMA error, then clear the error and increment
        // the error counter.
        //
        if(ui32Status)
        {
            uDMAErrorStatusClear();
            g_ui32uDMAErrCount++;
        }
    }
    
    
    
    //*****************************************************************************
    //
    // The interrupt handler for UART0.  This interrupt will occur when a DMA
    // transfer is complete using the UART0 uDMA channel.  It will also be
    // triggered if the peripheral signals an error.
    //
    //*****************************************************************************
    void
    UART0IntHandler(void)
    {
        uint32_t ui32Status;
        uint32_t ui32Mode;
    
        //
        // Read the interrupt status of the UART.
        //
        ui32Status = 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.
        //
        UARTIntClear(UART0_BASE, ui32Status);
        g_ui32RxBufCount++;
    //
        IntDisable(INT_UART0);
        IntDisable(INT_UDMA);
    
    }
    
    //*****************************************************************************
    //
    // Initializes the UART0 peripheral and sets up the TX and RX uDMA channels.
    // The UART is configured for loopback mode so that any data sent on TX will be
    // received on RX.  The uDMA channels are configured so that the TX channel
    // will copy data from a buffer to the UART TX output.  And the uDMA RX channel
    // will receive any incoming data into the buffers.
    //
    //*****************************************************************************
    void
    InitUART0Transfer(void)
    {
        //
        // Enable the UART peripheral, and configure it to operate even if the CPU
        // is in sleep.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    
        // 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.
        //
        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.
        //
        UARTEnable(UART0_BASE);
        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.
        //
        uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX,
                                         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 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 efficient that single byte transfers.
        //
        uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_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
        // transfer size is set to match the size of the buffer.
        //
        uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                    UDMA_MODE_BASIC,
                                   (void *)(UART0_BASE + UART_O_DR),
                                   g_ui8RxBuf, sizeof(g_ui8RxBuf));
    
    
        //
        // Put the attributes in a known state for the uDMA UART0TX channel.  These
        // should already be disabled by default.
        //
        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 efficient bus usage
        // than the default which allows single or burst transfers.
        //
        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.
        //
        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.
        //
        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.
        //
        uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
        uDMAChannelEnable(UDMA_CHANNEL_UART0TX);
    
        //
        // Enable the UART DMA TX/RX interrupts.
        //
        UARTIntEnable(UART0_BASE, UART_INT_DMATX | UART_INT_DMATX);
    
        //
        // Enable the UART peripheral interrupts.
        //
        IntEnable(INT_UART0);
    }
    
    
    
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, g_ui32SysClock);
    }
    
    /*
     * Check data and response
     */
    uint8_t Check(void)
    {
        if(g_ui8RxBuf[0] != 'R')
        {
            return 0;
        }
        return 1;
    }
    
    void TxAssign(void)
    {
        uint8_t ui8Index;
        for(ui8Index = 0; ui8Index < 8; ui8Index++)
        {
            g_ui8TxBuf[ui8Index] = g_ui8RxBuf[ui8Index] + 1;
        }
    }
    
    void ClearBuf(void)
    {
        uint8_t ui8Index;
        for(ui8Index = 0; ui8Index < UART_BUF_SIZE; ui8Index++)
        {
            g_ui8RxBuf[ui8Index] = g_ui8TxBuf[ui8Index] = 0;
        }
    }
    
    void SendTxBuf(void)
    {
        uint8_t ui8Index;
        for(ui8Index = 0; ui8Index < 8; ui8Index++)
        {
            UARTCharPut(UART0_BASE, g_ui8TxBuf[ui8Index]);
            if(UARTCharsAvail(UART0_BASE))
            {
                UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE));
            }
        }
        UARTIntEnable(UART0_BASE, UART_INT_DMATX | UART_INT_DMATX);
    
        //
        // Enable the UART peripheral interrupts.
        //
        IntEnable(INT_UART0);
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to use the uDMA controller to transfer data
    // between memory buffers and to and from a peripheral, in this case a UART.
    // The uDMA controller is configured to repeatedly transfer a block of data
    // from one memory buffer to another.  It is also set up to repeatedly copy a
    // block of data from a buffer to the UART output.  The UART data is looped
    // back so the same data is received.
    //
    //*****************************************************************************
    int
    main(void)
    {
    
        //
        // Set the clocking to run directly from the crystal at 120MHz.
        //
        SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
        g_ui32SysClock = SysCtlClockGet();
    
        //
        // Enable peripherals to operate when CPU is in sleep.
        //
        SysCtlPeripheralClockGating(true);
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PN0).
        //
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    
        //
        // Initialize the UART.
        //
        ConfigureUART();
        UARTprintf("\033[2J\033[H");
        UARTprintf("uDMA Example\n");
    
        //
        // Show the clock frequency on the display.
        //
        UARTprintf("Tiva C Series @ %u MHz\n\n", g_ui32SysClock / 1000000);
    
    
        //
        // Enable the uDMA controller at the system level.  Enable it to continue
        // to run while the processor is in sleep.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
    
        //
        // Enable the uDMA controller error interrupt.  This interrupt will occur
        // if there is a bus error during a transfer.
        //
        IntEnable(INT_UDMAERR);
    
        //
        // Enable the uDMA controller.
        //
        uDMAEnable();
    
        //
        // Point at the control table to use for channel control structures.
        //
        uDMAControlBaseSet(pui8ControlTable);
    
        //
        // Initialize the uDMA UART transfers.
        //
        InitUART0Transfer();
    
        //
        // Wait in the while until the DMA transfer has completed
        //
        while(g_ui32RxBufCount == 0x0){
    
        }
    
        UARTprintf("uDMA Example done\n");
    
    //    //
    //    // Disable uDMA and UART interrupts now that the test is complete.
    //    //
        IntDisable(INT_UART0);
        IntDisable(INT_UDMA);
    
        //
        // Loop forever with the CPU not sleeping, so the debugger can connect.
        //
        while(1)
        {
                  //
            // Turn on the LED.
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock/100);
    
            //
            // Turn off the LED.
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock/100);
    
            if(Check())
            {
                TxAssign();
                SendTxBuf();
            }
            ClearBuf();
            uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                        UDMA_MODE_BASIC,
                                       (void *)(UART0_BASE + UART_O_DR),
                                       g_ui8RxBuf, sizeof(g_ui8RxBuf));
        }
    }
    

    Regards,

    Nam