Doug is the owner of Access Microsystems, a software-development house specializing in C/C++ software development. He is also the author of the BTFILER and BTVIEWER Btrieve file utilities. Doug can be contacted at 404 Midstreams Road, Brick, NJ 08724, or on CompuServe at 74040,607.
When people comment about the number of computers I have at home (two working and two not-quite-working PCs), I remind them that they probably have at least four--and likely more--computers around their house. What people sometimes forget (or don't realize at all) is that computers are not limited to the now-familiar PC-style boxes. Microwaves, stereos, VCRs, and even the family station wagon are chock full of computers we refer to as "embedded systems." And where there are computers, there must be programmers.
The two books I'll examine here are explicitly written to help ease the learning curve for embedded-systems programmers. Interestingly, both books also shed light on the recent trend of using C rather than assembly language in embedded-systems programming.
Programming Microcontrollers in C, by Ted Van Sickle, is designed to help the experienced embedded-systems programmer (who is likely experienced in assembly languages) program embedded systems in C. His C tutorial is thorough, beginning with the very basic elements of the language (fundamental data types, control structures, and so on), progressing through pointer usage, and going all the way to structures, unions, pointers, and functions. Special emphasis is given to areas of C that are often misunderstood, even by seasoned C programmers. For example, detailed instructions for decomposing complex pointer declarations are provided. I wish I'd had access to such a tutorial when I was learning C many years ago.
Several functional programs of reasonable length are covered, selected for their ability to teach various elements of C, and not just in handling embedded-system-type problems. The introduction to C, amounting to just over one quarter of the book, would alone be worth the price of the book. However, there is a great deal more.
Van Sickle next takes a chapter to describe some of the basic functions of a microcontroller, placing emphasis on some of the features that, while sometimes used in general programming, take on much greater significance in embedded systems. For example, timers and analog-to-digital converters are discussed, as well as some special aspects of memory access in microcontrollers.
The final sections of Programming Microcontrollers in C are devoted to details of small 8-bit, large 8-bit, and larger Motorola microcontrollers, giving details of likely uses of each class of microcontrollers as well as information on the kinds of restrictions for each in common C compilers. Appendices offer detailed specifications on many of the microcontrollers listed, as well as header files that allow for compilation of some of the programs from the book. A companion diskette is available at an additional cost of $30.00.
My reservations about Programming Microcontrollers in C are minor. The discussion of printf() and related functions could have been improved by a discussion of the overhead they carry. This is, of course, critical in embedded-systems applications. Another minor lapse is the equating of a FILE* with a file handle. A FILE* may have a file handle, but a FILE * is not a file handle. These are minor nits and can easily be forgiven because of the overall quality of the text. A more serious limitation, acknowledged by the author, is the fact that coverage is limited to Motorola microcontrollers, with no discussion of other vendors' products.
John Forrest Brown's Embedded Systems Programming in C and Assembler takes a slightly different approach to explaining the integration of C into the embedded-systems-programming world. Some knowledge of both C and embedded-systems programming is presumed, and knowledge of the two major microprocessor architectures (Intel and Motorola) does not hurt, either.
Brown begins with a useful introduction defining embedded-systems programming. Although he recognizes that much of what embedded systems used to perform can now be reasonably done using a dedicated PC, he explains the situations in which the flexibility of the PC might not be the asset it normally is. This is a good discussion of the virtues and perils of developing embedded systems in today's ever-changing corporate and technological climate.
After discussing essentially the same issues as Van Sickle with regards to the major parts of embedded-systems programming (interacting with timers, interrupt service routines, analog-to-digital converters, and so on), Brown moves on to several chapters of nuts-and-bolts programming, using examples from both Intel and Motorola wherever possible. Handling interrupts, an essential part of embedded-systems programming, is covered in great detail, showing where C or assembler might be more appropriate as well as the many differences between Intel and Motorola processors that cannot be easily hidden from the embedded-systems programmer. In all cases, Brown discusses possible timing problems, which can be very difficult to diagnose, along with possible solutions. As is fitting in a book devoted to C and assembler programming, mixed-language issues are discussed, shedding light on another area where microprocessor differences cannot be hidden.
Brown moves well beyond the microwave and other appliances in discussions of issues that surround embedded-systems programming. Multiprocessing and interprocess synchronization are discussed in some detail. Some previously discussed topics are revisited in the context of multitasking. The examples in the appendices have a marked military bent (missile-to-aircraft interface, pilot control panel, and so on) and include, not surprisingly, Department of Defense guidelines for defense-system software development (DOD-STD-2167A). Beyond these rigid guidelines, Brown presents ideas for more careful thought about the design process, as well as more than the usual "documentation is a good thing" talk. Embedded Systems Programming in C and Assembler gives you a start at developing a methodology about the embedded-systems software design and development process.
As mentioned, most examples are related to the aircraft industry. The examples and explanations of why they do what they do take up over half the book. The examples come with explanations that further examine the problems and the workarounds found in the main body of the text. The code for the examples is included on a diskette that comes with the book.
Brown misses only a couple of opportunities to make the best explanation possible of migrating toward C for embedded-systems programming. For example, in a discussion of debugging code, he misses an opportunity to explain one of the few good uses of the C preprocessor that remains, even in the C++ world: employing #ifdefs to use a single set of source-code modules that can simply be compiled with different sets of #defines to enable or disable debugging. As in Van Sickle's book, C++ is mentioned, but not covered. Many of the tasks of the embedded-systems programmer can be properly handled using C++ classes. Maybe the second edition of each book will cover C++.
I recommend both books if Motorola embedded-systems work is in your future. Van Sickle's book will easily pay for itself, and Brown's can be useful if you think there is any chance that code will be moved to an Intel platform.
Ted Van Sickle
HighText Publications, 1994
394 pp., $29.95
ISBN 1-878707-14-0
John Forrest Brown
Van Nostrand Reinhold, 1994
304 pp., $49.50
ISBN 0-442-01817-7
Copyright © 1994, Dr. Dobb's Journal