UART0 receives 0xFD

Hi,
I’m trying to use UART0 to communicate with some hardware connected to IOT expansion. It does basically work, I can receive and send data in both directions. The only issue is that sometimes the received characters are 0xFD. I checked for such an occasion the electrical signal with Logic Analyzer, and it seems to be fine. I have also activated odd parity and PARMRK, but I do not see an parity error. I also would not expect one to be honest, as the signal seems to be okay.

Log output:

Apr 14 11:14:19 swi-mdm9x28-wp user.info Legato:  INFO | App[6771]/App T=readThread | main.c readThread() 81 | FD
Apr 14 11:14:19 swi-mdm9x28-wp user.info Legato:  INFO | App[6771]/App T=readThread | main.c readThread() 81 | FD

Application (reduced to a minimal example):

#include "legato.h"
#include <termios.h>

static int uartHandle = 0;

static void initialize() {
    uartHandle = open("/dev/ttyHS0", O_RDWR | O_NOCTTY | O_NDELAY);
    
    if (uartHandle == -1) {
        LE_ERROR("unable to open UART");
        return;
    }
    
    fcntl(uartHandle, F_SETFL, 0);
    struct termios terminalSettings;
    int returnValue = tcgetattr(uartHandle, &terminalSettings);

    
    if (returnValue < 0) {
        LE_ERROR("unable to get current terminal settings");
        return;
    }

    terminalSettings.c_cc[VMIN] = 0; // do not require a minimum amount of bytes
    terminalSettings.c_cc[VTIME] = 1; // set the timeout to 100ms

    cfsetspeed(&terminalSettings, B115200);
    terminalSettings.c_cflag &= ~CSTOPB; // require only one stop bit
    terminalSettings.c_cflag &= ~CRTSCTS; // disable hardware control
    terminalSettings.c_cflag |= CLOCAL; // ignore modem control lines
    terminalSettings.c_cflag |= CREAD; // enable receiver
    terminalSettings.c_cflag |= PARENB; // enable parity generation on output and parity checking for input
    terminalSettings.c_cflag |= PARODD; // use odd parity
    terminalSettings.c_cflag &= ~CSIZE; // unset character configuration
    terminalSettings.c_cflag |= CS8; // use 8 bit characters

    terminalSettings.c_iflag |= INPCK; // enable input parity checking
    terminalSettings.c_iflag |= IGNBRK; // ignore break condition on input
    terminalSettings.c_iflag &= ~BRKINT; // turn BREAK into \0
    terminalSettings.c_iflag |= PARMRK; // forward characters with parity errors
    terminalSettings.c_iflag &= ~ISTRIP; // do not strip of eighth bit
    terminalSettings.c_iflag &= ~INLCR; // do not translate NL to CR on input
    terminalSettings.c_iflag &= ~IGNCR; // do not ignore carriage return on input
    terminalSettings.c_iflag &= ~ICRNL; // do not translate carriage return to newline on input
    terminalSettings.c_iflag &= ~IXON; // disable XON_XOFF flow control on input
    terminalSettings.c_iflag &= ~IGNPAR; // do not ignore framing and parity errors

    terminalSettings.c_lflag &= ~ECHO; // do not echo input
    terminalSettings.c_lflag &= ~ECHONL; // do not echo NL
    terminalSettings.c_lflag &= ~ECHOE; // do not echo ERASE
    terminalSettings.c_lflag &= ~ECHOK; // do not echo KILL
    terminalSettings.c_lflag &= ~ICANON; // disable canonical mode -> disable meaning of special characters, get every character immediately
    terminalSettings.c_lflag &= ~ISIG; // do not generate a signal for a special character
    terminalSettings.c_lflag &= ~IEXTEN; // disable implementation defined input processing

    terminalSettings.c_oflag &= ~OPOST; // disable implementation defined output processing

    returnValue = tcsetattr(uartHandle, TCSANOW, &terminalSettings);
    if (returnValue < 0) {
        LE_ERROR("unable to set terminal settings");
        return;
    }

    returnValue = tcflush(uartHandle, TCIOFLUSH);
    if (returnValue < 0) {
        LE_ERROR("unable to flush terminal IO buffers");
        return;
    }
    
    LE_INFO("successfully configured UART");
}

static void* readThread(void *context) {
    LE_INFO("uart read thread started");
    uint8_t buffer[3];
    
    while (true) {		
        int readBytes = read(uartHandle, buffer, sizeof(buffer));

        for (size_t i = 0; i < readBytes; ++i) {
            LE_INFO("%02X", buffer[i]);
        }
    }

    return 0;
}

COMPONENT_INIT {
    initialize();	
    le_thread_Ref_t readThreadHandle = le_thread_Create("readThread", readThread, 0);
    le_thread_Start(readThreadHandle);
    LE_INFO("initialization finished");	
}

Weirdly, this issues seems to happen only at the start of a transmission. If there is a longer byte sequence to be received I get the correct results from a certain point one, with one or two FD bytes prefixed.

Logic-Analyzer output:

I would be really glad if somebody could help me out here, as I am running out of options and ideas. Btw, I have already tried to reduce the baud rate to 9600. Just out of curiosity.

Regards,
benediktibk

you can disable the UART suspend mode and see if there is still problem:

1 Like

Works like a charm:

int returnValue = system("echo -1 > /sys/devices/78b0000.uart/power/autosuspend_delay_ms");

if (returnValue != 0) {
    LE_ERROR("unable to disable autosuspend for UART");
    return;
}

Mate, I owe you a beer.

Regards,
benediktibk