This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129XNCZAD: UART reports break and framing errors after calling UARTConfigSetExpClk()

Part Number: TM4C129XNCZAD

I saw a few other posts on this forum mentioning similar issues, but could not find a definitive answer anywhere.

My init code for the UART is as follows:

// Note: It does not matter which UART I use. I tried 0 thru 7, and they all do the same thing.
#define PC_UART_SYSCTL              SYSCTL_PERIPH_UART3
#define PC_UART_BASE                UART3_BASE

    SysCtlPeripheralEnable(PC_UART_SYSCTL);
    while (!SysCtlPeripheralReady(PC_UART_SYSCTL))
    {
    }

    UARTDisable(PC_UART_BASE);
    UARTConfigSetExpClk(PC_UART_BASE, getSystemClockFreqHz(), PC_UART_BAUD_RATE, 
                        (     UART_CONFIG_WLEN_8 
                            | UART_CONFIG_STOP_ONE 
                            | UART_CONFIG_PAR_NONE));

This seems to match the code in the Programming Example section of the TivaWare manual.

Later on, I do a loopback test on the UART:

        bool passed = true;

        // must disable before changing settings
        UARTDisable(PC_UART_BASE);

	// put UART into loopback mode
	PlaceUARTLoopback(PC_UART_BASE, 1);

        // clear any pending rx errors
        UARTIntClear(PC_UART_BASE, 0xffffffffu);
        UARTRxErrorClear(PC_UART_BASE);

        UARTEnable(PC_UART_BASE);
	UARTCharPut (PC_UART_BASE, 0x5a);
	value = UARTCharGet(PC_UART_BASE);
        passed = (value == 0x5a);

	if (passed)
	{
	         *puStatus &= ~POST_UART_LOOPBACK;
	}
	else
        {
            *puStatus |= POST_UART_LOOPBACK;
        }

        UARTDisable(PC_UART_BASE);
	PlaceUARTLoopback(PC_UART_BASE, 0);

The loopback test usually fails (although it will intermittently pass).

If I single step through the init code using the CCS debugger, I see that after calling UARTConfigSetExpClk(),the UART's RX error status register shows both a break and a framing error, and the data register contents are 0x0500. If I continue stepping, after a few instructions the errors get cleared and the DR goes to 0x0000.

However, if I just run to the loopback test without stepping, the errors are still set and the DR still contains 0x0500. Even after calling UARTRxErrorClear() in the loopback test code, the error bits remain set, causing the test to fail.

I also discovered that if I add a 100 ms delay before calling the loopback test, then things work fine.

It appears that there is some sort of time lag before the contents of the UART control registers arrive at the proper state. Is there something I am neglecting to do in setting up the UART?

Regards,

Dave

  • The UARTDisable() function allows the character being transmitted to complete. You may need to loop on calls to UARTBusy() to make sure the UART finished transmitting the last character before calling PlaceUARTLoopback().
  • Hi, Bob,

    I am not transmitting/receiving any characters before running the loopback test. Nevertheless, following your suggestion I changed the start of my test code to:

    UARTDisable(PC_UART_BASE);
    while (UARTBusy(PC_UART_BASE))
    {
    }

    // put UART into loopback mode
    PlaceUARTLoopback(PC_UART_BASE, 1);

    However, I still see the break and framing errors. And I don't understand why explicitly clearing the rx errors before sending the character does not actually clear the values in the RSR.

    Also, if I set a breakpoint just before doing the read, it works.

    Regards,

    Dave
  • I played around with adding delays just before enabling the UART and putting the character, and I found that a 1 ms delay is sufficient to get the loopback test to pass. No idea why that would be necessary, though.

    Regards,

    Dave
  • I had no issues when I modified the "Hello" example for an EK-TM4C129XL booster pack to do a loopback test. The UARTEnable and UARTDisable were not required, but did not cause a problem when added. What does your PlaceUARTLoopback() function do?

    int
    main(void)
    {
    	unsigned char value;
    	unsigned int divider;
    	//
        // Run from the PLL at 120 MHz.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                    SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                    SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Configure the device pins.
        //
        PinoutSet(false, false);
    
        //
        // Enable the GPIO pins for the LED D1 (PN1).
        //
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
    
        //
        // Initialize the UART.
        //
        ConfigureUART();
    
        //
        // Hello!
        //
        UARTprintf("Hello, world!\n");
    
        // Make sure UART is finished
        while(UARTBusy(UART0_BASE))
        {
        }
        UARTDisable(UART0_BASE);
        UARTLoopbackEnable(UART0_BASE);
        UARTEnable(UART0_BASE);
        UARTCharPut(UART0_BASE, 0x5A);
        value = UARTCharGet(UART0_BASE);
        if (0x5A == value)
        {
        	divider = 64u; // Fast blink
        }
        else
        {
        	divider = 16u; // Slow blink
        }
        //
        // We are finished.  Hang around flashing D1.
        //
        while(1)
        {
            //
            // Turn on D1.
            //
            LEDWrite(CLP_D1, 1);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock / divider);
    
            //
            // Turn off D1.
            //
            LEDWrite(CLP_D1, 0);
    
            //
            // Delay for a bit.
            //
            SysCtlDelay(g_ui32SysClock / divider);
        }
    }
    

  • Hi, Bob,

    The PlaceUARTLoopback() code is:

    void PlaceUARTLoopback(unsigned long ulBase, unsigned long loopback)
    {
    //
    // Check the arguments.
    //
    ASSERT(UARTBaseValid(ulBase));


    //
    // Enable or disable looback for the uart
    //

    if (loopback) {
    HWREG(ulBase + UART_O_CTL) |= UART_CTL_LBE;
    }
    else {
    HWREG(ulBase + UART_O_CTL) &= (~UART_CTL_LBE);
    }
    }

    I think the original engineer got this from the TivaWare UARTLoopbackEnable() code, but since he needed to be able to disable the loopback (which, curiously, the TivaWare library does not seem to make provision for) he created a new function that did both.

    Regards,

    Dave
  • I revisited this issue after having ignored it for several weeks. I was able to get the test to pass by adding a peripheral reset before performing the loopback test. Thanks to cb1 for recommending this (in a different thread where I was having problems with the SSI peripheral).

    // do a full reset of the UART peripheral to guarantee a clean state
    SysCtlPeripheralReset(PC_UART_SYSCTL);
    while (!SysCtlPeripheralReady( PC_UART_SYSCTL ))
    {
    }

    Regards,

    Dave