Programming Pointers
Better even at the lowest levels
Dan Saks
11/1/2008 12:00 AM EDT
For the past several years, I've been presenting a talk at the Embedded Systems Conferences called "Writing ISRs in C++." The talk is aimed at programmers who've already written interrupt-handling code in C and would like to see how to use the features of C++ to make such code even better. More recently, I started presenting a talk at the Software Development Conferences entitled "C++ on Bare Metal", which presents ways to use C++ features such as classes, inheritance, and templates to model memory-mapped devices as tidy, yet efficient, abstractions.
This fall, both conferences took place at the Hynes Convention Center in Boston during the same week. I was one of two or three lecturers who spoke at both conferences, and I presented both talks. This time, I was struck by the number of attendees at each talk who were not so much interested in how to write such low-level code in C++, but rather why you'd want to write it in C++ rather than in C.
Ten or twelve years ago, C++ was still a novelty in the embedded world. Most of the developers at my conference lectures were as interested in why as in how, so I typically devoted time to both. Over the years, more and more programmers came to my talks already sold on why and were just interested in how. For the past few years, I've focused on how because that's what I thought my audiences wanted to hear. That's why this recent uptick in concern about why caught my attention.
So the question is "Why would you prefer to write low-level code that directly manipulates hardware and handles interrupts in C++ rather than in C?" If C and C++ were different languages, as different as say C++ and Ada, or even C++ and Java, this might be harder to answer. But C++ is essentially C with a bunch more stuff. I believe the only substantive features in C that aren't also in C++ are some built-in support for numerical computing. Device drivers and interrupt handlers don't do much number crunching.
C++ provides all the facilities of C for controlling hardware efficiently. At times, controlling hardware can be tricky and error prone. C++ has features that C lacks, principally classes and templates, that let you bundle device controls into components that are, as Scott Meyers would say, "easy to use correctly and hard to use incorrectly."1
For example, many processors have an interrupt controller with an interrupt-pending register. That register has a bit for each interrupt-generating device that indicates whether an interrupt is pending for that device. An interrupt handler for a given device should clear that device's interrupt-pending bit after handling the interrupt.
In C, you might represent the interrupt-controller register as a struct, such as:
struct interrupt_controller
{
device_register INTMOD;
device_register INTPND;
device_register INTMSK;
};
and access the device via a pointer:
interrupt_controller *const ic
= (interrupt_controller *)0x3FF4000;
With most control registers, you clear a bit using a masking operation, such as:
ic->INTPND &= ~button;
Here, button is presumably a one-bit mask that corresponds to the interrupt-pending bit for a push button. However, interrupt-pending bits should be cleared atomically, and few, if any, processors implement the &= operation so that it's atomic. Thus, many interrupt controllers are wired so that you clear an interrupt-pending bit by assigning rather than and-ing to the register, as in:
ic->INTPND = button;





shaskil
12/4/2008 2:10 AM EST
no comments!!!!!!
Sign in to Reply
Frank38
12/10/2008 8:36 AM EST
What a nice article ! I'm going to show it to some of my workmates because every time I talk about using C++ I get a "no way !" as an answer...
Sign in to Reply
D J Liu
12/18/2008 2:10 AM EST
When properly used, inline and template may even produce faster C++ code than C code.
Sign in to Reply
kdavidson
12/18/2008 1:10 PM EST
I've been using C++ for low-level motor control for over 10 years now and cringe when I'm forced back into C when working on a processor that doesn't support C++. Today's compilers produce excellent code with minimal overhead.
Sign in to Reply
jscott27
9/3/2009 8:48 AM EDT
The examples show poor use of C for modularity, encapsulation and interface design more than they show advantages of C++ over C. For ic_clear there is no reason to have a pointer to the interrupt controller in the prototype unless you have multiple interrupt controllers, which your C++ example does not deal with. As far as forgetting the function exists and attempting to directly access the IC register, if the definition of the register was static to the file responsible for managing the IC, then this would not be an issue in C, either.
I think there are advantages in going to C++ over C, but I have not seen those articulated very well. It is possible to create better interfaces and C++ has better type checking, but I have yet to see anyone put together a comprehensive argument showing the advantages of well written C++ vs well written C are worth the learning cost and additional ROM / execution time required when moving to C++.
Articles like this from experts make me wonder if C++ really is worth it.
Sign in to Reply
GordonScott
2/28/2011 10:36 AM EST
: ic-%gt;clear(button);
:
: Can you write a function similar to that in C?
I can write _exactly_ that in C.
Whyever should I not?
It's just a pointer to a handler for the device identified by 'ic' and you'll find precisely that arrangement in countless device drivers.
Sign in to Reply
GordonScott
2/28/2011 10:38 AM EST
Urg .. what did the formatter do to that?
Sign in to Reply