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: Issues with UART to SSH Data Formatting and Partial Transmissions

Part Number: EK-TM4C1294XL

Context:
I am currently working on a project involving data transmission from UART to SSH using a TM4C1294 microcontroller. The development environment is Code Composer Studio.

Problem Statement:
I'm experiencing issues with the formatting and completeness of data transmitted between UART and SSH. For example when trying to send this data;

Serial 0 is up, line protocol is up
   Hardware is MCI Serial
     Internet address is 150.136.190.203, subnet mask is 255.255.255.0
     MTU 1500 bytes, BW 1544 Kbit, DLY 20000 usec, rely 255/255, load 1/255
     Encapsulation HDLC, loopback not set, keepalive set (10 sec)
     Last input 0:00:07, output 0:00:00, output hang never
     Output queue 0/40, 0 drops; input queue 0/75, 0 drops

     Five minute input rate 0 bits/sec, 0 packets/sec
     Five minute output rate 0 bits/sec, 0 packets/sec
           16263 packets input, 1347238 bytes, 0 no buffer
           Received 13983 broadcasts, 0 runts, 0 giants
           2 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 2 abort
1 carrier transitions 

     22146 packets output, 2383680 bytes, 0 underruns
     0 output errors, 0 collisions, 2 interface resets, 0 restarts
      

  1. UART to SSH: Data sent from UART to SSH gets truncated and only partial messages are received. For example, I try to send a detailed status message, but only the first part is received before it cuts off.
  2. Serial 0 is up,
    
  3. SSH to UART: Data sent from SSH to UART does not preserve the intended layout. It should display as multi-line formatted text, but instead, it's coming through as one continuous line without any breaks.
  4. Serial 0 is up, line protocol is up   Hardware is MCI Serial     Internet address is 150.136.190.203, subnet mask is 255.255.255.0     MTU 1500 bytes, BW 1544 Kbit, DLY 20000 usec, rely 255/255, load 1/255     Encapsulation HDLC, loopback not set, keepalive set (10 sec)     Last input 0:00:07, output 0:00:00, output hang never     Output queue 0/40, 0 drops; input queue 0/75, 0 drops     Five minute input rate 0 bits/sec, 0 packets/sec     Five minute output rate 0 bits/sec, 0 packets/sec           16263 packets input, 1347238 bytes, 0 no buffer           Received 13983 broadcasts, 0 runts, 0 giants           2 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 2 abort1 carrier transitions      22146 packets output, 2383680 bytes, 0 underruns     0 output errors, 0 collisions, 2 interface resets, 0 restarts

What I've Tried:

  • I've increased the UART buffer size to 1024 bytes to accommodate larger chunks.
  • Checked and ensured that no overflow or buffer overrun errors are reported by the microcontroller.
  • Experimented with different baud rates and settings to rule out communication speed and configuration issues.

Relevant Code Snippets:

UART Initialization and Read Function:

uint32_t UARTRead(uint32_t ui32Base, uint8_t *buffer, uint32_t length) {
    uint32_t i;
    for (i = 0; i < length; ++i) {
        if (!UARTCharsAvail(ui32Base))
            break;
        buffer[i] = UARTCharGet(ui32Base);
    }
    return i;
}

void UARTWrite(uint32_t ui32Base, const uint8_t *buffer, uint32_t length) {
    for (uint32_t i = 0; i < length; ++i) {
        UARTCharPut(ui32Base, buffer[i]);
    }
}

Session Handling in ShellServer:
void startSerialSession(ShellServerSession *session) {
    uint8_t uartBuffer[1024];
    uint32_t uartBytesRead;

    while (1) {
        uartBytesRead = UARTCharsAvail(UART0_BASE) ? UARTRead(UART0_BASE, uartBuffer, sizeof(uartBuffer)) : 0;
        if (uartBytesRead > 0) {
            shellServerWriteStream(session, (char *)uartBuffer, uartBytesRead, NULL, 0);
        }

        char shellBuffer[1024];
        size_t shellBytesReceived = 0;
        error_t readError = shellServerReadStream(session, shellBuffer, sizeof(shellBuffer), &shellBytesReceived, 0);

        if (readError == NO_ERROR && shellBytesReceived > 0) {
            UARTWrite(UART0_BASE, (uint8_t *)shellBuffer, shellBytesReceived);
        }
        osDelayTask(10); // To prevent CPU overload
    }
}

