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.

TM4C123GH6PM: UART2 PROBLEM

Part Number: TM4C123GH6PM


Hi everybody, I have designed a custom board and done with all solderings and etc. I have made uart connections by using uart2(PD6,PD7), and used uart0 and uart1 pins for other purposes. While designing the circuit, I complately forgot about PD7 is locked and needs to be unlocked. Uart0 example code is working fine, but when I try to convert it to uart2 and make the required changes in startup.c file, code doesn't work. I searched forum and saw people are having the same problem and there is no a working code exapmle shared. I tried to unlock the PD7, still doesn't work. Do you have a working uart2 code? Or can u help me to make mine work. 

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "inc/hw_gpio.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"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the USB debug virtual serial port on the evaluation board)
//! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
//! the UART are transmitted back to the UART.
//
//*****************************************************************************



//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

void UARTIntHandler(void);


void uart2_init(){
	//initializes UART2 
	//sets up transmit and receive interrupts
	//0. Init Clock to UART2 and Port D
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	//Give it time for clocks to start
	SysCtlDelay(10);
	//Disable UART before programming
	UARTDisable(UART2_BASE);
	//1.  set baud rate, txe/rxe, stp2 (clear then and fen), and wlen (8 bit_)
	UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(), 9600, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
	UARTFIFODisable(UART2_BASE); //DISABLE FIFO. This should make my interrupt every time I get a byte.
	//1.5. Set up AFSEL To D6, D7 and UNLOCK D7
	HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
	HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7;
	GPIOPinConfigure(GPIO_PD6_U2RX);
	GPIOPinConfigure(GPIO_PD7_U2TX);
	//Set D6 as Input (RX) and D7 as Output (TX)
	GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_7);
	GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_6);
	//A little redundancy shouldn't hurt.
	GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);
	//Enable Global NVIC Interrupt
	IntEnable(INT_UART2);
	//Enable Local Interrupts
	UARTIntEnable(UART2_BASE, (UART_INT_TX | UART_INT_RX)); //enable Tx and Rx int
	UARTTxIntModeSet(UART2_BASE, UART_TXINT_MODE_EOT); //set Tx mode to EOT
	UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //set Rx to trigger with two bytes
	//Disable for now so I don't get stuck in the TX isr.
	UARTIntDisable(UART2_BASE, UART_INT_TX);
	//Link a function to the UART Interrupt
	UARTIntRegister(UART2_BASE, UARTIntHandler);
	//Enable UART2
	UARTEnable(UART2_BASE);
        
}


