Fish On, Fish Off: Part 2
In ELJ's January/February 2001 issue, I described the installation of an open-source home automation CGI Sparkler, a home-automation product, on a desktop Linux machine. This article describes installing Sparkler on an embedded system using the popular embedded Linux distribution, Hard Hat Linux (HHL). Given the diversity of embedded boards available today, I chose to make the article as useful as possible by giving detailed information about the principles involved in setting up an embedded system. This should prove useful regardless of which embedded system you select.
In order to keep the implementation applicable to the greatest number of embedded systems, I chose to limit the size of installation to 1.44MB, so it will fit on a floppy disk. This requirement will accommodate embedded systems with severe resource limitations.
Booting from the floppy disk is akin to booting from the EEPROM in a diskless embedded system. The main difference is the logistics of moving the prepared image to permanent memory in the particular device and instructing the device to boot from that image. Though it may seem like a logistical nightmare to move a Linux installation image to an embedded system that does not have a hard disk drive or a floppy drive, most embedded systems contain the necessary utilities and software programs to facilitate the installation onto the device of choice. Usually, this consists of a device boot-time utility that facilitates loading the image to the device via TFTP to the necessary memory location of the EEPROM.
Since we are trying to run Sparkler on an embedded device, it is necessary to use a CGI-capable web server with minimal memory and disk-space requirements. For this purpose, I chose thttpd (see Resources), a popular low-resource, high-speed web server. It is necessary to configure and compile the thttpd package to create a binary for inclusion into the RAM disk image.
Since the lightweight C library included with HHL does not support the C library getpwnam function, thttpd cannot verify that the user ``nobody'' is present when it runs, causing thttpd to fail. I worked around this limitation by looking up the uid and gid for the user ``nobody'' in the HHL /etc/passwd and /etc/group files. Then I commented out lines 264-273 in thttpd.c and hard-coded the uid and gid values in the source code at line 275:
I'm sure that many C wizards out there could have come up with a better workaround. After making this change, a simple ./configure and make will build the program.
Sparkler and BottleRocket software are also necessary. In my previous article, I assume the use of the Apache web server, and I mention using ScriptAlias to create a /sparkler server path. Since thttpd does not contain as many fancy features as Apache, I chose to place Sparkler at the /cgi-bin/sparkler server path. This requires a change to a CGI form parameter in the Sparkler source. Find lines 86 and 96 in the Sparkler source and change /sparkler to /cgi-bin/sparkler. A better solution will be implemented in a future version of Sparkler. Once this change is made, Sparkler can be compiled, as described in the previous article, using a simple make. BottleRocket can be compiled with a simple ./configure and make similar to that of thttpd.
The first step to getting an embedded Linux system up and running is to prepare a kernel that contains the drivers for the peripherals available on the particular device. I started working from the Linux/demos/Microwindows directory on the Hard Hat Linux distribution CD. This directory provides the necessary scripts to create new images and to create a working boot floppy disk. The kernel provided contains just enough device support to demonstrate the Microwindows graphical user interface. Since a CGI application such as Sparkler requires additional functionality, I found it necessary to compile my own kernel for the system I was working on.
The Hard Hat Linux distribution CD contains a sample Linux kernel with minimal device drivers. In order to get Sparkler running, I decided that I would need both Ethernet and serial device support, which are not provided by the demonstration Hard Hat Linux kernel. I chose the latest stable Linux kernel, version 2.2.18, and configured it for functionality that includes support for serial, Ethernet and a few other necessities. See the Linux Kernel HOWTO for information on compiling a Linux kernel.
Hard Hat Linux provides some extremely helpful sample scripts to create a Linux initrd image that the kernel can mount as a RAM disk. A small Linux system and any application that will fit within the space constraints of a floppy disk can be included in this image. It is necessary to modify the HHL scripts to add our applications to the existing HHL default image.
The scripts that I used were included in the demos directory on the HHL distribution CD. I modified the script that created the RAM disk so that we could include the web server, Sparkler, and network utilities to configure the system's IP address and routing.
You will have to modify the scripts to reflect the paths and locations of your own software. You will also have to set the hostname of your device by changing the /bin/hostname goby.test.com line in the scripts to reflect the hostname of your own machine. You must also change the parameters to the ifconfig and route commands to reflect the IP address and routing information for the network that you are placing your device on. (I used the internal network IP addresses 192.168.0.x as a placeholder in Listing 1 and 2 [available at ftp://ftp.linuxjournal.com/pub/elj/listings/issue2]--these will not work on the Internet.)
Keep in mind that the scripts are distributed with HHL, and they expect the HHL CDK (Cross Development Kit) to be installed. Instructions are included with the HHL distribution on installing the RPMs that contain the compiler, libraries and other utilities.
In order to install our newly built applications properly in the image, commands must be added to the makeramdisk script as seen in Listing 1. These commands copy each application from where it resides on the host system to the /tmp/ramdisk_staging directory where the script will make an image out of it.
The first set of commands that I added to makeramdisk copy BottleRocket and set up the /dev/firecracker symbolic link that will point to the serial device to use. Remember that the Linux devices /dev/ttyS0 maps to COM1 in DOS/Windows and /dev/ttyS1 maps to COM2 in DOS/Windows.
The next sets of commands copies in Sparkler, thttpd and the libcrypt library that thttpd needs at runtime. I also added commands to the rc.sysinit startup script to set the hostname of the device, configure an IP address and set up routing for the device so that it can communicate on the Internet.
Once you have made the changes described above and you have properly installed the HHL CDK, you are now ready to create the image. Copy your newly built Linux kernel into the working directory. I copied the Microwindows directory from the CD and made changes in my home directory. Replace the default vmlinuz Linux kernel image with the one that you just built, and run the makeramdisk script. It should execute properly and create an image. It mounts the image to /tmp/ramdisk, so you can check to make sure that everything is okay. If this completes successfully, you can run the makefloppy script [see Listing 2 at ftp://ftp.linuxjournal.com/pub/elj/listings/issue2] program with a floppy disk, in your floppy drive and it will create a bootable-Linux disk with your new applications.
Once you have finished creating your bootable disk, start up your device with the disk in the drive, and carefully watch the screen to make sure that startup occurs successfully. Don't forget to connect your X10 Firecracker controller to the appropriate serial port of your device. Once startup completes, use the ps command to make sure that thttpd is running. Then pull out your wireless phone, access the URL of your device, and you should now be able to control the lighting in your house using your new embedded system.
The most common problem you may experience is not having a properly built kernel image. Make sure that you have enabled initrd, ramdisk and loopback support. Also, make sure that you have chosen the correct Ethernet driver for your device.
Try to determine where your setup is failing. Pay attention to whether the problem is that the kernel is not loading properly or that the image did not get created properly. The difficulty of diagnosing problems is compounded by the fact that you may not have all the tools available that you would on your desktop Linux system due to space constraints. You may have to use trial and error to determine what specific issues to resolve for your particular configuration.
In ELJ's January/February 2001 issue, my article described getting Sparkler set up on a desktop Linux system and some of the low-cost home automation possibilities available to today's computer users. This time, I described the step-by-step process that I went through using HHL to build a small, self-contained embedded Linux configuration that fits on a floppy disk. With little modification, these instructions can be applied to embedded systems that lack a floppy drive as a boot device. The procedure described in this article could also be applied to the PowerPC architecture since HHL includes both Linux and PPC cross-platform development tools. I hope that my description of the embedded development process will give confidence to those who are intimidated by the unknown and often frustrating world of developing on and for resource-constrained embedded systems.
Erik Lotspeich (firstname.lastname@example.org) is a software developer for ELC Technologies (http://www.elctech.com/) who actually does control his fish lighting from his cell phone.