Creat: An Embedded Systems Project
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.