Hardware for Headless Linux

In this book I’ll concentrate on PC Engines’ ALIX series of system boards. In principle most of the information here may be transferred to other hardware. I am limiting myself to this hardware because I have the most experience with these devices. I have tested nearly everything I have written here on these little machines.

Like the boards from Soekris, the ALIX boards are available as single board computer without moving parts. As long as I don’t install any moving parts (like harddisks) on the devices, I can eliminate mechanical wear (provided that the device itself does not get moved and is not attached to a car or anything similar).

The advantages of these devices are that they don’t require much power and are compatible with personal computers. I can choose from boards with up to three Ethernet interfaces for my project. The operating system fits onto a CompactFlash card (socket is on board) or onto a notebook harddisk that can also be connected to some of the boards. In principle I could load the operating system everytime from the network. Some of the boards have a Mini-PCI slot for expansion cards.

Most of these boards don’t have a video card or a port for a keyboard but they do have a serial connection. Even the BIOS is accessible through this serial console. Only a few models have VGA and PS/2 connections.

Tip

I usually use PuTTY on computers with MS Windows to access the serial console. This program allows me to set up the connection type in the configuration menu. If I choose serial, I can set the interface and the baud rate. There are more options under the category Connection/Serial.

I do have a larger selection on computers with Linux. I can also take PuTTY if I have a graphical desktop. Some of the programs I am able to use in an ASCII terminal include C-Kermit, Minicom and Picocom wich have quite a few setting options.

If I have not installed any of these programs before, I can use screen. This program is installed on nearly all of my Linux computers. With screen I can access a serial interface like this:

$ screen /dev/ttyS0 38400

or (without flow control):

$ screen /dev/ttyS0 38400,-ixon,-ixoff

There are also USB interfaces on the board. The boards without VGA have TinyBIOS in the flash ROM which allows for a few configuration options.

Tip

Press s during the memory test to enter setup in TinyBIOS. The operating manual describes the options available. It can be found at the webpage of PC Engines.

If I don’t plan to use a special housing for my project, I can usually find the right case where I buy the boards.

CompactFlash card

The boards of the ALIX.2 and the ALIX.6 series do have CompactFlash adapters so that you can put the operating system and the data on a CF card. That way the whole system remains compact and is less sensitive to mechanical wear and tear.

To extend the lifetime of the CF card I minimize the writing access by setting it to read-only. Alternatively I can use the TRIM command, which has been available since CompactFlash 5.0 came out, and a sufficient new Linux (with a kernel version of at least 2.6.33) as well as an appropriate file system (btrfs, ext4fs, fat, gfs2). These file systems may use the TRIM command to help with the wear leveling of the CF firmware.

LED

There are three LED on the boards that are visible through the case. I can use two kernel modules to control these LEDs: the leds_alix2 module and the cs5535_gpio module which can directly drive the pins of the GPIO chip CS5535. With kernel versions >= 2.6.33, I have to make sure that only one LED module loads. This can be done, for instance, through blacklisting in /etc/modprobe.d/blacklist:

blacklist cs5535_gpio

The LED module provides access to the LEDs via sysfs. To switch them on or off I use the file brightness:

# echo 1 > /sys/class/leds/alix\:3/brightness
# sleep 5
# echo 0 > /sys/class/leds/alix\:3/brightness

Using these three commands I was able to switch on the third LED and after five seconds switch it off again.

Additionally there are trigger modules that support some applications. I will introduce a few of them in a moment, but first lets look at the heartbeat trigger:

# modprobe ledtrig-heartbeat
# echo heartbeat > /sys/class/leds/alix\:2/trigger

This allows me to put a predetermined pulse pattern on an LED (in this case the second LED).

Next there is the timer trigger:

# modprobe ledtrig-timer
# echo timer  > /sys/class/leds/alix\:1/trigger
# echo 1000 > /sys/class/leds/alix\:1/delay_on
# echo 100 > /sys/class/leds/alix\:1/delay_off

In this example the first LED switches on for 1000 ms and then switches off for 100 ms repetitively.

To monitor the activity of IDE disks I can use the trigger ide-disk. I don’t need to load an extra kernel module to do this.

# echo ide-disk > /sys/class/leds/alix\:2/trigger

If I’m in the mood, I can emit Morse code signals with the LEDs:

# modprobe ledtrig-morse
# echo morse > /sys/class/leds/alix\:1/trigger
# echo "SOS" > /sys/class/leds/alix\:1/message
# echo 100 > /sys/class/leds/alix\:1/delay

I set the speed of the Morse code with the value that I enter under delay.

The netdev trigger is even more useful by allowing me to monitor network activity.

# modprobe ledtrig-netdev
# echo netdev > /sys/class/leds/alix\:2/trigger 
# echo ppp0 > /sys/class/leds/alix\:2/device_name 
# echo link tx rx > /sys/class/leds/alix\:2/mode

In this example the second LED switches on as soon as a PPP connection is established and blinks if there is any traffic going over this connection.

I can find out which triggers are momentarily available and active by reading the file trigger:

