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.

EK-TM4C1294XL: UART configuration for loop back mode

Part Number: EK-TM4C1294XL

I am currently trying to develop in ARM Keil and am having some difficulty in testing the UART in loop back mode.  
Below is the code I am using (the registers sets are structs, which does make things easier to read)   I tried to use loop back, sending 1 character "U", but I don't see that result when I inspect the DR register after the send.  

//MANUAL UART SETUP OF UART 0 and 1 as well as GPIO ports START
        SYSCTL->RCGCUART |= 0xFF;
        SYSCTL->RCGCGPIO |= 0x3;        
        GPIOA_AHB->DIR |= 0x2; //sets 
        GPIOA_AHB->DEN |= 0x3;
        GPIOA_AHB->AFSEL |= 3;
        GPIOB_AHB->DIR |= 0x2; 
        GPIOB_AHB->DEN |= 0x3;
        GPIOB_AHB->AFSEL |= 3;
        
        GPIOA_AHB->PCTL |= GPIO_PA0_U0RX | GPIO_PA1_U0TX;
        GPIOB_AHB->PCTL |= GPIO_PB0_U1RX | GPIO_PB1_U1TX;
        //MANUAL UART SETUP END
        

        //SET UP BAUD FOR UART 0 START 
        UART0->CTL &= ~0x1; //clear UARTEN        
        UART0->IBRD |= 10; //Set integer part of BDR (BDR = 20000/ ( 16 * baud)
        UART0->FBRD |= 54; // equal to (IBRD  - floor IBRD) * 64 + 0.5)  
        UART0->LCRH |= 0x60; //set WLEN to 8 bits
        UART0->CC = 0; //set up to base clock divisor to RSCLKCFG.
        UART0->DMACTL |= 3;
        UART0->CTL |= (3 << 8); //enable TX and RX
        UART0->CTL |= (1 << 7); //enable loop back
        UART0->CTL &= ~0x1; //clear UARTEN      
//        //SET UP BAUD FOR UART 0 END
        
