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.

TM4C1294NCPDT: enet_s2e Data Is Bursty, What Determines UART & Telnet Buffer Send or Flush Times

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

Our product is using the TM4C1294NCPDT and software based on the enet_s2e reference example.
I have found that the data coming into our UART and then out the telnet port is bursty which has confused the desk top application connecting to our product by telnet.  Our desk top poles several times a second with a protocol command  ">04<CR>"  That is a greater than sign, a zero a four and a carriage return which I will abbreviate as ">04".  This is a request to our product for measurement information. Our product is to return a string.

The developer of the desk top application discovered that the response to the ">04" was what he called buffered up. Some times no response but after a subsequent ">04" was sent the instrument sent multiple responses.

I believe I have found the root cause in the enet_s2e reference design which displays such buffering and bursting of data through the telnet to UART connection.

With the reference enet_s2e project I wired PC6 to PN4 and PC7 to PN5 to connect the UARTs. Then I used RealTerminal to send repeatedly a text file containing only ">04" into one telnet port.  RealTerm allows me to set inter-character delays and delays at end of line and delays before the tile to be sent is sent. 

I captured and time stamped the data out the other telnet port with a Processing program I wrote which time stamps to milliseconds (since program started) . I see the ">04" command is passed through the two telnet pipes in bursts. In the screen shot I will provide there is a burst where the delay was 217 milliseconds and  three ">04" commands were sent. See time stamp 2019 3 14 17 12 187874.

I would like to reduce or eliminate this burstyness.

I have begun to examine the enet_s2e code and see what I think as a 40 mS HOST_TMR_INTERVAL managing the telnet UART buffers and so I would have thought that the burstyness would be on the order of 40 mS not 200 mS.

Any improved insight would be appreciated.

I would like to understand the code enough to possibly flush the buffer when a <CR> or <LF> occures for example but am not sure that might violate the design in ways I can not anticipate.

