Creating a BSD embeded system — user experiences
This is a collection of users' accounts on building / creating embeded BSD projects.
The following article describes an embeded project that creates "voice verification system". Please note that this project was based on FreeBSD version 4.1. So understand that process today would be different (some amendments have been added).
BSD embeded Voice Verification System
For the last few weeks, I've been designing an embedded system for voice verification. The embedded microcomputer will sit near a door and determine whether a user should gain entry to the building or not.
Such a system is very different from a normal PC; the microcomputer is dedicated entirely to one specific function. Its sole purpose is to perform its assigned task. In other words, it will be embedded into a system. There will be no keyboard, or display. It must boot and start performing its assigned function automatically.
In this article, I'll share an experience with you that will give you an idea of what's involved in producing an embeded system using BSD. This will show you how you can design an embedded system of your own. You can use this information to convert an old 386, or 486 machine into a dedicated robot controller, a complete home appliance/lighting/sprinkler controller, or even a router! Specifically, I'll use FreeBSD for this example, but this could probably also be done with any UNIX-like OS – such as Linux.
The hardware
My clients purchased a large number of 133-MHz Pentium PC-104 boards and sound cards. For those of you who aren't familiar with the PC-104 standard; they're a very small PC that can fit in a space about the size of a standard 3½ inch floppy disk drive. The computer has an onboard semiconductor flash disk that emulates a 24Mb hard drive, too. Quite simply, it's a complete PC, with BIOS, a 24Mb hard drive, with a sound card.
I expected this job to be very easy — in fact is is! But I didn't do it right the first time — as you'll soon see. I figured all I had to do was get the OS working on the board, make sure that I could read and write to the sound card and the COM port, and make sure that the voice verification software worked. I figured that all that was necessary, was to write some control logic to make the unit perform the appropriate tasks in the proper sequence. Of course, anything that involves computers (especially PCs) never works as planned. The client already had voice verification software, and an operating system. This operating system simulated Window$ in almost every way, but it lacked support for the sound card. The maker of the sound card provided device drivers, but the drivers only supported playing samples — not recording them.
Trouble ahead
At this point, I realized some potential issues – either I had to convince the operating system company, or the board manufacturer to produce a working device driver that would support the sound card. I was unsuccessful in both endeavors, and I began to consider my alternatives. By the way, this type of situation is why closed source software is ultimately a FAIL — If it doesn't work, you have no recourse, other than choosing not to use it. Which exemplifies the real value of open source software.
First, I studied the flash hard drive emulator chip to see if FreeBSD supported it. I went to a FreeBSD chat room and talked with several FreeBSD developers. They told me that support for the chip did indeed exist. Next, I examined the kernel configuration file. In the Lint file, which is the FreeBSD kernel documentation for all supported features, I found a line that explained how I could add support for the DiskOnChip 2000.
If I were more familiar with the current Linux kernel, I might have considered using it for this project instead of FreeBSD. To support this chip in Linux, I would have had to apply a patch to the Linux kernel, which I think is kind of a kludge. I didn't want to patch my normal system kernel, and I would have had to copy everything to a separate location. Clearly, FreeBSD was the answer.
FreeBSD kernel configuration
FreeBSD
kernel configuration is unbelievably painless and easy. Instead of
answering a lot of questions (which you must do when configuring a Linux
kernel), I just copied the
Generic
file to a new name. Then, I chose additional features from the
Lint file and added them to my new file. The
specific lines that I wanted from Lint
were:
# M-systems DiskOnChip products # see src/sys/contrib/dev/fla/README device fla0 at isa?
and
# For non-pnp sound cards with no bridge drivers only: device pcm0 at isa? irq 10 drq 1 flags 0x0 # # For PnP/PCI sound cards device pcm
By placing these lines into my new kernel configuration file, I created a new specification for a kernel that includes additional support for the DiskOnChip and most of the sound cards. I also provided permanent documentation for the kernel. Which means that I can mail this configuration file to other people who have FreeBSD systems and they can build an identical kernel. If someone lacks the necessary resources for building a kernel, that user can send specifications to another FreeBSD user (like me), who can then create the desired kernel and return it.
Once you have the
configuration
file, all you need to do to create a kernel is run:
# config <Kernel Configuration File Name>
NOTE
The above – while still valid, is an old, and cumbersome path to configuring, and building a kernel. The modern, and far more streamline path is to use the following command:
# make buildkernel KERNCONF=MYKERNEL
where "MYKERNEL" is the name you chose for your kernel config file (KERNCONF).
At this point, for the sake of this article, you'd be done building the kernel. But, for the sake of completness, we'll continue the path using the old method, so as to provide a bit more depth into what occurs during a kernel build.
Old proceedure continued...
This command builds the kernel directory and makes the appropriate
changes within the makefile and other important files. When this
procedure finishes, your machine will remind you to change the directory
to the one that was just created, and it will tell you to run the make
depend and the make kernel commands.
The following command places you in the correct directory for building
the kernel:
# cd ../../compile/<Kernel Configuration File Name>
The next step determines which object files need to be recompiled and which ones can be reused from previous compiles. The appropriate command is:
# make depend
This is command actually builds the kernel:
# make kernel
Normally, I would follow this step by typing make install, which causes the new kernel to replace the kernel that the system normally boots. I didn't want to use this kernel on my workstation, so I omitted the install step.
Boot floppy
I had a kernel that I thought would work on my target platform. My next step was to create a custom boot floppy that will include this new kernel. My first effort to create a special boot floppy was to replace the kernel file on the floppies. (There are two: the first is kern.flp, and the other is mfsroot.flp). Then, I was able to watch the floppy boot and recognize both the sound card and the DiskOnChip 2000. As FreeBSD boots, it lists which devices are detected. Watching the kernel detect both of these devices was like finding the Holy Grail of this project.
The custom boot floppies managed to detect the devices, but they didn't actually boot the system. As it turns out, making boot floppy images isn't an easy chore. It's very difficult, and I strongly recommend that you leave this task to the experts. Of course, I could have avoided the entire situation if I had obtained an IDE cable for this PC-104 board. For some reason, the manufacturer gave me all sorts of grief when I tried to persuade them to sell me their special IDE cable. I asked them to send it to me via overnight delivery, but I still hadn't received it after a week. If they had been nicer to me, I would give them a great recommendation. Too bad, too, because the main computer board and the accompanying documentation were excellent.
Doing things correctly — D'OH!
The correct way to build a new FreeBSD system on the PC-104 platform is
as follows:
- Build a normal FreeBSD system on a hard drive
- Connect the hard drive to the PC-104 system
- Build the kernel with support for sound card and flash disk
- Reboot the system with the new kernel on the hard drive
Final touches
Once you've built your file system on the flash disk, you can copy all of the required files, change the rc file in the /etc directory so that it runs only those processes that you want to run on this mini-system, and change the /etc/fstab file so that it mounts only the flash disk. And you're pretty much done! There's one more important procedure: You must install a boot loader on the flash disk. You should accomplish that task with the /stand/sysinstall utility, though you also can use the sysinstall program to perform the fdisk, disklabel, and newfs operations.
If you set everything up correctly, you can remove the hard drive, and
the system will run off of the flash disk. The FreeBSD
boot loader is very
nice. It probes all of the available boot
devices dynamically. It presents you with a menu that offers something
similar to the following:
F1 – FreeBSD F5 – disk 2
Each line of the menu represents a bootable partition that's found on the current disk(s). Pressing [F5] forces the boot loader to probe the second disk for bootable partitions. It should probe every disk in the series until it finds a partition that you want. The best aspect of the boot loader is that it remembers your last choice and automatically selects that choice after a timeout period. Thus, if you press [F1] the first time, the system always boots the flash disk FreeBSD partition.
Booting and initializing
My next challenge was to make sure that the embedded FreeBSD system would boot and run my application program immediately. I thought about changing the boot loader to run my program instead of init; fortunately, better sense prevailed. Instead, I invoked my application in the last line of /etc/rc, and I threw it into the background with an & character at the end of the command. The initialization program brought up the system like usual, and my application ran just like initialization does when it starts up all the daemons. I like this solution because init also causes getty to offer the login prompt at all specified ports. Since the PC-104 board has two COM ports, I made one a console, which allowed me to debug the system over the COM port.
Sans video, sans keyboard
The only real question at this point was how the system would operate
without a video card. It's very easy to make the system function while
the console sits there. The target platform
wouldn't have a VGA card or a keyboard, but that's unimportant to
FreeBSD. You can reroute the console to any
device in your
/etc/ttys file that you want. All I
had to do was change the following line:
ttyd0 "/usr/libexec/getty std.9600" dialup off secure
to:
ttyd0 "/usr/libexec/getty std.9600" dialup on secure
You can reroute the console during boot by editing the /boot/defaults/loader.conf file and adding this line:
console="comconsole"
In reality, FreeBSD is smart enough to find a COM port that will display console information if it can't find the normal VGA device. This way, however, you can force FreeBSD to a serial port. After making these changes, I had an embedded system that sent all console information to COM1 and that allowed for login either at the normal console, or at COM1.
The only other question about proper operation that might arise is whether or not the BIOS allows booting without a keyboard or video card. Fortunately, this specific brand of BIOS had an option that, when selected, disabled the function that checks these devices. Before you choose a PC for embedded use, you will definitely need to consider it's design. If you're turning an old 386 into a router, you don't want to have to attach a VGA card and a keyboard just to appease the BIOS.
So, what other projects might you try?
Maybe you've got an old 486 lying around and you want to turn into a router for your home network. You could fill all the ISA slots with Ethernet adapters and run a minimal distribution of FreeBSD on the system. You could get along with a leftover 100-MB hard drive — normally, I wouldn't consider the use an old hard drive because they're prone to failure. But since this would be a router, however, all of the important information would be maintained on another host anyway. In this system, the hard drive would exist exclusively for retaining code and data for operation. The worst thing that could happen would be the loss of some invaluable log file information.
Is a home appliance control center more your style? Well, let's add a voice modem/sound card to the system, and we'll buy some remote control equipment. X10 offers remote control light switches that respond to FM signals that are sent over the power wires in your home. Of course, you have to install these switches and remove the existing light switches, but then you can control the whole network from a central location. You could design a parallel port interface card that would latch the parallel data and control any number of relays. Then, you could use the relays to switch electrical circuits on and off.
Without the sound card and modem, you could use your computer to respond to timed events or network commands. If you add the sound card and modem and write a little software, you could create a dial-in menu system that would allow you to call home and make your computer respond to the DTMF (Dual Tone Multi-Frequency) tones on your telephone keyboard.