3.9.1. Use UART¶
3.9.1.1. Overview¶
This section describes how to access an UART module in user space applications, and introduces some Linux infrastructures for exposing 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 kernel config (see details in Porting UART), the UART module is exposed as a device node /dev/ttyS<x> in Linux filesystem, where <x> is the index defined in serial aliases in kernel devicetree.
For example, devicetree file k3-am64.dtsi
has
aliases {
...
serial2 = &main_uart0;
...
};
which indicates serial index 2 is assigned to MAIN UART0, then /dev/ttyS2 represents MAIN UART0 module in Linux.
3.9.1.2. UART Applications¶
User space applications access UART via its device node /dev/ttyS<x> in the similar way as accessing regular files, 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 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 kernel boot log (dmesg). For example, the following shows how to check which UART(s) are enabled.
# dmesg | grep 'ttyS. '
[ 0.296705] 2800000.serial: ttyS2 at MMIO 0x2800000 (irq = 18, base_baud = 3000000) is a 8250
It shows /dev/ttyS2
is assigned to UART which base address is 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. 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 in a given
baud rate. When in receiving mode (using option -m r), serialcheck
uses the same data file to compare with 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, which is useful for checking any line error.
# ./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. The main differences from serialcheck
are
- generate sending characters internally, instead of using 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)