Creat: An Embedded Systems Project
Creat stands for Combined Resource Embedded Application Toolkit. It is a collection of tools pulled together from the Internet to permit Linux users (and, in the future, any UNIX users) to construct simple projects based on the Motorola MC68HC811 8-bit microcontroller. For the hardware part of the project, the idea was to provide a general microcontroller for students who wanted to have a small lump of computing power in their final-year projects; for those who wanted to specialize in applied microcomputing, to study the innards of the project. I wanted it to be accessible enough from “both ends”--programming and hardware—so that an expert in one would benefit from experience with the other. The whole project turned out to be a positive experience and a lesson in the benefits of cooperation and open software.
In choosing hardware for the exercise, I would have liked to obtain an up-market 16-bit microcontroller with Linux ported to it. This would have given seamless integration between host machine and target platforms, but even now, the cost of such a project is prohibitive in both cash and development time. The monster thus created would probably have been a significant overkill for the target application areas. At the very low end, the Linux community already has a range of useful utilities aimed at the PIC microprocessor (see “PIC Programming with Linux” by Brian C. Lane, Linux Journal, October 1998), which is a useful chip for replacing large quantities of logic with a single package. More ambitious projects might make use of a microcontroller port of Linux itself (see the Linux/Microcontroller Home Page by D. Jeff Dionne, http://ryeham.ee.ryerson.ca/uCinux/). My target was those projects in between: more processing power than you need to count events and run a multiplexed LED display and less than you need to run X. Our typical projects had an LCD display, a keyboard and some custom electronics to handle the project-specific I/O. The handling of interrupts might be important, together with enough flexibility to store a reasonable amount of data. The projects need to be highly testable and modifiable, but in the interests of economy, special hardware adapters and programmers were to be avoided.
With limited time and money, the clear way forward was to trawl the Net. More than just the hardware must be considered to build a useful system. To compete with the large and expensive kits in the marketplace, I would need an in-circuit emulator, a compiler/assembler and some way of downloading the program and booting the target board. For the benefit of the hard-line computer scientist, in-circuit emulators are expensive devices which plug into the microcontroller socket at one end and the workstation at the other. They do all the things done by a decent IDE, but can also ensure the hardware is behaving by monitoring bus control signals and the like. For microcontrollers, students are encouraged to plug in a logic analyzer instead: rather like an oscilloscope with an enormous number of channels and triggering, which can be locked to a particular data value and hence to the execution of a particular instruction. You don't get to see a stack trace or register contents, but you can examine exactly what is going on in terms of logic levels.
At the University of Leeds, all Electronic Engineering graduates are familiar with C. Those who specialize in computer subjects will also probably have picked up some parsing, X Window System applications programming, Java or C++ and Occam. The major requirement is to provide them with “right-first-time” prototyping tools, so that they can debug programs on workstations and get them “shipped” with as little ado as possible. The environment within which they are performing their project actually makes quite a good analogy to a commercial one: too little money and too big a time pressure to craft the most beautiful and elegant system imaginable. One thing the School of Electronic and Electrical Engineering doesn't have is the facility to make plated-through PCBs (polyclorobenzine circuit boards). It is too expensive to run because of severe environmental problems associated with the technology. It is possible for students to produce single or double-sided copper boards by photo lithography and etching (and they have), but plating through and the production of microcontroller boards is truly out of the question. Thus, we need to make boards for general application. We have them manufactured externally on large panels and cut up, so they can be used as the brain of an electrically more simple project built on a circuit board manufactured in-house.
The Creat specification required the following:
more powerful than a PIC with large data storage capacity
a development environment which is open to C users
very inexpensive to construct
flexible in application area
no special hardware for programming or servicing
target system simulation to aid debugging
Having produced a requirements spec, it was quite obvious I would not have time to write all of the necessary code and design the hardware from scratch. The normal scenario would be to obtain a loan (or course development grant), hire staff and have them reinvent the wheel by building yet-another-microcontroller-kit, then persuade the University to try and market it. Of course, this would have produced all the usual arguments against releasing the software source, and the cost would not be much less than $100,000 US by the time everything had been shaken down, even for a simple system. The openness of the project would be compromised; distribution, maintenance and servicing issues would arise.
Fortunately, as a long-time Linux user in an EE department, I had already come across Thomas Nau's PCB program. (Source code is available from ftp://ftp.uni-ulmde/pub/pcb/, also available as a Red Hat RPM or as a Debian package. See the README file for more details.)
PCB is a drawing package, with many useful debugging aids including net list import and export, but no auto route or schematic capture capability. It is ideal for students intricately hand-drafting a single-sided PCB—a skill not yet superseded by at least the majority of commercial packages. Maintenance of the package has been taken over by Harry Eaton, who looks after such features as Gerber output (the file format popular amongst PCB manufacturers). Figure 1 shows this program in action displaying part of the Creat CPU board. The really good thing about PCB is that it comes with a microcontroller circuit layout as a demonstration file. This is one of Thomas's projects, and I couldn't believe my luck, because it had all the attributes I needed for Creat. In fact, because Thomas's board was a full-blown stand-alone application, it was rather too complex for the tasks we needed, so I set about hacking it down to size.
The second stroke of luck came when I received an e-mail from Jerome Debard, a graduate of Toulouse. His degree was in Engineering, he wanted to gain some work experience and language skills by working in England, and was prepared to do so for free! He took the idea of reducing Thomas's board, and in a few weeks of frenzied activity, got it working, including writing a run-time library for it. (He also did the cooking at the Annual Communications Group Rooftop Barbecue, which is the first time that occasion has ever benefitted from having a French chef.)
Figure 2. The Creat CPU board
Aside from getting the circuit mis au point, the hardware was basically wrapped up. Figure 2 shows the bare board after commercial manufacture: its actual size is about 3.5 inches square with all the components added. To make the board work, you have to solder up the components labeled in plain text. If you want it to work without a regulated bench supply, you will need the components labeled in parentheses too. This gives you a microcontroller module with 2KB of EEPROM, 256KB of RAM, 28 digital and 8 analogue I/O lines. This is useful for some projects, but not really enough for C. Adding the components labeled in italics gives you up to 128KB of RAM, but leaves only five I/O lines. Fortunately, Motorola makes a rather useful PRU (port replacement unit) which can be hung on the address and data bus, transparently giving you these lines back. Figure 3 shows the memory map of the system with 128KB fitted. (Motorola, Inc. produces a comprehensive reference manual for this processor family, ref. no. MC68HC11RM/AD REV 3: Motorola Literature Distribution, P.O. Box 5405, Denver, Colorado 80217
Figure 3. System Memory Map
With essentially reliable hardware, the work now begins on a development system and first of all on the C compiler. Back to the Internet and to the aforementioned Donald Jeff Dionne, in whose public FTP space I found a binary distribution of exactly the compiler I needed. Based on the gcc port by Coactive (http://www.coactive.com/), it was ideal. A common source-code base could be built to run on the Linux boxes and then cross-compiled for the Creat board. The binary was in the old a.out format, and I e-mailed Jeff to find out whether it had been developed.
gcc-hc11 was the C compiler Jerome had looked at, then rushed out a run-time library including memory allocation and rudimentary string I/O routines. At the time, there were two European Community exchange students from Valencia in the department, so based on the availability of a working gcc, we started to cook up something which would be useful and free.
It is often efficient to divide a microcontroller-based project into two, testing the hardware and software independently before using them together. Of course, it is important for the two tasks to advise each other, but if the project is large, it is almost certain a hardware group will be working on the project concurrently with a software group. Creat seeks to make that process as easy as possible through a strict process of hardware abstraction. When somebody builds a piece of hardware which might be of general use, they make a package of it. A package consists of three things: a PCB layout in pcb format with the same form factor as the main CPU board, a set of subroutines (which might be written in C or assembler) with a specific C-language interface, and another set of C subroutines taking the same arguments which compile and run on the workstation.
The key idea is that any program which uses a particular piece of hardware, e.g., a dot-matrix LCD display, can be written using the Creat LCD device interface. This provides two main calls: an initialisation call invoked before the device can be used and another to write a character on the LCD. Creat's make system can be used to build the application for the Linux box by issuing the commands:
make depend; make wkstn
After testing, code can be compiled for the 6811 as well using:
make 6811; make boot
Daniel Roques Escolar and Alberto Ramos Fernandez worked long and hard on the coding for two packages: one to drive a dot-matrix LCD and the other to drive a row/column-scanned keyboard. We were inspired by a previous article (“Using Tcl and Tk from Your C Programs” by Matt Welsh, Linux Journal, February 1995) which showed how Tcl/TK scripts can be executed by forking off a new process and then executing a copy of wish. Connecting wish through a pipe to the parent process means commands can be sent to it and information received back. This makes it very easy to present a simulated LCD as a wish X window, and much can be achieved without having to write any X code at all. Even though Xlib-based code would execute much quicker than a wish script, it shouldn't be a problem since it is probably a case of a 586 of some sort versus an 8-bit microcontroller.
Thanks to Danny and Alberto, at least two additional modules are now available which plug into the Creat bus: the LCD and keyboard modules. These packages provide the hardware abstraction interface and use a forked wish script to emulate the LCD and the keyboard on-screen.
There is one problem area in which microcontrollers tend to outperform even Linux—interrupt handling. Microcontrollers come loaded with I/O facility, so a huge number of interrupt sources exist. There are even timers which don't have to connect with the asynchronous outside world, but just sit there generating interrupts. These and other troublemakers present a serious problem for simulation on a Linux platform. The programmer writing the hardware abstraction code might want to generate a handful of different interrupts, but the only ones present for the purpose of simulation are SIGUSR1 and SIGUSR2. A single timer can produce that many. We therefore devised a method for the simulation of multiple interrupt sources.
When there is a conflict of interests in hardware simulation, it is important to place the strain on the Linux side of things rather than on the microcontroller. The interrupt handling method is basically transparent as far as the 68HC811 is concerned. It amounts to the insertion of a vector in an interrupt table in response to a “register interrupt” subroutine call. At the Linux end, things are more complicated by the fact that all processes which generate interrupts are told to generate the same interrupt. In addition, each one shares a pipe with the parent process, down which they write a byte before raising SIGUSR1. When the handler gets called, it uses select against all pipes to establish which process needs servicing, then looks in its own table of service routines and calls the appropriate one. Listing 1 shows the code which registers an interrupt process.
With the registration process available, it is possible to create packages that cause interrupts to take place. The simplest example is the timer device, which generates interrupts at a regular interval. The routine to create a timer device is init_timer and in the case of the microcontroller, it would only have to set the appropriate timer interrupt vector and start the hardware timer in free-running mode. When compiled on the workstation, the function registers an interrupt source, then forks off a function which spends most of its time sleeping, awakening now and then to raise a signal. The code appears in Listing 2.
Whether the interrupt source is a timer or some other simulated I/O device, the same interrupt service routine, sigusr1_handler (Listing 4), is called each time a signal is raised. The signal handler has access to the list of registered processes, so it can call scanlist (Listing 3) to catch the culprit and execute an associated interrupt service routine. The whole thing acts like a kind of interrupt multiplexor, so that with the help of a list of pipes, the appropriate source can be associated with the appropriate service routine, even though all possible sources raise the same signal.
In actuality, all I have done is manage a project. The project had some excellent resources and my input was to point them in what I feel is an educationally useful direction. I hope “real” applications (whatever they might be) will find this package useful too. The whole bundle is available in a package on my web site (http://www.ee.leeds.ac.uk/homes/NJB/Software/linux-stuff.html#creat) and you can browse the manual written by Danny and Alberto on-line. Thomas's PCB, as modified by Jerome and others, is also there, along with the port replacement unit PCB and all other software mentioned above. The manual contains over 130 pages.
I hope people will be encouraged to contribute packages to this project. The modules available so far are not entirely complete. I need to tidy up the interrupt registry to make it truly modular and make the vector insertion work on the microcontroller. Issues with the LCD module need resolving, such as the display size being fixed in the Tcl/Tk script; and a new version of gcc6811 needs building, using an up-to-date gcc as the base and glibc. However, on the positive side, among the things which have delayed my fixing these problems is that the whole system does actually seem to work together rather well. Figure 4 shows the simulated keyboard and LCD, with a simple counter ticking away in the background.