I will add screen shots separate to this first post.

  • Here is a screen shot of RealTerm and my Processing Sketch with time stamped data.

  • I wrote, "RealTerm allows me to set inter-character delays and delays at end of line and delays before the tile to be sent is sent. "

    Should have been: "RealTerm allows me to set inter-character delays and delays at end of line and delays before the file to be sent is sent. "
  • Oops my bad. I though I was using the enet_s2e unmodified but I see I have used the code where we have changed the UARTs to reflect our printed circuit assembly. We are using UART 3 and UART5 but the original example code is using UART3 and UART4.
  • Hi Forrest,
    I don't know for sure what the root cause is. However, I feel that it may have something to do with the FIFO in the UART. The FIFO in the UART will buffer data until the programmed threshold level before it interrupts the CPU. Can you try with the UARTFIFODisable to disable the FIFO or set the UARTFIFOLevelSet to 1 so that it does not utilized the FIFO. See if this makes a difference. If not working, we need to explore other possibilities.
  • Hi Forrest,
    I have not heard back from you. I assume you are able to resolve the issue. Hopefully, the UART FIFO I brought up may have something to do with your observation. I will close the thread for now. If you have new questions you can open a new thread or reply back to this with some comments if the issue persists.
  • Hello Charles,

    Thank you for the suggestion to look at the UART buffer.  I have not had a chance to look at the UART FIFO and understand how I might change it.

    I have been out of office for several days due to ilness (Flu) and am just now back.   I have a back log of items to clear before I can get back into examining the code at this point so It may be a few more days.

    Thanks for the insight.

    Forrest Lee Erickson

  • I cleared my To Do back log and got back to this today.

    I found again on page 571 of  the TivaWare™ Peripheral Driver Library document number: SW-TM4C-DRL-UG-2.1.4.178

    The very brief description of  UARTFIFODisable

    After looking through the enet_s2e code I decided to try to put a call to this function in the file serial. at the function :

    //*****************************************************************************
    //
    //! Configures the serial port to a default setup.
    //!
    //! \param ui32Port is the UART port number to be accessed.
    //!
    //! This function resets the serial port to a default configuration.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SerialSetDefault(uint32_t ui32Port)
    {
        //
        // Check the arguments.
        //
        ASSERT(ui32Port < MAX_S2E_PORTS);
    
        //
        // Configure the serial port with default parameters.
        //
        _SerialSetConfig(ui32Port, &g_psDefaultParameters->sPort[ui32Port]);
    
        UARTFIFODisable(ui32Port);  ///FLE 20190327
    }
    

    The project compiled but when I ran on the Launchpad the the TI provided finder program could not find the device on the LAN and the web server was not serving.
    I pressed the pause button on the debugger and the program was trapped in ISR fault trap.

    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a fault
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    FaultISR(void)
    {
        //
        // Enter an infinite loop.
        //
        while(1)
        {
        }
    }
    



    So something about placing the TivaWare call there renders an ISR a fault.


    Nothing in the PDF tells me if there is a sequence of calls that this is to be part of or not.

    Any idea how to use this "UARTFIFODisable" function?


  • More information. I put a break point on the UARTFIFODisable call.
    The code stopped there as expected. Then i single stepped and with in two clicks I was in the FaultISR trap.
  • I removed my first guess.
    I noticed I was to give the function an argument for the UART base address.
    I moved the function call to the function below. 
    Same result. It builds but when I run it the program gets traped in the FaultISR.
    
    
    //*****************************************************************************
    //
    //! Initializes the serial port driver.
    //!
    //! This function initializes and configures the serial port driver.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SerialInit(void)
    {
        //
        // Initialize the ring buffers used by the UART Drivers.
        //
        RingBufInit(&g_sRxBuf[0], g_pui8RX0Buffer, sizeof(g_pui8RX0Buffer));
        RingBufInit(&g_sTxBuf[0], g_pui8TX0Buffer, sizeof(g_pui8TX0Buffer));
        RingBufInit(&g_sRxBuf[1], g_pui8RX1Buffer, sizeof(g_pui8RX1Buffer));
        RingBufInit(&g_sTxBuf[1], g_pui8TX1Buffer, sizeof(g_pui8TX1Buffer));
    
        //
        // Enable and Configure Serial Port 0.
        //
        SysCtlPeripheralEnable(S2E_PORT0_RX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_TX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_RTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_CTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_UART_PERIPH);
        GPIOPinConfigure(S2E_PORT0_RX_CONFIG);
        GPIOPinConfigure(S2E_PORT0_TX_CONFIG);
        GPIOPinConfigure(S2E_PORT0_RTS_CONFIG);
        GPIOPinConfigure(S2E_PORT0_CTS_CONFIG);
        GPIOPinTypeUART(S2E_PORT0_RX_PORT, S2E_PORT0_RX_PIN);
        GPIOPinTypeUART(S2E_PORT0_TX_PORT, S2E_PORT0_TX_PIN);
        GPIOPinTypeUART(S2E_PORT0_RTS_PORT, S2E_PORT0_RTS_PIN);
        GPIOPinTypeUART(S2E_PORT0_CTS_PORT, S2E_PORT0_CTS_PIN);
    
        //
        // Configure the Port 1 pins appropriately.
        //
        SysCtlPeripheralEnable(S2E_PORT1_RX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_TX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_RTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_CTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_UART_PERIPH);
        GPIOPinConfigure(S2E_PORT1_RX_CONFIG);
        GPIOPinConfigure(S2E_PORT1_TX_CONFIG);
        GPIOPinConfigure(S2E_PORT1_RTS_CONFIG);
        GPIOPinConfigure(S2E_PORT1_CTS_CONFIG);
        GPIOPinTypeUART(S2E_PORT1_RX_PORT, S2E_PORT1_RX_PIN);
        GPIOPinTypeUART(S2E_PORT1_TX_PORT, S2E_PORT1_TX_PIN);
        GPIOPinTypeUART(S2E_PORT1_RTS_PORT, S2E_PORT1_RTS_PIN);
        GPIOPinTypeUART(S2E_PORT1_CTS_PORT, S2E_PORT1_CTS_PIN);
    
        //
        // Configure Port 0.
        //
        UARTFIFODisable(S2E_PORT0_UART_PORT);  ///FLE 20190327
        SerialSetDefault(0);
    
        //
        // Configure Port 1.
        //
        UARTFIFODisable(S2E_PORT1_UART_PORT);  ///FLE 20190327
        SerialSetDefault(1);
    }
    

  • Hi Forrest,
    In the original example the S2E_PORT0_UART_PORT is defined as UART4_BASE and S2E_PORT1_UART_PORT is defined as UART3_BASE. Do you have the corresponding UART enabled using SysCtlPeripheralEnable() first?
  • Hello Charles,

    Thanks for getting back to me.

    Regarding enabling SysCtlPeripheralEnable() first

    I think yes. Here is the code where you can see the SysCtlPeripheralEnable() are called for port 0 and port 1.  My change was after the enable.

    //*****************************************************************************
    //
    //! Initializes the serial port driver.
    //!
    //! This function initializes and configures the serial port driver.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SerialInit(void)
    {
        //
        // Initialize the ring buffers used by the UART Drivers.
        //
        RingBufInit(&g_sRxBuf[0], g_pui8RX0Buffer, sizeof(g_pui8RX0Buffer));
        RingBufInit(&g_sTxBuf[0], g_pui8TX0Buffer, sizeof(g_pui8TX0Buffer));
        RingBufInit(&g_sRxBuf[1], g_pui8RX1Buffer, sizeof(g_pui8RX1Buffer));
        RingBufInit(&g_sTxBuf[1], g_pui8TX1Buffer, sizeof(g_pui8TX1Buffer));
    
        //
        // Enable and Configure Serial Port 0.
        //
        SysCtlPeripheralEnable(S2E_PORT0_RX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_TX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_RTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_CTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT0_UART_PERIPH);
        GPIOPinConfigure(S2E_PORT0_RX_CONFIG);
        GPIOPinConfigure(S2E_PORT0_TX_CONFIG);
        GPIOPinConfigure(S2E_PORT0_RTS_CONFIG);
        GPIOPinConfigure(S2E_PORT0_CTS_CONFIG);
        GPIOPinTypeUART(S2E_PORT0_RX_PORT, S2E_PORT0_RX_PIN);
        GPIOPinTypeUART(S2E_PORT0_TX_PORT, S2E_PORT0_TX_PIN);
        GPIOPinTypeUART(S2E_PORT0_RTS_PORT, S2E_PORT0_RTS_PIN);
        GPIOPinTypeUART(S2E_PORT0_CTS_PORT, S2E_PORT0_CTS_PIN);
    
        //
        // Configure the Port 1 pins appropriately.
        //
        SysCtlPeripheralEnable(S2E_PORT1_RX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_TX_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_RTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_CTS_PERIPH);
        SysCtlPeripheralEnable(S2E_PORT1_UART_PERIPH);
        GPIOPinConfigure(S2E_PORT1_RX_CONFIG);
        GPIOPinConfigure(S2E_PORT1_TX_CONFIG);
        GPIOPinConfigure(S2E_PORT1_RTS_CONFIG);
        GPIOPinConfigure(S2E_PORT1_CTS_CONFIG);
        GPIOPinTypeUART(S2E_PORT1_RX_PORT, S2E_PORT1_RX_PIN);
        GPIOPinTypeUART(S2E_PORT1_TX_PORT, S2E_PORT1_TX_PIN);
        GPIOPinTypeUART(S2E_PORT1_RTS_PORT, S2E_PORT1_RTS_PIN);
        GPIOPinTypeUART(S2E_PORT1_CTS_PORT, S2E_PORT1_CTS_PIN);
    
        //
        // Configure Port 0.
        //
        UARTFIFODisable(S2E_PORT0_UART_PORT);  ///FLE 20190327
        SerialSetDefault(0);
    
        //
        // Configure Port 1.
        //
        UARTFIFODisable(S2E_PORT1_UART_PORT);  ///FLE 20190327
        SerialSetDefault(1);
    }

  • Hi Forrest,
    I still think that somehow the peripheral is not enabled. I tried the UARTFIFODisable() in one of the TivaWare example and I don't see an issue.

    Can you try below right before you call SerialSetDefault(0) as an experiment? I assume the S2E_PORT0_UART_PORT is defined as UART4_BASE. When you single step the UARTFIFODisable() will you get an exception again?

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART4))
    {
    }
    UARTFIFODisable(UART4_BASE);
    SerialSetDefault(0);

    If you still have an exception can you take a look at the below app note that illustrates how to find the cause of the faults.
    www.ti.com/.../spma043.pdf
  • Hello Charles,

    Regarding, "I still think that somehow the peripheral is not enabled. I tried the UARTFIFODisable() in one of the TivaWare example and I don't see an issue."  

    Which example and which file and where did you make your experiment?  I would like to become compitent with the TiviWare API to do this.

    FYI, I continued reading the code in serial.c and found a place where the comments indicated the FIFO was set up. See below.

    I commented out the line and tested and did not find the burstyness I had found before. So I think I found a fix.

    I wanted to experiment with setting the FIFO size to 1/8 but since I cannot figure out the syntax and where to DisableFIFO I can not guess where to modify the code to change the FIFO size.

    Any  pointers would be appreciated.

    Thank you,
    Forrest Erickson

  • HI Forrest,

      Glad that it is the UART FIFO that I was suspecting. 

     It is the uart_echo example I modified. The example can be found in <TivaWare_Installation>/examples/boards/EK-TM4C1294XL/uart_echo. Look for the UARTFIFODisable I inserted below. I ran the example I don't have any fault. 

    //*****************************************************************************
    //
    // uart_echo.c - Example for reading data from and writing data to the UART in
    //               an interrupt driven fashion.
    //
    // Copyright (c) 2013-2017 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.
    // 
    // This is part of revision 2.1.4.178 of the EK-TM4C1294XL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.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/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.
    //
    //*****************************************************************************
    
    //****************************************************************************
    //
    // System clock rate in Hz.
    //
    //****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = ROM_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        ROM_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(ROM_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            ROM_UARTCharPutNonBlocking(UART0_BASE,
                                       ROM_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(g_ui32SysClock / (1000 * 3));
    
            //
            // Turn off the LED
            //
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 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_UARTCharPut(UART0_BASE, *pui8Buffer++);
        }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    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 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);
    
        //
        // Enable the peripherals used by this example.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    
        //
        // Enable processor interrupts.
        //
        ROM_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinConfigure(GPIO_PB4_U0CTS);
        GPIOPinConfigure(GPIO_PB5_U0RTS);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        ROM_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
        UARTFlowControlSet(UART0_BASE, UART_FLOWCONTROL_TX|UART_FLOWCONTROL_RX);
    
        // Disable FIFO
        UARTFIFODisable(UART0_BASE);
    
        //
        // Enable the UART interrupt.
        //
        ROM_IntEnable(INT_UART0);
        ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    
        //
        // Prompt for text to be entered.
        //
        UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
    
        //
        // Loop forever echoing data through the UART.
        //
        while(1)
        {
        }
    }
    

    To change the FIFO level, see below API.

  • Charles,
    Thanks for getting back with ideas.

    Regarding, "...SysCtlPeripheralEnable..."
    The UARTs are still being enabled with this function using the original code.

    Screen shot below.

  • Hi Forrest,
    1. Did you have a chance to run the example I pasted with the UARTFIFODisable()?
    2. You didn't answer me if the below code works for you?

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART4))
    {
    }
    UARTFIFODisable(UART4_BASE);
    SerialSetDefault(0);

    3. You said you get a fault when you called UARTFIFODisable and I understand prior to the call you had enabled the peripheral. If you go to the Register Browser in CCS, do you see all the values of the UART4 registers prior to calling the UARTFIFODisable? If the UART4 was not enabled or somehow disabled for whatever reason prior to calling it the UARTFIFODisable() then the CCS will show message in red that it can't access the UART.

    4. What if you replace the UARTFIFODisable with a direct write using HWREG to disable the FIFO. See below API content.

    void
    UARTFIFODisable(uint32_t ui32Base)
    {
    //
    // Check the arguments.
    //
    ASSERT(_UARTBaseValid(ui32Base));

    //
    // Disable the FIFO.
    //
    HWREG(ui32Base + UART_O_LCRH) &= ~(UART_LCRH_FEN);
    }
  • Hi Forrest,
    I didn't hear from you. I hope your issue is somehow resolved and you were able to try the several suggestions in my last reply. I will close the thread for now. If you have new question please open a new thread. If you have some comments about the current issue you can reply to this thread again.
  • Hello Charles,

    Regarding:

    1. Did you have a chance to run the example I pasted with the UARTFIFODisable()?

    I ran the code in the example project you indicated and it compiled. However in the example project I was not able to duplicate the bursty nature before modification so I am left wondering if I know the root cause.

    Bottom line I am still going to do some more experiments.

    I was thinking of changing the FIFO size and seeing if I could maximize / minimize the bursty ness.

  • Hi Forrest,
    I think the reason is that out of reset, the FIFO is disabled and this is the reason that you don't see the bursty behavior. What I was demonstrating in the code I pasted was to show that by calling UARTFIFODisable() I didn't get any fault.
    Yes, please also try to set the FIFO level to smaller threshold. I should reduce the bursty behavior.