void GPIOPinUnlockGPIO(uint32_t ui32Port, uint8_t ui8Pins) {
    HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY;      // Unlock the port
    HWREG(ui32Port + GPIO_O_CR) |= ui8Pins;             // Unlock the Pin
    HWREG(ui32Port + GPIO_O_LOCK) = 0;                  // Lock the port
}

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = ROM_UARTIntStatus(UART2_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    ROM_UARTIntClear(UART2_BASE, ui32Status);

    //
    // Loop while there are characters in the receive FIFO.
    //
    while(ROM_UARTCharsAvail(UART2_BASE))
    {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART2_BASE,
                                   ROM_UARTCharGetNonBlocking(UART2_BASE));

        //
        // Blink the LED to show a character transfer is occuring.
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay(SysCtlClockGet() / (1000 * 3));

        //
        // Turn off the LED
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

    }
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
{
    //
    // Loop while there are more characters to send.
    //
    while(ui32Count--)
    {
        //
        // Write the next character to the UART.
        //
        ROM_UARTCharPutNonBlocking(UART2_BASE, *pui8Buffer++);
    }
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPUEnable();
    ROM_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    //
    // Enable the peripherals used by this example.
    //
//    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
//    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
//
//    //
//    // Enable processor interrupts.
//    //
//    ROM_IntMasterEnable();
//    
////    GPIOPinUnlockGPIO(GPIO_PORTD_BASE, GPIO_PIN_7);     // Unlock the PD7 GPIO
//
////    GPIOPinConfigure(GPIO_PD7_NMI);
//    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0x4C4F434B;
//    HWREG(GPIO_PORTD_BASE + GPIO_O_CR) = 0xFF;
//    HWREG(GPIO_PORTD_BASE + GPIO_O_CR) = 0x0000007F;
//    
//    GPIOPinConfigure(GPIO_PD6_U2RX);
//    GPIOPinConfigure(GPIO_PD7_U2TX);
//    
//    HWREG(GPIO_PORTD_BASE + GPIO_O_AFSEL) |= 0x00000080;
//    
//    HWREG(GPIO_PORTD_BASE + GPIO_O_DEN) |= 0x00000080;
//
////
//// Relock the commit register
////
//    HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0;
//
//
//
//
//    //
//    // Set GPIO A0 and A1 as UART pins.
//    //
//
//    ROM_GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);
//
//    //
//    // Configure the UART for 115,200, 8-N-1 operation.
//    //
//    ROM_UARTConfigSetExpClk(UART2_BASE, ROM_SysCtlClockGet(), 9600,
//                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
//                             UART_CONFIG_PAR_NONE));
//
//    //
//    // Enable the UART interrupt.
//    //
//    ROM_IntEnable(INT_UART2);
//    ROM_UARTIntEnable(UART2_BASE, UART_INT_RX | UART_INT_RT);
//
//    //
//    // Prompt for text to be entered.

    uart2_init();
//    //
    UARTSend((uint8_t *)"\033[2JEnter text: ", 16);

    //
    // Loop forever echoing data through the UART.
    //
    while(1)
    {
          UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
          SysCtlDelay(1000);
          
    }
}

  • Feel your pain - yet your writing does not enable "best quality" of response.      Suggestions listed below attempt to "aid others" in your assistance - & guide your further writings.

    Furkan ERMAN said:
    I tried to unlock the PD7, still doesn't work.

    "Doesn't work" (that term - not your invention) provides "little" diagnostic value!      Far more useful would be your description of specific details - which better clarify your issue.   (i.e. No signal output appears - Baud rate not to spec, illegal data format etc.)

    In addition - we are not explicitly told "How you connect to UART_2."     UART_2's output & input signal levels are CMOS - must connect to a device sharing that spec.   (NOT RS232!)

    A scope provides the ideal means to monitor UART_2.     Absent that - with greatly slowed baud rate - an Led may be pressed to serve.

    It is noted that your code w/in (main) effectively "comments away" key references to UART_2 (wasting your reviewer's time) and only steers correctly during the final (few) lines.     That's not helpful nor considerate.

    Lastly - you've chosen to involve many aspects of this UART.     That is NOT "KISS" appropriate - instead the simplest - most direct set-up & config - of the minimal required to gain UART_2's operation - is preferred.   (i.e. less to "go wrong" - hold you hostage.)

    As regards "success of unlock" - that may be most easily judged by configuring PD7 to GPIO Output - then toggling - while noting results.    Should the unlock have failed - "ALL of your UART efforts are doomed" - so this quick check may prove worthwhile...

  • Thanks for your answer. I have read your some answers in different posts, and struggled to understand. You have unusual writing style, and my english is not that good to understand well. I think you want me to wait by writing Plz Standby
  • Yes - that (was) true - net was in/out as I am "in the air." Post has now been completed - and provides items for your consideration.
    Good luck.

    When "struggling" (which is impossible for me to know) you may always write - and request clarification.   I author many tech contracts (have several small businesses) - which demand detail & precision.     It proves time-consuming & stressful to "shift-gears" when writing for those "new to English" here.     Your "PM" always gets response - and that falls to you...   (i.e. "Ask" - and clarification will follow...)

  •  thank you to let me solve problem by myself. Important note for people who use tx,rx icdi pins on Tiva Launchpad: Connect Tx -> Tx and Rx -> Rx. Working code is below. Don't forget to make required changes in startup.c file. 

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "inc/hw_gpio.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"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>UART Echo (uart_echo)</h1>
    //!
    //! This example application utilizes the UART to echo text.  The first UART
    //! (connected to the USB debug virtual serial port on the evaluation board)
    //! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
    //! the UART are transmitted back to the UART.
    //
    //*****************************************************************************
    
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    void GPIOPinUnlockGPIO(uint32_t ui32Port, uint8_t ui8Pins) {
        HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY;      // Unlock the port
        HWREG(ui32Port + GPIO_O_CR) |= ui8Pins;             // Unlock the Pin
        HWREG(ui32Port + GPIO_O_LOCK) = 0;                  // Lock the port
    }
    
    
    //*****************************************************************************
    //
    // Send a string to the UART.
    //
    //*****************************************************************************
    void
    UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ui32Count--)
        {
            //
            // Write the next character to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART2_BASE, *pui8Buffer++);
        }
    }
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
        //
        // Get the interrrupt status.
        //
        ui32Status = ROM_UARTIntStatus(UART2_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        ROM_UARTIntClear(UART2_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(ROM_UARTCharsAvail(UART2_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART2_BASE,ROM_UARTCharGetNonBlocking(UART2_BASE));
    
            SysCtlDelay(SysCtlClockGet() / (1000 * 3));
        }
    }
    
    void uart2_init(){
    	//initializes UART2 
    	//sets up transmit and receive interrupts
    
    	//0. Init Clock to UART2 and Port D
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
            
    	//Give it time for clocks to start
    	SysCtlDelay(10);
            
    	//Set up AFSEL To D6, D7 and UNLOCK D7
            GPIOPinUnlockGPIO(GPIO_PORTD_BASE, GPIO_PIN_7);
    	GPIOPinConfigure(GPIO_PD6_U2RX);
    	GPIOPinConfigure(GPIO_PD7_U2TX);
    	GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);
            
            //set baud rate, txe/rxe, stp2 (clear then and fen), and wlen (8 bit_)
    	UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(), 9600, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    
    //        UARTFIFOEnable(UART2_BASE);
    //        UARTTxIntModeSet(UART0_BASE, UART_TXINT_MODE_FIFO);
    
    //        UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //set Rx to trigger with two bytes
    
    	//Enable Global NVIC Interrupt
    	IntEnable(INT_UART2);
    	//Enable Local Interrupts
    //	UARTIntEnable(UART2_BASE, (UART_INT_TX | UART_INT_RX)); //enable Tx and Rx int
            UARTIntEnable(UART2_BASE, UART_INT_RX); //enable Rx int
            UARTIntDisable(UART2_BASE, UART_INT_TX); //enable Rx int
    	//Enable UART2
     	UARTEnable(UART2_BASE);
            UARTFIFODisable(UART2_BASE);
    }
    
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPUEnable();
        ROM_FPULazyStackingEnable();
    
        //
        // Set the clocking to run directly from the crystal.
        //
        SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    
        uart2_init();
    
    
        //
        // Loop forever echoing data through the UART.
        //
    
    
         
         ROM_IntMasterEnable();
         
    
         
         UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
         
         
         
        while(1)
        {
        }
    }

  • Furkan ERMAN said:
    Important note for people who use tx,rx icdi pins on Tiva Launchpad: Connect Tx -> Tx and Rx -> Rx.

    That (almost) seems "counter-intuitive" is it not far more "normal" to connect MU's TX to (remote's) RX and MCU's RX to (remote's) TX?

    However - even easier - before ALTERING the board's ICDI connections - carefully NOTE THEM - so that "switching to a different UART" becomes far simpler!

    Your initial post noted, "I have made uart connections by using uart2(PD6,PD7), and used uart0 and uart1 pins for other purposes."

    Yours was a custom board - which is unlikely to include the ICDI MCU - this is why I asked, "How have you connected UART_2?"      That was a key diagnostic - was it not?    (yet no Verify was awarded...)    There was absolutely NO MENTION of PD6/PD7 being connected to the ICDI MCU - which was likely upon a SECOND BOARD!     (strange/unusual that!)

    All other "tips" do hold - for those w/similar "UART issues"...