C for embedded controllers

Ed Lansinger elansi01 at mpg.gmpt.gmeds.com
Mon Dec 11 07:22:50 GMT 1995


My apologies for a) reviving a thread that may have already died
a natural death and b) not responding to other people earlier
pursuant to this thread.  I got really busy all of a sudden.

With respect to the question of using C++ for embedded control and
my upcoming article in the February issue of the C/C++ User's
Journal -

Bruce Bowling wrote:

>Some of the things which blows my mind from using C++ are the following:
>
>1) Virtual functions, in which the virtual function tables get set up
>at runtime (i.e. the function pointers inside of an object get
>set when the object is created) or when an object gets created
>using "new".

It turns out to be no big deal.  When an instance of a class with
virtual functions is created, storage for a pointer to a table
of function addresses, the "vtbl" pointer, is allocated (these addresses
are the addresses of the virtual functions).  This pointer is
inserted as an invisible addition to the normal data members.

When a call is made to a virtual function, the address for the "real"
function is looked up out of this table, then the function is called.
It is therefore only slightly slower than a straight function call.
(The meaning behind calling a C++ virtual member function is different
than behind calling a normal C function, so it's not really appropriate
to compare call times.  If you tried to express the same meaning in C or
assembler or whatever you would still have to go through the same
basic procedure and it would take just as long.)

How does this vtbl pointer get initialized?  Note that all objects of
a given class will use the same vtbl.  They don't have individual vtbls,
they have individual pointers to a vtbl.  The vtbls are created at
compile time.  The only thing that happens at run time is the initialization
of the vtbl pointer inside the new object.  This happens during the "new"
process.  Since the class of the object to be "newed" is explicit, the
correct vtbl is also known.

I recommend reading Ellis and Stroustrup, "The Annotated C++ Reference
Manual", sections 10.7c and 10.8c, for additional information.  I
also recommend playing with cfront.

>Virtual functions appear to be an additional layer
>to debug through, since addresses are determined at runtime and
>can change depending on the inheritance of an object.

To clarify, the addresses of the functions to call (comprising the vtbl)
are determined at compile time.  The determination of which vtbl to use
for a new object happens at runtime during the call to "new" (this is
a trivial determination based solely on the class of the object as specified
in the call to "new").  The vtbl pointer, once initialized, does not change
(at least in any normal code).  An object's inheritance cannot change at
runtime, it's just that you can operate on an object knowing that it is
descended from a certain class without needing to know its exact class.

As to the "additional layer", it's largely invisible during debugging.
If I step a machine instruction at a time across a call to a virtual function,
watching the current high-level source line, the debugger makes a brief detour
to the last line in the file (I assume this indicates a point in the code
for which the compiler indicated no valid source line), then goes to the
first line of the virtual function.  It's effortless.

>2) How does one handle "new" in an embedded system?  Making a "malloc"
>function is easy - making a new, which does things like set up
>virtual function pointers using the constructor, appears harder.
>Does the compiler do all the work?  (I am assuming there is
>no operating system).

I deal with this in the article.  I used cfront (translates C++ to C),
then the Introl C compiler.  cfront requires you to write new(), delete(),
vec_new(), and vec_delete() (the last two are for creating and destroying
arrays of objects).  new() only needs to do what malloc() would do.  cfront
writes C code to take care of anything else.  In the article I don't
give new() and delete() as they are typically very specific to the
system but I do give vec_new() and vec_delete() which need not be.

>3) The strong typecasting of C++, while nice for the new or
>sloppy programmer, can be a menance to someone who wants
>to pass an argument a certain way because they know what
>they are doing and are incrementally smarter than the compiler
>at that moment.

If I may be so bold, I see this belief as a relic from K & R.  I feel
that the weak typing of (non-ANSI) C is nice for the ((new || old) &&
(sloppy || lazy)) programmer who wants to pass an argument when it's too
bothersome to figure out how to properly typecast it. I have never been
prevented by C++ from doing anything I wanted to do.  Explicitness makes
for fewer misunderstandings over time.

What is cool along these lines (IMHO) is the extended ability to make new
types.  I should have gone into this in the article but I didn't.  Creating,
say, a reduced-precision floating point type along with new arithmetic 
operators so you can still write "w = (x * y) + z;" instead of
"w = add( mult (x, y), z);" has important implications for embedded code.
If you don't have strong typing and the ability to define and carefully
control your own type conversions, you or the nimwit who tries to "improve"
your code six months from now (these two sets are not necessarily disjoint)
could hang themselves right quickly.

Matt Sale wrote:

>Then why do you claim in part 1 of your Circuit Cellar INK series
>that "The code is in assembly." 

Sorry, I wasn't clear.  The CCI articles were written about the earliest
viable version of that system as it existed in May '93.  The CUJ article is
about work that I did on a later version as it existed in Spring '94.  The
first was programmed in assembler, the second in C++.

>By the way, the Circuit Cellar series was good, but lacked actual
>code or schematics.  Most Circuit Cellar articles contain enough
>info to actually build something.  Are you willing to make more
>information available?

Thanks for the compliment.  All source code is available, as is the case
with all CCI articles.  Well, let me qualify that.  I have source code for
a barely running version as of May '92 which I will happily make available.
The code for the May '93 version is only available on a hard drive that
crashed right before the articles were published.  All backup floppies
(and I made *extensive* backups) had been lost during the year I was not
involved with the project.  As yet I am not wealthy enough to send the
hard drive off to a data recovery service.

I made a judgement call on the schematics.  Most of the circuitry involved
was rather trivial, and I figured rather than waste space on yet another
example of using an LM324 as a buffer, I'd concentrate on the real beef,
i.e. the special circuits I needed that weren't as obvious.  You should
find schematics for these more important circuits in the articles.  If
there is anything more you'd like to know I'd be happy to provide further
information.

Sandy Ganz wrote:

>Will their be lots of examples in the C/C++ users journal. I hate to think
>that I'm going to have to wait that long to see some of the examples. What
>can I get now...Do you have schematics, or is that propritary?

Yes, there are several examples, including 7 short code listings.  The
article is not about EFI systems, though.  It has one main theme - how
to get C++ code running on an embedded system for which no C++
compiler exists.  The major subtheme is that C++ worked and was useful
for this application.  There is no information on the hardware at all (not
the focus of that magazine anyways), although it's essentially the same
hardware I described in the CCI articles.  The code examples used in
the article are not fully representative of the body of code I
created.  For instance, I don't show the LCDDisplay class and how
it works with the Optrex LCD display to create different display
contexts for different objects such that each thinks they have
their own entire display.  I also don't go into the Process class
that I created for round-robing multitasking, nor the overall
structure, nor ....  Perhaps if you were more specific about what
you're interested in I could be more helpful.


Ed Lansinger
elansi01 at mpg.gmpt.gmeds.com:
GM Powertrain Premium V (Northstar/Aurora) Software & Calibraton Group
lansie at rpi.edu:
Project Leader, Rensselaer Formula Lightning Team





More information about the Diy_efi mailing list