A serial port is a communication interface that allows data to be transferred in or out of a computer one bit at a time. Moreover, serial ports are useful for connecting devices such as modems, printers, and network devices to a computer. In Linux, everything is a file, including devices, processes, sockets, pipes, and serial ports. Thus, we might want to find out which serial port device file corresponds to our physical serial port.
In this tutorial, we’ll understand what serial ports and /dev/ttyS* devices are and why it’s essential to identify them correctly. Finally, we’ll see to figure out the correct /dev/ttyS* for our serial port.
2. Serial Ports
Serial ports are useful for connecting devices that have low data transfer rates:
Basically, a serial port consists of a connector, a cable, and a controller.
The connector is the part that plugs into the computer or the device, and it has several pins that carry different signals. On the other hand, a cable is the wire that connects the connector to the controller. Importantly, it can be either straight-through or cross-over depending on the type of device. Finally, the controller is the circuit that converts the parallel data from the computer into serial data, and vice versa.
In general, serial data transmission follows a protocol that defines how the data is encoded, framed, and synchronized. To that end, the protocol specifies some parameters:
- baud rate: speed of data transmission in bits per second (bps)
- data bits: number of bits in each unit of data
- parity: method of error detection by adding an extra bit to each unit of data (usually none, even, or odd)
- stop bits: number of bits that indicate the end of a unit of data
- flow control: method of regulating the data flow between the sender and the receiver
Finally, the sender and receiver must agree on these parameters before communicating successfully.
3. What Is /dev/ttyS*?
/dev/ttyS* is a naming convention for serial ports on Linux systems. Further, the * is a number that indicates the order of the port:
- /dev/ttyS0 is the first serial port
- /dev/ttyS1 is the second serial port
Usually, /dev/ttyS0 corresponds to COM1, /dev/ttyS1 – to COM2, and so on. However, this may not always be the case depending on the hardware configuration and detection.
Further, /dev/ttyS* are character devices. This means they can be accessed byte by byte using file-like operations. For example, we can read from or write to a serial port using commands like cat or echo. We can also use programs like minicom or screen to interact with a serial port in a terminal-like interface.
4. How to Identify Available Serial Ports
We can identify the available serial ports using different commands. We’ll explore these in the sections that follow.
4.1. Using dmesg
dmesg displays the messages from the kernel ring buffer, which contains information about the hardware devices detected by the system. Thus, we can use dmesg in addition to the grep command to find out which serial ports are recognized by the kernel and their corresponding /dev/ttyS* names:
# dmesg | grep ttyS
[ 1.123456] 00:05: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 1.234567] 00:06: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
So, the output shows that the kernel detects two serial ports:
It also shows some additional information:
- I/O: indicates the I/O address where the serial port is located
- irq: specifies the interrupt request (IRQ) number associated with the serial port
- 16550A: a common UART (Universal Asynchronous Receiver-Transmitter) chip used for serial communication
Notably, dmesg displays only the detected serial ports. Further, UART is commonly used as a synonym for a serial port.
4.2. Using setserial
setserial allows us to get or set the configuration of a serial port device. Thus, we can use setserial to list the available serial ports and their parameters.
For instance, we can get the information about all the /dev/ttyS* devices:
# setserial -g /dev/ttyS*
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3
In the code snippet above, we use the -g option to retrieve and display the current configuration and state of the serial port devices. The output shows that there are four /dev/ttyS* devices on the system:
- ttyS0 and ttyS1 correspond to UARTs that the system recognizes (16550A)
- ttyS2 and ttyS3 have unknown UART types which means they’re not detected or are disabled by the operating system
The output also shows each port address and interrupt request number.
The /proc/tty/driver/serial file in the /proc pseudo-filesystem contains information about the serial port drivers and devices on the system. Therefore, we can use cat to read this file and see which UARTs were detected by the system:
$ cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
1: uart:16550A port:000002F8 irq:3 tx:111780 rx:1321 RTS|DTR|DSR
2: uart:unknown port:000003E8 irq:4
3: uart:unknown port:000002E8 irq:3
In the output above, tx and rx indicate how much data the port has transmitted and received. For instance, serial port 1 has transmitted 111780 characters and received 1321 characters. Further, RTS|DTR|DSR indicates that the RTS, DTR, and DSR flow controls are all present and active for the serial port with index 1.
5. How to Test Serial Ports
We can test the serial ports to verify their functionality and connectivity. In fact, there are several ways to test serial ports on a Linux system.
5.1. Using the cat Command
cat concatenates files and prints them to the standard output. Then, this output can be redirected to a file or device.
So, we can use cat to read data from a serial port device:
$ cat /dev/ttyS1
This reads data from the serial port device /dev/ttyS1 and prints it to the terminal. However, if the system can’t detect the serial port, it prints out an input/output error.
5.2. Using the minicom Command
minicom is a terminal-based program that allows us to interact with a serial port device in a user-friendly interface. Thus, we can use minicom to send and receive data from a serial port device and see it displayed on the screen.
For instance, let’s start minicom with the serial port device /dev/ttyS0 as the default device:
$ minicom -D /dev/ttyS0
The -D option enables us to specify the serial port device that we want to use with minicom. As a result, we’ll see a prompt screen:
Welcome to minicom 2.7
Port /dev/ttyS0, 08:17:30
Press CTRL-A Z for help on special keys
We can then type anything on the keyboard and see it sent to the serial port device. To access a menu of options and commands for minicom, we can press Ctrl-A, Z.
5.3. Using the screen Command
screen is also a terminal-based program that allows us to create and manage multiple terminal sessions in a single window.
Moreover, we can use screen to interact with a serial port device in a terminal-like interface:
$ screen /dev/ttyS0 9600
This starts screen with the serial port device /dev/ttyS0 at 9600 baud rate as the default session. Afterward, anything we type on the keyboard is sent to the serial port device. We can also see anything received from the serial port device displayed on the screen.
In this article, we learned what serial ports are. Further, we saw what /dev/ttyS* means and how to figure out which /dev/ttyS* our serial port is.
Serial ports are used for debugging and testing purposes, such as sending commands and receiving output from embedded systems, microcontrollers, and sensors. Without knowing which /dev/ttyS* corresponds to which serial port, we may not be able to communicate with the desired device or application, or may cause errors or conflicts with other devices or applications.