Linux based Remote Terminal Server

During development and testing of embedded systems, the serial port is used for communicating with the host. This applies to firmware based embedded systems or Linux based embedded systems. But laptops and desktops today generally do not have a serial port. At Zilogic, we hit on this problem every time we go out for a corporate training.

One solution is to use a USB-to-Serial converter. But our experience shows that the USB-to-Serial converters available in the market are hardly reliable. Fed up with the USB-to-Serial converters we decided to develop our own Remote Terminal Server, which makes the serial port available over the network.

This article describes how to build a simple 4-port Remote Terminal Server, using a Linux and various other open source tools. We hope this also serves to show how a product can be built using Linux and other Free and Open Source software components.

User Interface and Design

The Remote Terminal Server user interface is kept as simple as possible - the user will access the serial port by telnetting to the box. The serial port can be selected by specifying the appropriate username serial1, serial2, serial3 and serial4.

When the user logins in with username serial1, instead of starting the shell, we start a terminal program like picocom on the corresponding serial port.

http://www.zilogic.com/static/images/rts-blocks.png
Figure 1. Blocks

Since the Remote Terminal Server is a networked device, it needs an IP address to communicate with the external world. The IP address can be obtained using a DHCP client. We will assume that all networks, we will be using the device on, will have DHCP server.

While DHCP works, the problem with DHCP is that, the IP address is dynamically assigned and the user will not know the address. We solve this using Service Location Protocol (SLP). With SLP, the user can probe the network to determine the IP address of systems providing a service. For more information see http://openslp.org/

Building Blocks

We need a board capable of running Linux, that has an ethernet interface and atleast 4 serial ports. The SAM9L-9260 Olimex Board, perfectly fits our requirements. We also require some custom hardware circuitry, since the Olimex Board only terminates one serial port.

http://www.zilogic.com/static/images/olimex.jpg
Figure 2. Olimex Board - SAM9L-9260

On the software side, for the base system we will be the standard the basic U-Boot, Linux and BusyBox. Apart from these we will be using the following applications:

Make sure you get the above programs, compile them and install them on to your target.

Integrating the Blocks

Given a system that already has Linux on it, we will see how we configure the system to make it work as Remote Terminal Server.

Kernel

By default the kernel is configured to support only 3 serial ports, one of which is used for the console. We configure 2 more serial ports available on the AT91SAM9260, by modifying the board specific code, as shown below.

--- linux-2.6.39.orig/arch/arm/mach-at91/board-sam9-l9260.c     2011-12-12 19:41:44.000000000 +0530
+++ linux-2.6.39/arch/arm/mach-at91/board-sam9-l9260.c  2011-12-12 19:54:20.000000000 +0530
@@ -63,6 +63,13 @@
        /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
        at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);

+       /* USART1 on ttyS3. (Rx & Tx) */
+       at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
+
+       /* USART1 on ttyS4. (Rx & Tx) */
+       at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
+
+
        /* set serial console to ttyS0 (ie, DBGU) */
        at91_set_serial_console(0);
 }

Shell Replacement

We create a bunch of scripts that will be invoked instead of the shell, when the user logs in. There should be one script for each serial port. The script for serial port /dev/ttyS1 is shown below.

#!/bin/sh

picocom /dev/ttyS1

Users

We create the users serial1, serial2, serial3, serial4 using adduser.

# adduser -s /etc/serial1.script -G uucp -D serial1
# passwd -d serial1

# adduser -s /etc/serial2.script -G uucp -D serial2
# passwd -d serial2

# adduser -s /etc/serial3.script -G uucp -D serial3
# passwd -d serial3

# adduser -s /etc/serial4.script -G uucp -D serial4
# passwd -d serial4

The login shell is specified using the -s option. In this case, it happens to be our script that launches picocom. The group is specified using the -G option as uucp, since udev by default sets the serial devices to group uucp. Passwords are not assigned by specifying the -D option.

Since we do not want login passwords, it also required to delete the passwords using passwd command, using the -d option.

IP Address and Service Discovery

On system boot up, we invoke udhcpc to acquire an IP address, and configure the network interface.

In a perfect world we would immediately get an IP address. But in reality, when the system boots up, the device might not have been plugged into the Ethernet network. udhcpc is designed to handle this as well. We start udhcpc as shown below.

# udhcpc -b -S eth0

The -b option tells udhcpc to run in the background if it cannot acquire an IP address immediately. It will try again after 20 seconds, by default.

The -S option tells udhcpc to log the messages to syslog.

When udhcpc acquires an IP address, it executes a script /usr/share/udhcpc/default.script by default. The script is passed the state as argument, and the acquired parameters in environment variables. The script is supposed to configure the interface if an IP address has been acquired. The script used in our case is shown below.

#!/bin/sh

[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1

case "$1" in
    deconfig)
            ifconfig $interface 0.0.0.0
            ;;
    renew|bound)
            ifconfig eth0 $ip ${broadcast:+broadcast} $broadcast ${subnet:+netmask} $subnet
            logger ifconfig eth0 $ip ${broadcast:+broadcast} $broadcast ${subnet:+netmask} $subnet
            killall slpd
            slpd -l /var/log/slpd.log
            slptool register service:serial.zilogic:telnet://$ip:23
            ;;
esac
exit 0

If an IP address has been acquired we configure the interface using ifconfig, restart slpd, and register our service using slptool.

We register our service with the service type serial.zilogic:telnet. The service can be searched for from the PC using the slptool as shown below.

$ slptool findsrvs service:serial.zilogic

Startup Script

The complete startup script /etc/rcS is listed below.

!/bin/sh

mount -a
mkdir /var/log

syslogd
klogd

hostname tuna

mknod /dev/ttyS0 c 4 64
mknod /dev/null  c 1 3
mknod /dev/console c 5 1

udevd --daemon
udevadm trigger

mkdir /dev/pts

mount devpts /dev/pts -t devpts

ifconfig lo 127.0.0.1
udhcpc -b -S

sleep 5
dropbear
telnetd

The Box

The additional hardware circuitry containing the transceiver for 4 serial ports is made on a prototyping board. The motherboard along with the proto board is wrapped up into a plastic enclosure.

http://www.zilogic.com/static/images/open-box.jpg
Figure 3. Inside the Box

Slots are cut out on the top of the box for the serial port connectors. The finished product in action is shown below.

http://www.zilogic.com/static/images/in-action.jpg
Figure 4. Remote Terminal Server in Action

Concluding Remarks

Well, the Remote Terminal Server serves as a good replacement for the USB-to-Serial converters. But this is just the beginning. You could think of a lot more improvements that can be made, like a web interface for configuration, using the GPIOs for resetting the boards, etc. Hope this article has also shown how a complete product can be built from the existing Free and Open Source components.

Credits

  • Thanks to PG, Kannan and Venkat for the enclosure and hardware design.

  • Thanks to Abdul for integrating the software components and testing the product.