Specific Question: 
- How can I ensure that the entire data payload is transmitted without truncation and preserves the intended formatting?
- In the context of UART communications, what are the recommended strategies for explicitly handling special characters such as carriage returns and line feeds? How can I ensure these characters are correctly processed to maintain data formatting between UART and SSH?
- How critical is it to have synchronized hardware settings like baud rate, parity, and stop bits across communicating UART devices? Can slight discrepancies lead to significant communication errors, and how can I best verify and align these settings?
- I'm considering implementing CRC checks or a simpler checksum method to ensure data integrity during UART communication. Does anyone have advice on the most efficient methods to implement these checks in embedded systems, particularly for the TM4C1294 microcontroller?

Additional Details:

  • Baud rate: 115190
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • UART Config - Base: 0x4000C000, Clock: 120000000 Hz, Baud: 115190, Data Bits: 8 bits, Parity: None, Stop Bits: 1 stop bit, Flow Control: None Current configuration displayed.

Thank you for any suggestions or guidance you can provide!

  • Hi,

      Are you in interrupt mode or polling mode?

      If you try a slower baudrate like 9600, does it make a difference? This experiment will help determine if the problem is due to baudrate. 

      I use the below code in interrupt mode with baudrate at 119200 and use Hercules utility to read a text file that has the same content as yours and I don't see any issue. I will suggest you try the the below code and see if it makes a difference. 

    #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 = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE,
                                       MAP_UARTCharGetNonBlocking(UART0_BASE));
        }
    }
    
    //*****************************************************************************
    //
    // 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.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
        }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // 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 = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_240), 120000000);
                                                 
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    
        //
        // Enable the GPIO pins for the LED (PN0).
        //
        MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
    
        //
        // Enable the peripherals used by this example.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable processor interrupts.
        //
        MAP_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
        MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        MAP_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
        //
        // Enable the UART interrupt.
        //
        MAP_IntEnable(INT_UART0);
        MAP_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)
        {
        }
    }

  • Hello,  I have an update on my end;

    Changes Made:

    • Changed the polling mode at UART to interrupt mode.
    • Added an interrupt handler for UART4.
    • Connected an RS-232 Level Shifter to the UART4 port.

    New Issues: We tested the physical UART4 port on an RS-232 Level Shifter with three devices. One device worked partially, but the other two sent gibberish.

    Devices Tested:

    1. Device 1: (115200 baud) - Gibberish on SSH to reverse serial.
    2. Device 2: (9600 baud) - Gibberish on SSH to reverse serial.
    3. Device 3: (9600 baud) - Full output from the endpoint device on SSH to reverse serial, but input to it was gibberish.

    Device 1 and 2 Input/Ouput:

    Device3 Input/Output:

    The SSH to reverse serial functionality is working, but there are discrepancies in the configuration and initialization process that need to be resolved. 

    UART Initialization and Interrupt Handler:

    void PhyUART4Init(uint32_t baudrate) {
        uint32_t ui32SysClk = 120000000; // System clock frequency
    
        // Enable GPIOK and UART4 peripherals
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
    
        // Wait for the peripherals to be ready
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART4));
    
        // Configure GPIO pins for UART4
        GPIOPinConfigure(GPIO_PK0_U4RX); // PK0 as U4RX
        GPIOPinConfigure(GPIO_PK1_U4TX); // PK1 as U4TX
        GPIOPinTypeUART(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        // Set UART4 configuration
        UARTConfigSetExpClk(UART4_BASE, ui32SysClk, baudrate,
                            UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
    
        // Enable the UART FIFO
        UARTFIFOEnable(UART4_BASE);
        UARTFIFOLevelSet(UART4_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
    
        // Register and enable UART interrupts
        UARTIntRegister(UART4_BASE, UART4IntHandler);
        UARTIntEnable(UART4_BASE, UART_INT_RX);
        IntEnable(INT_UART4);
    
        // Enable the UART for operation
        UARTEnable(UART4_BASE);
    
        // Debug: Log UART configuration completion
        TRACE_INFO("UART4 configured with baud rate: %u\n", baudrate);
    }
    
    void UART4IntHandler(void) {
        uint32_t ui32Status;
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        char data;
    
        ui32Status = UARTIntStatus(UART4_BASE, true);
        UARTIntClear(UART4_BASE, ui32Status);
    
        if (ui32Status & UART_INT_RX) {
            while (UARTCharsAvail(UART4_BASE)) {
                data = (char)UARTCharGetNonBlocking(UART4_BASE);
                xQueueSendToBackFromISR(qUART4, &data, &xHigherPriorityTaskWoken);
            }
        }
    
        if (xHigherPriorityTaskWoken == pdTRUE) {
            portYIELD();
        }
    }
    

    UART Read and Write Functions:

    uint32_t UARTRead(uint32_t ui32Base, uint8_t *buffer, uint32_t length) {
        uint32_t i;
        for (i = 0; i < length; ++i) {
            if (!UARTCharsAvail(ui32Base))
                break;
            buffer[i] = UARTCharGet(ui32Base);
        }
        return i;
    }
    
    void UARTWrite(uint32_t ui32Base, const uint8_t *buffer, uint32_t length) {
        for (uint32_t i = 0; i < length; ++i) {
            UARTCharPut(ui32Base, buffer[i]);
        }
    }
    

    Session Handling:

    void startSerialSession(void *pvParameters) {
        uint8_t uartBuffer[1024];
        char data;
    
        while (1) {
            uint32_t uartBytesRead = 0;
            while (xQueueReceive(qUART4, &data, 0) == pdTRUE) {
                uartBuffer[uartBytesRead++] = data;
                if (uartBytesRead >= sizeof(uartBuffer)) {
                    break;
                }
            }
    
            if (uartBytesRead > 0) {
                shellServerWriteStream(g_serialSession, (char *)uartBuffer, uartBytesRead, NULL, 0);
            }
    
            vTaskDelay(10); // To prevent CPU overload
        }
    }
    

    Specific Questions:

    1. How can I ensure compatibility with different devices to avoid receiving gibberish data?
    2. Are there recommended configurations for UART parameters (baud rate, parity, stop bits) that enhance compatibility across various devices?
    3. How can I refine the initialization process to address discrepancies in UART communication with different devices?
    4. What debugging strategies or tools can help identify and resolve these communication issues?

    Additional Details:

    • Baud rate: 115200 (Device 1) and 9600 (Devices 2 and 3)
    • Data bits: 8
    • Parity: None
    • Stop bits: 1
    • UART Config - Base: 0x4000C000, Clock: 120000000 Hz, Baud: 115200/9600, Data Bits: 8 bits, Parity: None, Stop Bits: 1 stop bit, Flow Control: None

    Thank you for any suggestions or guidance you can provide!

     

  • Hi Can,

    We found the UART cannot RX/TX 32 bytes using 16 word FIFO R/W mode without monitoring the buffer empty flag in non-blocking high speed serial data transports. Perhaps try reducing (assuming you have implemented ringbuffer.c) to 16 word R/W. Otherwise slow down TX/RX loops using SysCtrlDelay(MyDelayPeriod) zoom in on timing issues even in interrupt level FIFO mode. 

    Regards, 

  • Hi,

      Looks like you are using FreeRTOS. Have you tried my posted code? If you have not tried my bare-metal code, why don't you try it first? If you are getting  gibberish data, then I tend to think the problem is related to both sides not having the the same baudrate or configuration. If the cause is due to data buffering then the result would be missing data instead of gibberish data. 

     I will suggest you send simple data to begin with for easier diagnose/debug. Try sending just a few characters first. You can examine the receive buffer and see if the buffer contains the correct data. This way it is easier to isolate the problem. 

  • Hi Genatco,
    I will try your recommendation regarding the FIFO R/W mode. I haven't implemented
    ringbuffer.c, but I'll look into adjusting the buffer size and incorporating SysCtrlDelay(MyDelayPeriod) to address potential timing issues. I'll update you with the results.

  • Hi Charles,
    Yes, I am using FreeRTOS and currently isolating the problems to determine if it’s due to baud rate/configuration mismatches, data buffering or else. I'll check again by sending simple data and check the receive buffer for accuracy, maybe compare them out with an oscilloscope. I'll follow up with the outcomes of these tests shortly. Thanks again for your guidance.

  • Hi Can,

     One more thing to check if SSH performs any data encryption. I don't know how SSH works. You will need to check if there is any encryption/decryption required or plaintext can be used.