3.9.1. Use UART¶
3.9.1.1. Overview¶
This section describes how to access a UART module in user space applications. The section introduces some Linux infrastructure to expose UART runtime information, which is helpful in debugging UART applications. Some UART debugging tools and tips are also covered here.
When a UART instance is enabled in kernel devicetree and its corresponding kernel drivers are enabled in the kernel config (see details in Porting UART), then the UART module is exposed as a device node /dev/ttyS<x> in the Linux filesystem. <x> is the index defined in serial aliases in the kernel devicetree.
For example, devicetree file k3-am64.dtsi
has
aliases {
...
serial2 = &main_uart0;
...
};
which indicates serial index 2 is assigned to MAIN UART0. Thus, /dev/ttyS2 represents the MAIN UART0 module in Linux.
3.9.1.2. UART Applications¶
User space applications access UART via its device node /dev/ttyS<x> in a similar way as accessing regular files. The UART is accessed using open(), close(), read(), write(), and ioctl(). Some TTY specific functions, such as tcsetattr(), are available for configuring or controlling the UART port. The details are covered in Linux TTY programming topics in many resources on the internet.
The serial testing tools mentioned below in UART Test Utilities can be used as a reference to UART programming.
3.9.1.3. UART in Kernel Boot Log¶
UART initialization information is provided in the kernel boot log (dmesg). For example:
# dmesg | grep 'ttyS. '
[ 0.296705] 2800000.serial: ttyS2 at MMIO 0x2800000 (irq = 18, base_baud = 3000000) is a 8250
shows that /dev/ttyS2
is assigned to a UART with base address 0x2800000,
which is MAIN UART0 according to k3-am642-evm.dts.
3.9.1.4. UART in /proc Filesystem¶
Linux provides some information of UART ports in /proc filesystem, which is helpful in debugging UART application issues.
/proc/interrupts
/proc/interrupts
entry provides interrupt information at Linux runtime. To
only see the UART interrupts:
# grep serial /proc/interrupts
18: 712 0 GICv3 210 Level 2800000.serial
For details of procfs interface, please refer to kernel Documentation procfs.
/proc/tty
/proc/tty/driver/serial
entry provides some UART runtime statistics. For
example,
# cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:unknown port:00000000 irq:0
1: uart:unknown port:00000000 irq:0
2: uart:8250 mmio:0x02800000 irq:18 tx:11822 rx:88 RTS|CTS|DTR
3: uart:unknown port:00000000 irq:0
4: uart:unknown port:00000000 irq:0
5: uart:unknown port:00000000 irq:0
6: uart:unknown port:00000000 irq:0
7: uart:unknown port:00000000 irq:0
8: uart:unknown port:00000000 irq:0
9: uart:unknown port:00000000 irq:0
shows /dev/ttyS2
has transmitted 11822 characters and received 88 characters.
3.9.1.5. UART Test Utilities¶
There are many serial testing tools in the Linux open source community. The following are a few examples which can be compiled and run on AM64x:
serialcheck
serialcheck provides two
utilities, serialcheck
and serialstates
.
serialcheck
sends characters from a data file to a UART port at a given
baud rate. When in receiving mode (using option -m r), serialcheck
uses the same data file to check the received characters for data
integrity.
# ./serialcheck --help
Usage: serialcheck [OPTION...]
user stress testing tool
-b, --baud=NUM baudrate
-d, --device=FILE serial node device
-f, --file=FILE binary file for transfers
-h, --hflow enable hardware flow control
-k, --loopback loopback mode
-l, --loops=NUM loops to perform (0 => wait fot CTRL-C
-m, --mode=M transfer mode (d = duplex, t = send r = receive)
-n, --no-termios No termios change (baud rate etc. remains
unchanged)
-?, --help Give this help list
--usage Give a short usage message
serialstates
periodically monitors the given UART port and prints its
runtime status. This is useful for checking for line errors.
# ./serialstats --help
Usage: serialstats [OPTION...]
uart stats tool
-d, --device=FILE serial node device
-i, --interval=NUM interval in seconds
-o, --once print stats once and exit
-?, --help Give this help list
--usage Give a short usage message
For example:
# ./serialstats -d /dev/ttyS2 -o
cts: 0 dsr: 0 rng: 0 dcd: 0 rx: 400 tx: 21995 frame error 0 overuns 0 parity: 0 break: 0 buffer overrun: 0
linux-serial-test
linux-serial-test is another
UART stress test tool. linux-serial-test
is different from serialcheck
because it will:
generate sending characters internally, instead of using an external data file.
support divisor option which can be used for custom baud rates, especially helpful for the 13x mode in AM64x UART.
support sending single byte. For example, with option -y 0x55 -z 0x0 it sends 8-bits line toggles followed by line at 0. This is helpful when using a scope to check the accuracy of the baud rate.
support RS-485 mode.
Usage:
# ./linux-serial-test -h
Linux serial test app
Usage: linux-serial-test [OPTION]
-h, --help
-b, --baud Baud rate, 115200, etc (115200 is default)
-p, --port Port (/dev/ttyS0, etc) (must be specified)
-d, --divisor UART Baud rate divisor (can be used to set custom baud rates)
-R, --rx_dump Dump Rx data (ascii, raw)
-T, --detailed_tx Detailed Tx data
-s, --stats Dump serial port stats every 5s
-S, --stop-on-err Stop program if we encounter an error
-y, --single-byte Send specified byte to the serial port
-z, --second-byte Send another specified byte to the serial port
-c, --rts-cts Enable RTS/CTS flow control
-B, --2-stop-bit Use two stop bits per character
-P, --parity Use parity bit (odd, even, mark, space)
-e, --dump-err Display errors
-r, --no-rx Don't receive data (can be used to test flow control)
when serial driver buffer is full
-t, --no-tx Don't transmit data
-l, --rx-delay Delay between reading data (ms) (can be used to test flow control)
-a, --tx-delay Delay between writing data (ms)
-w, --tx-bytes Number of bytes for each write (default is to repeatedly write 1024 bytes
until no more are accepted)
-q, --rs485 Enable RS485 direction control on port, and set delay
from when TX is finished and RS485 driver enable is
de-asserted. Delay is specified in bit times.
-o, --tx-time Number of seconds to transmit for (defaults to 0, meaning no limit)
-i, --rx-time Number of seconds to receive for (defaults to 0, meaning no limit)
-A, --ascii Output bytes range from 32 to 126 (default is 0 to 255)