# cat /sys/class/leds/alix\:1/trigger 
none ide-disk [morse] default-on gpio heartbeat \
netdev timer usbdev
# cat /sys/class/leds/alix\:2/trigger 
none ide-disk morse default-on gpio heartbeat \
[netdev] timer usbdev

I deactivate the triggers by writing none in this file.

# echo none > /sys/class/leds/alix\:1/trigger
# echo none > /sys/class/leds/alix\:2/trigger
# echo none > /sys/class/leds/alix\:3/trigger

Tip

With ALIX 3D3 boards, LEDs may not be recognized from the kernel module leds-alix2. One reason could be that there is another BIOS on this board as there is onthe ALIX 2.x devices. In this case, entering leds-alix2.force=1 as a kernel boot parameter may help. Otherwise the loading of the kernel module is aborted with the message FATAL: Error inserting leds_alix2 (.../leds-alix2.ko): No such device.

Mode switch

There is a little switch on the ALIX boards that helps you enter the BIOS setup at system start if the serial interface has been deactivated. This switch is connected to pin 24 of the GPIO chip CS5536 and may be queried if kernel support for this chip is activated. Alternatively one can query bit 8 at I/O port 0x61b0. 0 signifies a pressed switch.

Kernel module

I can use the kernel module css5535-gpio with the kernel of Voyage Linux 0.7. In doing so I have to keep in mind possible problems with the kernel module leds-alix:

# modprobe cs5535-gpio
# ls -l /sys/class/gpio/
total 0
--w------- 1 root root 4096 Dec  7 07:24 export
--w------- 1 root root 4096 Dec  7 07:25 unexport
# echo 24 > /sys/class/gpio/export
# ls -l /sys/class/gpio/GPIO24/
total 0
-rw-r--r-- 1 root root 4096 Dec  7 07:31 active_low
-rw-r--r-- 1 root root 4096 Dec  7 07:31 direction
drwxr-xr-x 2 root root    0 Dec  7 07:31 power
lrwxrwxrwx 1 root root    0 Dec  7 07:31 subsystem \
-> ../../../../class/gpio
-rw-r--r-- 1 root root 4096 Dec  7 07:31 uevent
-rw-r--r-- 1 root root 4096 Dec  7 07:31 value
# echo in > /sys/class/gpio/GPIO24/direction
# cat /sys/class/gpio/GPIO24/value 
1
# echo 24 > /sys/class/gpio/unexport

Initially the directory /sys/class/gpio/ only contains the files export and unexport. Here I enter the number of the pin that I want to use. For the mode switch this is pin 24. After I enter this number in the file export, the kernel module opens up more pseudo files in the directory /sys/class/gpio/GPIO24/ to control and query the pin. At this point in time I’m only interested in the file direction, which determines whether I want to use the pin as input or output, and in the file value which allows me to read the value.

Query the I/O port

As an alternative to the kernel module I can directly read the I/O port through which the switch can be accessed. This can be done, for instance, using the following small C program:

mode-switch.c


 1 /* mode-switch.c - access mode-switch from ALIX Boards
 2  *
 3  * Exit value 0 means switch is pressed.
 4  */
 5 
 6 #include <sys/io.h>
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 
10 #define MSPORT 0x61b0
11 #define MSMASK 0x100
12 
13 int main() {
14 	if (ioperm(MSPORT,2,1)) {
15 		perror("ioperm");
16 		exit(255);
17 	}
18 	int status = 0 == (inw(MSPORT) & MSMASK);
19 	exit(status ? 0 : 1);
20 }

I compile the program like this:

$ gcc -O2 mode-switch.c -o mode-switch -m32

The option -m32 is important if I’m compiling the program on a 64-bit-system. Then I also need the package libc6-dev-i386 that contains some required header files.

For instance, to synchronize the system status with a keypress, I can use the above program to periodically query the state of the switch in an endless loop and backup the temporary data when the key is pressed:

1 while true; do
2   if /root/bin/mode-switch ; then
3     /etc/init.d/voyage-sync sync
4     sleep 60
5   else
6     sleep 1
7   fi
8 done

In this script the state of the switch is queried every second. This means I have to hold down the switch for somewhat more than a second to be sure that it is recognized. Once the keypress is recognized, the synchronization script is called up and the switch isn’t queried the next time for at least 60 seconds. Of course I could use one of the LEDs to signalize that the keypress was recognized.

Sensors

In order to query the sensors on the board, I can install the software package lm-sensors.

The kernel modules required are scx200_acb for the I²C controller and lm90 for the temperature sensors that are connected to the I²C bus.

I can query the sensors using the command sensors:

$ sensors
lm86-i2c-0-4c
Adapter: CS5536 ACB0
temp1:       +38.0 C (low  =  +0.0 C, high = +70.0 C)
                     (crit = +85.0 C, hyst = +75.0 C)
temp2:       +44.0 C (low  =  +0.0 C, high = +70.0 C)
                     (crit = +85.0 C, hyst = +75.0 C)

temp1 gives me a temperature reading of the main board and temp2 gives me a temperature reading of the processor.