//        //SET UP BAUD FOR UART 1 START 
        UART1->CTL &=~ 0x1; //clear UARTEN        
        UART1->IBRD |= 10; //Set integer part of BDR (BDR = 20000/ ( 16 * baud)
        UART1->FBRD |= 54; // equal to (IBRD  - floor IBRD) * 64 + 0.5)  
        UART1->LCRH |= 0x60; //set WLEN to 8 bits
        UART1->CC = 0; //set up to base clock divisor to RSCLKCFG.
        UART1->DMACTL |= 3;
        UART1->CTL |= (3 << 8); //enable TX and RX
        UART1->CTL |= (1 << 7); //enable loop back
        UART1->CTL &= ~0x1; //clear UARTEN    
        
        
        while( UART1->FR  & UART_FR_TXFF)
        {
            //While tx full, wait.
        }
        
        UART1->DR = (unsigned char)('x');
        
        
        volatile unsigned char  testResult[64];
        if( UART1->FR & UART_FR_RXFE )
        {
            testResult[0] = UART1->DR;
            testResult[1] = (unsigned char)('s');            
            testResult[2] = (unsigned char)('i');            
        }




  • We strongly discourage the use of direct register writes similar to what you have done in the code above. Rather we recommend the use of the TivaWare library to configure the pins and peripherals. It will make your code easier to write, easier to understand and more likely to be error free. Take a look at the attached example that puts UART0 in loopback mode: /cfs-file/__key/communityserver-discussions-components-files/908/4885.main.c

  • I have tried to use the file specified in the comments, though I am finding that while I could run this in Keil, I am having trouble running it in CCS.  I wanted to try to do this file in CCS to simplify any needed support so it would be all from TI.   When I try to load my board in CCS though, it isn't able to start.  It just hangs in boot_cortex_m.c it seems.  Keil didn't have this issue.  Is this a known problem? I like CCS's register view better and would actually prefer to use it.

    If I reset it, it will get stuck in boot_cortex_m.c line 118. If I do not, it just hangs without ever starting any code.

    __attribute__((section(".text:_c_int00_noargs"), used, naked))
    void _c_int00_noargs(void)
    {
    _c_int00_template(0, 1);
    }

    but never goes further. 

    My CMD file is the following (the default one for my board):

    /******************************************************************************
     *
     * Default Linker Command file for the Texas Instruments TM4C1294NCPDT
     *
     * This is derived from revision 15071 of the TivaWare Library.
     *
     *****************************************************************************/
    
    --retain=g_pfnVectors
    
    MEMORY
    {
        FLASH (RX) : origin = 0x00000000, length = 0x00100000
        SRAM (RWX) : origin = 0x20000000, length = 0x00040000
    }
    
    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M4_T_le_eabi.lib                                           */
    
    /* Section allocation in memory */
    
    SECTIONS
    {
        .intvecs:   > 0x00000000
        .text   :   > FLASH
        .const  :   > FLASH
        .cinit  :   > FLASH
        .pinit  :   > FLASH
        .init_array : > FLASH
    
        .vtable :   > 0x20000000
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM
    }
    
    __STACK_TOP = __stack + 512;
    

  • The startup files are different between the Keil compiler and the TI compiler. I have attached the entire CCS project in a .zip file. Use the CCS feature of "File" -> "Import" to import this project directly from the .zip file into your workspace./cfs-file/__key/communityserver-discussions-components-files/908/uart0_5F00_loopback.zip

  • Thanks this allowed me to at least get this code loaded on my board. I'll try some further tests to see if it all works as expected.

  • I was able to get the UART code working in C.   However, when I try to use this same code in C++ I am not able to get it to work.   It goes into the FaultISR call when I try this in C++. 

    Were any of these drivers created with C++ in mind?

  • When trying to do the same steps in the example but via a class it always goes into a the fault ISR.  I'll post the class/cpp files: 

    /*
     * uartDriver.h
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #ifndef UARTDRIVER_H_
    #define UARTDRIVER_H_
    
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    #include "utils/uartstdio.h"
    
    
    class UARTCtrl
    {
    public:
        UARTCtrl();
        //Configure UART
        UARTCtrl & setCurUart( uint32_t index );
        UARTCtrl & setConfigPins(void);
        UARTCtrl & setFifoEn(void);
        UARTCtrl & setBaud(uint32_t baudVal);
        UARTCtrl & setParity(uint32_t parVal);
        UARTCtrl & setDataLen(uint32_t val);
        UARTCtrl & setNumStopBits(uint32_t val);
        UARTCtrl & setSysClk(uint32_t extClkDef, uint32_t oscSource, uint32_t sysClkPllOsc, uint32_t vcoFreq, uint32_t sysFreq);
        UARTCtrl & setUartIO(); //only for 0-3
        UARTCtrl & setUartExpClk();
        UARTCtrl & setLoopback();
    
        void charPut( uint32_t index, char val );
        char charGet( uint32_t index );
        void uprintf( const char * pcString, ...);
        int  UARTgets(char *pcBuf, uint32_t ui32Len);
    
    
    private:
        uint32_t m_ui32SysClock;
        uint32_t m_curBase;
        uint32_t m_curIndex;
        uint32_t m_curParity;
        uint32_t m_curDataLen;
        uint32_t m_curNumStopBits;
        uint32_t m_curBaudRate;
        uint32_t m_baseArray[8];
        uint32_t m_gpioArray[8];
        uint32_t m_gpioBArray[8];
        uint32_t m_uartEnArray[8];
        uint32_t m_pinArray[16];
        uint32_t m_pinCfgArray[16];
    
    };
    
    
    
    #endif /* UARTDRIVER_H_ */
    
    /*
     * uartDriver.cpp
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #include "uartDriver.h"
    
    extern "C"
    {
        UARTCtrl::UARTCtrl()
        {
            //Use this one as the default for now.
            m_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_240), 120000000);
            m_curBase = UART0_BASE;
            m_curParity = UART_CONFIG_PAR_NONE;
            m_curDataLen = UART_CONFIG_WLEN_8;
            m_curNumStopBits = UART_CONFIG_STOP_ONE;
            m_curBaudRate = 115200; //default baud we will use
    
            //Copy the bases into an array for easier usage.
            m_baseArray[0] = UART0_BASE;
            m_baseArray[1] = UART1_BASE;
            m_baseArray[2] = UART2_BASE;
            m_baseArray[3] = UART3_BASE;
            m_baseArray[4] = UART4_BASE;
            m_baseArray[5] = UART5_BASE;
            m_baseArray[6] = UART6_BASE;
            m_baseArray[7] = UART7_BASE;
    
            m_gpioArray[0] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[1] = SYSCTL_PERIPH_GPIOB;
            m_gpioArray[2] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[3] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[4] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[5] = SYSCTL_PERIPH_GPIOC;
            m_gpioArray[6] = SYSCTL_PERIPH_GPIOP;
            m_gpioArray[7] = SYSCTL_PERIPH_GPIOC;
    
            m_gpioBArray[0] = GPIO_PORTA_BASE;
            m_gpioBArray[1] = GPIO_PORTB_BASE;
            m_gpioBArray[2] = GPIO_PORTA_BASE;
            m_gpioBArray[3] = GPIO_PORTA_BASE;
            m_gpioBArray[4] = GPIO_PORTA_BASE;
            m_gpioBArray[5] = GPIO_PORTC_BASE;
            m_gpioBArray[6] = GPIO_PORTP_BASE;
            m_gpioBArray[7] = GPIO_PORTC_BASE;
    
            m_uartEnArray[0] = SYSCTL_PERIPH_UART0;
            m_uartEnArray[1] = SYSCTL_PERIPH_UART1;
            m_uartEnArray[2] = SYSCTL_PERIPH_UART2;
            m_uartEnArray[3] = SYSCTL_PERIPH_UART3;
            m_uartEnArray[4] = SYSCTL_PERIPH_UART4;
            m_uartEnArray[5] = SYSCTL_PERIPH_UART5;
            m_uartEnArray[6] = SYSCTL_PERIPH_UART6;
            m_uartEnArray[7] = SYSCTL_PERIPH_UART7;
    
            m_pinArray[0] = GPIO_PIN_0; //0 a
            m_pinArray[1] = GPIO_PIN_1;
            m_pinArray[2] = GPIO_PIN_0; //1 b
            m_pinArray[3] = GPIO_PIN_1;
            m_pinArray[4] = GPIO_PIN_6; //2 a
            m_pinArray[5] = GPIO_PIN_7;
            m_pinArray[6] = GPIO_PIN_4; //3 a
            m_pinArray[7] = GPIO_PIN_5;
            m_pinArray[8] = GPIO_PIN_2; //4 a
            m_pinArray[9] = GPIO_PIN_3;
            m_pinArray[10] = GPIO_PIN_6; //5 c
            m_pinArray[11] = GPIO_PIN_7;
            m_pinArray[12] = GPIO_PIN_0; //6 p
            m_pinArray[13] = GPIO_PIN_1;
            m_pinArray[14] = GPIO_PIN_4; //7 c
            m_pinArray[15] = GPIO_PIN_5;
    
            m_pinCfgArray[0] = GPIO_PA0_U0RX; //0
            m_pinCfgArray[1] = GPIO_PA1_U0TX;
            m_pinCfgArray[2] = GPIO_PB0_U1RX; //1
            m_pinCfgArray[3] = GPIO_PB1_U1TX;
            m_pinCfgArray[4] = GPIO_PA6_U2RX; //2
            m_pinCfgArray[5] = GPIO_PA7_U2TX;
            m_pinCfgArray[6] = GPIO_PA4_U3RX; //3
            m_pinCfgArray[7] = GPIO_PA5_U3TX;
            m_pinCfgArray[8] = GPIO_PA2_U4RX; //4
            m_pinCfgArray[9] = GPIO_PA3_U4TX;
            m_pinCfgArray[10] = GPIO_PC6_U5RX; //5
            m_pinCfgArray[11] = GPIO_PC7_U5TX;
            m_pinCfgArray[12] = GPIO_PP0_U6RX; //6
            m_pinCfgArray[13] = GPIO_PP1_U6TX;
            m_pinCfgArray[14] = GPIO_PC4_U7RX; //7
            m_pinCfgArray[15] = GPIO_PC5_U7TX;
        }
        UARTCtrl & UARTCtrl::setConfigPins(void)
        {
            SysCtlPeripheralEnable(m_gpioArray[m_curIndex]);
            SysCtlPeripheralEnable(m_uartEnArray[m_curIndex]);
            uint32_t curIndexDual = m_curIndex << 1;
            GPIOPinConfigure(m_pinCfgArray[curIndexDual]);
            GPIOPinConfigure(m_pinCfgArray[curIndexDual+1]);
            GPIOPinTypeUART(m_gpioBArray[m_curIndex], m_pinArray[curIndexDual] | m_pinArray[curIndexDual+1]);
        }
        UARTCtrl & UARTCtrl::setCurUart( uint32_t index )
        {
            m_curIndex = index;
            m_curBase = m_baseArray[index];
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setFifoEn(void)
        {
            UARTFIFOEnable(m_curBase);
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setBaud(uint32_t baudVal)
        {
            m_curBaudRate = baudVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setParity(uint32_t parVal)
        {
            m_curParity = parVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setDataLen( uint32_t val )
        {
            m_curDataLen = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setNumStopBits(uint32_t val)
        {
            m_curNumStopBits = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setSysClk(uint32_t extClkDef, uint32_t oscSource, uint32_t sysClkPllOsc, uint32_t vcoFreq, uint32_t sysFreq)
        {
            uint32_t clkCfg = extClkDef | oscSource | sysClkPllOsc | vcoFreq;
            m_ui32SysClock = SysCtlClockFreqSet( clkCfg, sysFreq );
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setUartIO()
        {
            if( m_curIndex < 3 )
            {
                UARTStdioConfig(m_curIndex, m_curBaudRate, m_ui32SysClock);
            }
    
            return *this;
        } //only for 0-3
    
        UARTCtrl & UARTCtrl::setUartExpClk()
        {
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setLoopback() //do last in config.
        {
            UARTLoopbackEnable(m_curBase);
            return *this;
        }
    
        void UARTCtrl::charPut(uint32_t index, char val)
        {
            UARTCharPut(m_baseArray[index], val);
        }
    
        char UARTCtrl::charGet(uint32_t index)
        {
            return UARTCharGet( m_baseArray[index] );
        }
    
        void UARTCtrl::uprintf( const char * pcString, ...)
        {
            //index is set when setUartIO is called
            va_list vaArgP;
            va_start( vaArgP, pcString );
    
            UARTvprintf( pcString, vaArgP);
            va_end(vaArgP);
        }
    
        int UARTCtrl::UARTgets(char *pcBuf, uint32_t ui32Len)
        {
            //index is set when setUartIO is called
            UARTgets( pcBuf, ui32Len );
        }
    
    }
    

  • In main I have

    int
    main(void)
    {
            UARTCtrl uart;
    
            uart.setCurUart(0);
            uart.setSysClk(SYSCTL_XTAL_25MHZ,
                           SYSCTL_OSC_MAIN,
                           SYSCTL_USE_PLL,
                           SYSCTL_CFG_VCO_240,
                           120000000);
            uart.setConfigPins().setUartExpClk().setFifoEn().setUartIO().setLoopback();
    
            uart.charPut(0, 'U');
            g_c = uart.charGet(0);
    
            uart.uprintf("\nHello, world! %c", g_c);
    
            return 0;
    }

  • Often the fault ISR is reached when accessing a peripheral before it was enabled. It usually helps to step through the code (sometimes down to the assembly level) to identify what caused the fault. Here is an older application note that is also useful in identifying the issue in the code that caused the fault.

    https://www.ti.com/lit/an/spma043/spma043.pdf

  • Hi John,

    John Chaparro said:
    When trying to do the same steps in the example but via a class it always goes into a the fault ISR.  I'll post the class/cpp files: 

    The project compiles without symbol exceptions or warnings? I never could get Tivaware calls and C++ public/class to work together for another UART project. I think it has something to do with the tool chain Thumb compiler or the linker not switching to GNU C++ compiler midstream but that is an CCS issue anyway. For now it seems we can not mix the two seemingly the linker gets lost unless there is inline directive to force the change.

  • I don't get any warnings or linking errors.  Will keep trying and if I get it working I'll post the source here.

    (I did have 2 instances that I forgot to put return values, but that isn't related to the issues you mentioned.)

  • It seems that it faults when it encounters the "UARTCtrl uart;"   line.

    I removed the sys clock setting from the driver and put 

    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_240), 120000000);

    at the top of my main function.  It goes to the fault call when it reaches this line.

  • Here is the current source code:  

    main.cpp

    //*****************************************************************************
    //
    // Copyright (c) 2012-2020 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    #include "utils/uartstdio.h"
    
    #include "uartDriver.h"
    
    #define DEBUG
    //*****************************************************************************
    //
    // System clock rate in Hz.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    volatile char g_c;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    extern "C" void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    //extern "C" void ConfigureUART(void)
    //{
    //    //
    //    // Enable the GPIO Peripheral used by the UART.
    //    //
    //    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //
    //    //
    //    // Enable UART0
    //    //
    //    SysCtlPeripheralEnable(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.
    //    //
    //    UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
    //                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    //                                    UART_CONFIG_PAR_NONE));
    //    UARTFIFOEnable(UART0_BASE);
    //
    //    UARTStdioConfig(0, 115200, g_ui32SysClock);
    //}
    
    //*****************************************************************************
    //
    // Main 'C' Language entry point.
    //
    //*****************************************************************************
    extern "C" int main(void)
    {
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_240), 120000000);
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        UARTCtrl uart;
    //
        uart.setCurUart(0).setSysClk(g_ui32SysClock).setConfigPins();
        uart.setUartExpClk().setFifoEn().setUartIO().setLoopback();
    
    
        uart.charPut(0, 'U');
        g_c = uart.charGet(0);
    
        uart.uprintf("\nHello, world! %c", g_c);
    
    
    //    //
    //    // Run from the PLL at 120 MHz.
    //    // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
    //    // later to better reflect the actual VCO speed due to SYSCTL#22.
    //    //
    //    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
    //                                           SYSCTL_OSC_MAIN |
    //                                           SYSCTL_USE_PLL |
    //                                           SYSCTL_CFG_VCO_240), 120000000);
    //
    //    //
    //    // Initialize the UART.
    //    //
    //    ConfigureUART();
    //    UARTLoopbackEnable(UART0_BASE);
    //    UARTCharPut(UART0_BASE, 'U');
    //    g_c = UARTCharGet(UART0_BASE);
    //
    //    UARTprintf("\nHello, world!\n");
    
    
    }
    
    
    
    --------------------------------------------------------------------------------------------------------------------------

    uartDriver.h

    /*
     * uartDriver.h
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #ifndef UARTDRIVER_H_
    #define UARTDRIVER_H_
    
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    #include "utils/uartstdio.h"
    
    
    class UARTCtrl
    {
    public:
        UARTCtrl();
        //Configure UART
        UARTCtrl & setCurUart( uint32_t index );
        UARTCtrl & setConfigPins(void);
        UARTCtrl & setFifoEn(void);
        UARTCtrl & setBaud(uint32_t baudVal);
        UARTCtrl & setParity(uint32_t parVal);
        UARTCtrl & setDataLen(uint32_t val);
        UARTCtrl & setNumStopBits(uint32_t val);
        UARTCtrl & setSysClk(uint32_t clk);
        UARTCtrl & setUartIO(); //only for 0-3
        UARTCtrl & setUartExpClk();
        UARTCtrl & setLoopback();
    
        void charPut( uint32_t index, char val );
        char charGet( uint32_t index );
        void uprintf( const char * pcString, ...);
        int  UARTgets(char *pcBuf, uint32_t ui32Len);
    
    
    private:
        uint32_t m_ui32SysClock;
        uint32_t m_curBase;
        uint32_t m_curIndex;
        uint32_t m_curParity;
        uint32_t m_curDataLen;
        uint32_t m_curNumStopBits;
        uint32_t m_curBaudRate;
        uint32_t m_baseArray[8];
        uint32_t m_gpioArray[8];
        uint32_t m_gpioBArray[8];
        uint32_t m_uartEnArray[8];
        uint32_t m_pinArray[16];
        uint32_t m_pinCfgArray[16];
    
    };
    
    
    
    #endif /* UARTDRIVER_H_ */
    

    --------------------------------------------------------------------------------------------------------------------------

    uartDriver.cpp

    /*
     * uartDriver.cpp
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #include "uartDriver.h"
    
    extern "C"
    {
        UARTCtrl::UARTCtrl()
        {
            //Use this one as the default for now.
            m_ui32SysClock = 0;
            m_curBase = UART0_BASE;
            m_curParity = UART_CONFIG_PAR_NONE;
            m_curDataLen = UART_CONFIG_WLEN_8;
            m_curNumStopBits = UART_CONFIG_STOP_ONE;
            m_curBaudRate = 115200; //default baud we will use
    
            //Copy the bases into an array for easier usage.
            m_baseArray[0] = UART0_BASE;
            m_baseArray[1] = UART1_BASE;
            m_baseArray[2] = UART2_BASE;
            m_baseArray[3] = UART3_BASE;
            m_baseArray[4] = UART4_BASE;
            m_baseArray[5] = UART5_BASE;
            m_baseArray[6] = UART6_BASE;
            m_baseArray[7] = UART7_BASE;
    
            m_gpioArray[0] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[1] = SYSCTL_PERIPH_GPIOB;
            m_gpioArray[2] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[3] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[4] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[5] = SYSCTL_PERIPH_GPIOC;
            m_gpioArray[6] = SYSCTL_PERIPH_GPIOP;
            m_gpioArray[7] = SYSCTL_PERIPH_GPIOC;
    
            m_gpioBArray[0] = GPIO_PORTA_BASE;
            m_gpioBArray[1] = GPIO_PORTB_BASE;
            m_gpioBArray[2] = GPIO_PORTA_BASE;
            m_gpioBArray[3] = GPIO_PORTA_BASE;
            m_gpioBArray[4] = GPIO_PORTA_BASE;
            m_gpioBArray[5] = GPIO_PORTC_BASE;
            m_gpioBArray[6] = GPIO_PORTP_BASE;
            m_gpioBArray[7] = GPIO_PORTC_BASE;
    
            m_uartEnArray[0] = SYSCTL_PERIPH_UART0;
            m_uartEnArray[1] = SYSCTL_PERIPH_UART1;
            m_uartEnArray[2] = SYSCTL_PERIPH_UART2;
            m_uartEnArray[3] = SYSCTL_PERIPH_UART3;
            m_uartEnArray[4] = SYSCTL_PERIPH_UART4;
            m_uartEnArray[5] = SYSCTL_PERIPH_UART5;
            m_uartEnArray[6] = SYSCTL_PERIPH_UART6;
            m_uartEnArray[7] = SYSCTL_PERIPH_UART7;
    
            m_pinArray[0] = GPIO_PIN_0; //0 a
            m_pinArray[1] = GPIO_PIN_1;
            m_pinArray[2] = GPIO_PIN_0; //1 b
            m_pinArray[3] = GPIO_PIN_1;
            m_pinArray[4] = GPIO_PIN_6; //2 a
            m_pinArray[5] = GPIO_PIN_7;
            m_pinArray[6] = GPIO_PIN_4; //3 a
            m_pinArray[7] = GPIO_PIN_5;
            m_pinArray[8] = GPIO_PIN_2; //4 a
            m_pinArray[9] = GPIO_PIN_3;
            m_pinArray[10] = GPIO_PIN_6; //5 c
            m_pinArray[11] = GPIO_PIN_7;
            m_pinArray[12] = GPIO_PIN_0; //6 p
            m_pinArray[13] = GPIO_PIN_1;
            m_pinArray[14] = GPIO_PIN_4; //7 c
            m_pinArray[15] = GPIO_PIN_5;
    
            m_pinCfgArray[0] = GPIO_PA0_U0RX; //0
            m_pinCfgArray[1] = GPIO_PA1_U0TX;
            m_pinCfgArray[2] = GPIO_PB0_U1RX; //1
            m_pinCfgArray[3] = GPIO_PB1_U1TX;
            m_pinCfgArray[4] = GPIO_PA6_U2RX; //2
            m_pinCfgArray[5] = GPIO_PA7_U2TX;
            m_pinCfgArray[6] = GPIO_PA4_U3RX; //3
            m_pinCfgArray[7] = GPIO_PA5_U3TX;
            m_pinCfgArray[8] = GPIO_PA2_U4RX; //4
            m_pinCfgArray[9] = GPIO_PA3_U4TX;
            m_pinCfgArray[10] = GPIO_PC6_U5RX; //5
            m_pinCfgArray[11] = GPIO_PC7_U5TX;
            m_pinCfgArray[12] = GPIO_PP0_U6RX; //6
            m_pinCfgArray[13] = GPIO_PP1_U6TX;
            m_pinCfgArray[14] = GPIO_PC4_U7RX; //7
            m_pinCfgArray[15] = GPIO_PC5_U7TX;
        }
        UARTCtrl & UARTCtrl::setConfigPins(void)
        {
            SysCtlPeripheralEnable(m_gpioArray[m_curIndex]);
            SysCtlPeripheralEnable(m_uartEnArray[m_curIndex]);
            uint32_t curIndexDual = m_curIndex << 1;
            GPIOPinConfigure(m_pinCfgArray[curIndexDual]);
            GPIOPinConfigure(m_pinCfgArray[curIndexDual+1]);
            GPIOPinTypeUART(m_gpioBArray[m_curIndex], m_pinArray[curIndexDual] | m_pinArray[curIndexDual+1]);
    
            return *this;
        }
        UARTCtrl & UARTCtrl::setCurUart( uint32_t index )
        {
            m_curIndex = index;
            m_curBase = m_baseArray[index];
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setFifoEn(void)
        {
            UARTFIFOEnable(m_curBase);
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setBaud(uint32_t baudVal)
        {
            m_curBaudRate = baudVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setParity(uint32_t parVal)
        {
            m_curParity = parVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setDataLen( uint32_t val )
        {
            m_curDataLen = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setNumStopBits(uint32_t val)
        {
            m_curNumStopBits = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setSysClk( uint32_t clk )
        {
            m_ui32SysClock = clk;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setUartIO()
        {
            if( m_curIndex < 3 )
            {
                UARTStdioConfig(m_curIndex, m_curBaudRate, m_ui32SysClock);
            }
    
            return *this;
        } //only for 0-3
    
        UARTCtrl & UARTCtrl::setUartExpClk()
        {
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setLoopback() //do last in config.
        {
            UARTLoopbackEnable(m_curBase);
            return *this;
        }
    
        void UARTCtrl::charPut(uint32_t index, char val)
        {
            UARTCharPut(m_baseArray[index], val);
        }
    
        char UARTCtrl::charGet(uint32_t index)
        {
            return UARTCharGet( m_baseArray[index] );
        }
    
        void UARTCtrl::uprintf( const char * pcString, ...)
        {
            //index is set when setUartIO is called
            va_list vaArgP;
            va_start( vaArgP, pcString );
    
            UARTvprintf( pcString, vaArgP);
            va_end(vaArgP);
        }
    
        int UARTCtrl::UARTgets(char *pcBuf, uint32_t ui32Len)
        {
            //index is set when setUartIO is called
            return UARTgets( pcBuf, ui32Len );
        }
    
    }
    

  • Made some headway so I thought I'd share my source:  Ran into a very odd behavior:  Depending on what was called, the RXFE would change from low after I sent a char to high before I could read the char out.   This caused an infinite loop.  When I tried using uprintf call with an empty ""  argument at the end of the configuration, this behavior stopped.   Not really any clue why.   If I could figure that out, it is close to working as hoped.

    main.cpp     ----------------------------------------------------------------

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    #include "utils/uartstdio.h"
    
    #include "uartDriver.h"
    
    #define DEBUG
    //*****************************************************************************
    //
    // System clock rate in Hz.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    volatile char g_c;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    extern "C" void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // Main 'C' Language entry point.
    //
    //*****************************************************************************
    int main(void)
    {
        //Set sysClk.
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_240), 120000000);
        // Enable the GPIO Peripheral used by the UART.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        // Enable UART0
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //Set to static:  non-static seems to not work.
        static UARTCtrl uart;
        //Configure selected UART.
        uart.setCurUart(0).setSysClk(g_ui32SysClock).setConfigPins();
    
        //Setup baud and ext clock.  ext clock should be called last.
        uart.setBaud(115200).setDataLen(UART_CONFIG_WLEN_8).setParity(UART_CONFIG_PAR_NONE).setUartExpClk();
    
        //Optional configs
        uart.setFifoEn().setUartIO().setLoopback();
        //not sure why i need to do this:  very odd but charGet fails without.
        uart.endConfig();
    
        //Test charPut charGet and uprintf.
        uart.charPut(0, 'U');
        g_c = uart.charGet(0);
        uart.uprintf("\nHello, world! \n");
    }
    
    
    

    uartDriver.h       --------------------------------------------------------------

    /*
     * uartDriver.h
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #ifndef UARTDRIVER_H_
    #define UARTDRIVER_H_
    
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "drivers/pinout.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    #include "utils/uartstdio.h"
    
    //move into it a util class header:
    #define NOP __asm("    NOP")
    
    class UARTCtrl
    {
    public:
        UARTCtrl();
        //Configure UART
        UARTCtrl & setCurUart( uint32_t index );
        UARTCtrl & setConfigPins(void);
        UARTCtrl & setFifoEn(void);
        UARTCtrl & setBaud(uint32_t baudVal);
        UARTCtrl & setParity(uint32_t parVal);
        UARTCtrl & setDataLen(uint32_t val);
        UARTCtrl & setNumStopBits(uint32_t val);
        UARTCtrl & setSysClk(uint32_t clk);
        UARTCtrl & setUartIO(); //only for 0-3
        UARTCtrl & setUartExpClk();
        UARTCtrl & setLoopback();
    
        void endConfig();
    
        void charPut( uint32_t index, char val );
        char charGet( uint32_t index );
        void uprintf( const char * pcString, ...);
        int  UARTgets(char *pcBuf, uint32_t ui32Len);
    
    
    private:
        uint32_t m_ui32SysClock;
        uint32_t m_curBase;
        uint32_t m_curIndex;
        uint32_t m_curParity;
        uint32_t m_curDataLen;
        uint32_t m_curNumStopBits;
        uint32_t m_curBaudRate;
        uint32_t m_baseArray[8];
        uint32_t m_gpioArray[8];
        uint32_t m_gpioBArray[8];
        uint32_t m_uartEnArray[8];
        uint32_t m_pinArray[16];
        uint32_t m_pinCfgArray[16];
    
    };
    
    
    
    #endif /* UARTDRIVER_H_ */
    

    uartDriver.cpp   --------------------------------------------------------------

    /*
     * uartDriver.cpp
     *
     *  Created on: Jun 9, 2020
     *      Author: chaparrojd
     */
    
    #include "uartDriver.h"
    
    extern "C"
    {
        UARTCtrl::UARTCtrl()
        {
            //Use this one as the default for now.
            m_ui32SysClock = 0;
            m_curBase = UART0_BASE;
            m_curParity = UART_CONFIG_PAR_NONE;
            m_curDataLen = UART_CONFIG_WLEN_8;
            m_curNumStopBits = UART_CONFIG_STOP_ONE;
            m_curBaudRate = 115200; //default baud we will use
    
            //Copy the bases into an array for easier usage.
            m_baseArray[0] = UART0_BASE;
            m_baseArray[1] = UART1_BASE;
            m_baseArray[2] = UART2_BASE;
            m_baseArray[3] = UART3_BASE;
            m_baseArray[4] = UART4_BASE;
            m_baseArray[5] = UART5_BASE;
            m_baseArray[6] = UART6_BASE;
            m_baseArray[7] = UART7_BASE;
    
            m_gpioArray[0] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[1] = SYSCTL_PERIPH_GPIOB;
            m_gpioArray[2] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[3] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[4] = SYSCTL_PERIPH_GPIOA;
            m_gpioArray[5] = SYSCTL_PERIPH_GPIOC;
            m_gpioArray[6] = SYSCTL_PERIPH_GPIOP;
            m_gpioArray[7] = SYSCTL_PERIPH_GPIOC;
    
            m_gpioBArray[0] = GPIO_PORTA_BASE;
            m_gpioBArray[1] = GPIO_PORTB_BASE;
            m_gpioBArray[2] = GPIO_PORTA_BASE;
            m_gpioBArray[3] = GPIO_PORTA_BASE;
            m_gpioBArray[4] = GPIO_PORTA_BASE;
            m_gpioBArray[5] = GPIO_PORTC_BASE;
            m_gpioBArray[6] = GPIO_PORTP_BASE;
            m_gpioBArray[7] = GPIO_PORTC_BASE;
    
            m_uartEnArray[0] = SYSCTL_PERIPH_UART0;
            m_uartEnArray[1] = SYSCTL_PERIPH_UART1;
            m_uartEnArray[2] = SYSCTL_PERIPH_UART2;
            m_uartEnArray[3] = SYSCTL_PERIPH_UART3;
            m_uartEnArray[4] = SYSCTL_PERIPH_UART4;
            m_uartEnArray[5] = SYSCTL_PERIPH_UART5;
            m_uartEnArray[6] = SYSCTL_PERIPH_UART6;
            m_uartEnArray[7] = SYSCTL_PERIPH_UART7;
    
            m_pinArray[0] = GPIO_PIN_0; //0 a
            m_pinArray[1] = GPIO_PIN_1;
            m_pinArray[2] = GPIO_PIN_0; //1 b
            m_pinArray[3] = GPIO_PIN_1;
            m_pinArray[4] = GPIO_PIN_6; //2 a
            m_pinArray[5] = GPIO_PIN_7;
            m_pinArray[6] = GPIO_PIN_4; //3 a
            m_pinArray[7] = GPIO_PIN_5;
            m_pinArray[8] = GPIO_PIN_2; //4 a
            m_pinArray[9] = GPIO_PIN_3;
            m_pinArray[10] = GPIO_PIN_6; //5 c
            m_pinArray[11] = GPIO_PIN_7;
            m_pinArray[12] = GPIO_PIN_0; //6 p
            m_pinArray[13] = GPIO_PIN_1;
            m_pinArray[14] = GPIO_PIN_4; //7 c
            m_pinArray[15] = GPIO_PIN_5;
    
            m_pinCfgArray[0] = GPIO_PA0_U0RX; //0
            m_pinCfgArray[1] = GPIO_PA1_U0TX;
            m_pinCfgArray[2] = GPIO_PB0_U1RX; //1
            m_pinCfgArray[3] = GPIO_PB1_U1TX;
            m_pinCfgArray[4] = GPIO_PA6_U2RX; //2
            m_pinCfgArray[5] = GPIO_PA7_U2TX;
            m_pinCfgArray[6] = GPIO_PA4_U3RX; //3
            m_pinCfgArray[7] = GPIO_PA5_U3TX;
            m_pinCfgArray[8] = GPIO_PA2_U4RX; //4
            m_pinCfgArray[9] = GPIO_PA3_U4TX;
            m_pinCfgArray[10] = GPIO_PC6_U5RX; //5
            m_pinCfgArray[11] = GPIO_PC7_U5TX;
            m_pinCfgArray[12] = GPIO_PP0_U6RX; //6
            m_pinCfgArray[13] = GPIO_PP1_U6TX;
            m_pinCfgArray[14] = GPIO_PC4_U7RX; //7
            m_pinCfgArray[15] = GPIO_PC5_U7TX;
        }
        UARTCtrl & UARTCtrl::setConfigPins(void)
        {
            SysCtlPeripheralEnable(m_gpioArray[m_curIndex]);
            SysCtlPeripheralEnable(m_uartEnArray[m_curIndex]);
            uint32_t curIndexDual = m_curIndex << 1;
            GPIOPinConfigure(m_pinCfgArray[curIndexDual]);
            GPIOPinConfigure(m_pinCfgArray[curIndexDual+1]);
            GPIOPinTypeUART(m_gpioBArray[m_curIndex], m_pinArray[curIndexDual] | m_pinArray[curIndexDual+1]);
    
            return *this;
        }
        UARTCtrl & UARTCtrl::setCurUart( uint32_t index )
        {
            m_curIndex = index;
            m_curBase = m_baseArray[index];
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setFifoEn(void)
        {
            UARTFIFOEnable(m_curBase);
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setBaud(uint32_t baudVal)
        {
            m_curBaudRate = baudVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setParity(uint32_t parVal)
        {
            m_curParity = parVal;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setDataLen( uint32_t val )
        {
            m_curDataLen = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setNumStopBits(uint32_t val)
        {
            m_curNumStopBits = val;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setSysClk( uint32_t clk )
        {
            m_ui32SysClock = clk;
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setUartIO()
        {
            if( m_curIndex < 3 )
            {
                UARTStdioConfig(m_curIndex, m_curBaudRate, m_ui32SysClock);
            }
    
            return *this;
        } //only for 0-3
    
        UARTCtrl & UARTCtrl::setUartExpClk()
        {
            UARTConfigSetExpClk(m_curBase, m_ui32SysClock, m_curBaudRate,
                                (m_curDataLen | m_curNumStopBits | m_curParity));
            return *this;
        }
    
        UARTCtrl & UARTCtrl::setLoopback() //do last in config.
        {
            UARTLoopbackEnable(m_curBase);
            return *this;
        }
    
        void UARTCtrl::charPut(uint32_t index, char val)
        {
            UARTCharPut(m_baseArray[index], val);
        }
    
        char UARTCtrl::charGet(uint32_t index)
        {
            return UARTCharGet( m_baseArray[index] );
        }
    
        void UARTCtrl::uprintf( const char * pcString, ...)
        {
            //index is set when setUartIO is called
            va_list vaArgP;
            va_start( vaArgP, pcString );
    
            UARTvprintf( pcString, vaArgP);
            va_end(vaArgP);
        }
    
        int UARTCtrl::UARTgets(char *pcBuf, uint32_t ui32Len)
        {
            //index is set when setUartIO is called
            return UARTgets( pcBuf, ui32Len );
        }
    
        void UARTCtrl::endConfig()
        {
            //Seems to work when I have this in. Not sure why. The RXFE changes to high
            //in loop back when I try to read a char and goes into infinite loop. When this
            //is here it does not.
            uprintf("");
        }
    
    }
    

  • John Chaparro said:
    void UARTCtrl::endConfig() { //Seems to work when I have this in. Not sure why. The RXFE changes to high //in loop back when I try to read a char and goes into infinite loop. When this //is here it does not. uprintf(""); }

    It would seem you need to add SyCtlDelay() in your loop back R/W or RXFE flag is being over run. The uartprintf() adds some delay into the loop back and push/pop stack R/W adds instruction clock cycles same a delay.

    I saw the same oddness and reported to forum empty flag seems dependent on baud frequency and acts inconsistent in my opinion, perhaps from edge jitter. So UART reads 16 bytes without issue and must wait for time out or empty flag to drive an interrupt prior to application reading next byte RXFE pending. I simply added a test of the flag into the loop but you might get by if only single char R/W mode by adding delay into the loop back if it manual keyboard driven.