How to use UART for Diagnostic

From ESS-WIKI
Jump to: navigation, search

Linux serial port/UART access from userspace is provided through tty-devices under /dev. Depending on the driver used to drive the UART, those devices can have different names.


Configuration

From user space, one can use the command line utility stty to configure the serial speed. Then the port can be treated as as a regular file:

# stty -F /dev/ttyS1 115200
# echo Test > /dev/S1

Using C, use the struct termios to set the initial baud rate:

#include <termios.h>
...
struct termios tty;
int fd;
int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
 
fd = open("/dev/ttyS0", flags);
 
tcgetattr(fd, &tty);
 
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_cflag |= B115200;
 
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
    fprintf (stderr, "error %d from tcsetattr", errno);
    return -1;
}


A fixed list of baud rates are pre-defined:

Baud rate Symbol
921600 B921600
460800 B460800
230400 B230400
115200 B115200
57600 B57600
38400 B38400
19200 B19200
9600 B9600
4800 B4800
2400 B2400
1200 B1200

Non-standard baud rate

Vybrid modules

With the following userspace C program one can configure UART custom baud rates:


#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <asm/termios.h>
 
int main(int argc, char* argv[]) {
 
 int retval, fd, speed;
 struct termios2 ntio;
 
 if (argc != 3) {
  printf("Usage: %s /dev/ttyXXX 20000\n", argv[0], argv[0]);                  
  return -1;
 }
 
 speed = atoi(argv[2]);
 fd = open(argv[1], O_RDONLY);
 if (fd < 0) {
  perror("Open");
  return -1;
 }
 
 ioctl(fd, TCGETS2, &ntio);
 ntio.c_cflag &= ~CBAUD;
 ntio.c_cflag |= BOTHER;
 ntio.c_ispeed = speed;
 ntio.c_ospeed = speed;
 retval = ioctl(fd, TCSETS2, &ntio);
 close(fd);
 
 if (retval == 0)
  printf("New baud configured\n");
 else
  perror("ioctl");
 
 return 0;
}

RS-485

The Carrier Board implements RS-485 using a single transceiver in a half-duplex communication mode, which means that one medium is shared for transmitting and receiving data. The transceiver switches to transmit mode when the RTS signal is asserted (low active).

RS-485 defines the electrical characteristics of drivers and receivers for serial communication and supports bus topology. How RS-485 is exactly implemented depends on application and requirements. The RS-485 support has been tested using the configuration as found on Carrier Boards.

User Space

On carrier boards the following flags should be used:

...
    /* Enable RS485 mode: */
    rs485conf.flags |= SER_RS485_ENABLED;

    /* or, set logical level for RTS pin equal to 0 when sending: */
    rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);

    /* Set logical level for RTS pin equal to 1 after sending: */
    rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;

    /* Enable receiver during sending, required for i.MX devices */
    rs485conf.flags |= SER_RS485_RX_DURING_TX;
...

Enabling/disabling DMA

The current driver has a weak DMA implementation, which can lead to lock ups, especially on the RX side. The non-DMA (PIO) mode is much more robust, and thanks to the hardware FIFO also quite efficient. The easiest way to disable the DMA mode is to overwrite the dma-names property:

@@ -254,6 +254,7 @@
 
 &uart0 {
        status = "okay";
+       dma-names = "", "";
 };
 
 &uart1 {