For digging out hardware bugs, monitor programs fill the bill
Often during system development, times arise when you'd really like to dive into
hardware and quickly try something with an I/O device. One option is to plug in that
trusty emulator or logic analyzer. Another technique I frequently use-albeit a decidedly
less glitzy approach-is to use something called a monitor program. It's a low-cost design
tool you can either buy or build and have available in your toolkit for all types of
hardware and processor problems. Although monitors are valuable aids, just like any other
tool, they have limitations. Regardless of how powerful, a monitor program can't replace a
good emulator or logic analyzer. But for those with limited funds, a monitor might just be
your tool for squashing that last hidden hardware bug.
Although the exact origin of the name "monitor" is lost in some dusty recess
of computer history, ever since I started working with microprocessors I've used or
written monitor programs. Despite variations in form and capability, they have several
aspects in common in that they, at the very least, can display and modify memory or I/O.
Monitors communicate with the programmer over a dumb terminal, an easy connection to make
because nearly all embedded designs have a serial port. The transmission rate isn't
important; early monitor programs I used communicated with a Model 33 Teletype at 110
baud-perfectly acceptable for all tasks except long memory dumps.
Matching the austerity of the operator interface, the monitor program's commands are
also simple. In fact, you might already be familiar with them because the DOS DEBUG
program is a well-known monitor. Just like DOS itself, DEBUG came from the CP/M world and
thus reflects its hobbyist roots.
In general, the program's commands fall into three categories: memory, I/O and other.
Basic memory commands allow you to display an area of memory, fill it with a value and
edit any single location. However, many sophisticated monitors add commands such as
searching through memory, copying memory or performing memory tests. I personally like
simple solutions and uncomplicated programs, so I consider these extra commands as frills
and not necessary to the basic monitor's operation.
Similar in function, I/O commands allow you either to set an I/O port to a value or to
read its contents. If you ever choose to write a monitor program you might add
capabilities such as read and write block I/O commands or continuously read the I/O port
until the program reads a certain value. However, as you've already guessed, these
additions violate my simplicity rule.
The remaining commands I lump under the heading "other." These operators
might include a help command to list the structure of all commands or any other operators
that make life easier. Such specialized functions could send a long sequence of commands
to a UART or read the system real-time clock. Remember, the monitor is a tool, and just as
other craftsmen occasionally modify tools for particular purposes, this one's here to
customize to your way of doing things.
Regardless of what type of function any command is performing, they all have the same
basic structure and start with a letter. The chosen letter should remind you of the
function. For example, when creating a monitor I use the following commands: D for
displaying memory, F for filling memory and S for substituting or changing memory. I/O
commands can be equally simple. The command I inputs or reads data from a port, while O
outputs or writes to a port. Finally, what could be more obvious than to use ? or H for
invoking online help? Following the letter come one or more numbers that indicate the
memory or I/O locations to use and perhaps the information to go into those locations. One
thing I'm very particular about is that the monitors assume all numbers are in hex without
any special prefixes or suffixes to specify the number base-in other words, no decimal,
octal, binary or whatever else.
It takes more than a simple command structure for an application to be useful. You also
need to know a tool's limitations in order to avoid trying it on applications for which it
isn't suited. For instance, emulators are such great tools that everyone should have one.
However, most development organizations can't afford to buy a new emulator each time a
processor hits the market. Further, I've found that sometimes you just can't get an
emulator into the target design, especially in a production instrument. Consider one of my
customers who spent a fortune on their instrument's case design. It's pretty to look at,
but nobody thought ahead about how to get an emulator pod into the instrument. To install
a pod in this system takes me more than an hour to disassemble it plus another hour to
button it back up. By contrast, I can install a monitor program in under 5 sec through a
memory-card slot. As long as I don't need an emulator's unique features, my monitor
program provides all the capability I need to debug hardware problems.
Notice that I said hardware problems. A monitor program, as described above, doesn't
allow you to debug real software problems. Sure, it's possible to add commands to start a
program operating from a certain location, set breakpoints, dump registers, display stack
frames or whatever else. However, running these functions on the same processor that's
executing the target code imposes a significantly new computing load, potentially
invalidating the very data you're collecting. Also, adding this type of functionality runs
contrary to the spirit of what a monitor is used for.
In addition, a monitor requires that a certain amount of hardware be up and running in
the application before it's of any use. If the embedded processor's not running, get out
your emulator, logic analyzer or scope because a monitor is useless. However, if you face
a task such as trying to set up a flat-panel VGA-emulation chip with VGA extension
registers, a monitor program is ideal.
Recently, I encountered a great example of a monitor's usefulness. I incorporated a
PCMCIA Type 1 memory slot for loading new programs into a medical instrument's flash
memory. This feature seemed to work for more than six months. Then, just before I went to
deliver the instrument, I found that the memory-card driver would work with some cards but
not with others. I quickly loaded my monitor program onto a PCMCIA memory card (for some
reason it worked on all the memory cards) and started running it on the instrument. With
the program, I interrogated the memory card and tried exercising the I/O ports relating to
it. The program easily allowed me to determine the problem. I wasn't correctly setting the
configuration-register selection line and that, unbeknownst to me, some cards had
configuration memory and some didn't.
An emulator could've found this problem, but because I didn't own one for the processor
in this instrument, the monitor was the fastest way to solve the problem.
With this preamble out of the way, next time I'll get into how to create your own
monitor and the reasons for doing so. PE&IN