Objects are bad, some say.
Material possessions, things, belongings – they detract from the true essence of being, some say.
They are to be shed, released; life is to be lived minimally, ascetically, some say.
And yet, objects can make life more livable; they can be used for good. Perhaps there’s a balance between the desire for objects and the need to occupy a small footprint and live sparingly.
This has been the embedded software conundrum for years, with the preponderance of behavior leaning towards the minimalist side: no objects. C and assembly are just fine, thank you. We don’t need to be burdened with the overhead and sprawl of an object-oriented language. C++ and Java might work fine where resources are plentiful, but when the going gets serious, it’s back to a frugal subsistence existence.
At ESC (Design West) this year, I saw a presentation on a different approach to the balance between objects and simplicity: it’s an object-oriented language called B# (technically, it’s B?; smaller than the C# language; musically, B?=C, coincident with similarities between the languages; “be sharp”; get it?) specifically designed to be efficient in embedded applications. It appears to be the brainchild and personal mission of one Michel de Champlain, CTO of DeepObjectKnowledge in Montreal, a company that does training and is the primary vector for B#. He was the presenter at ESC.
DeepObjectKnowledge seems to be a small operation, and I’d never heard of B# before (not that that necessarily means anything about anything except my knowledge), so I have this sense that this is very much an evangelical drive –possibly even quixotic, although it wasn’t immediately obvious to me why programmers wouldn’t pick this up and run with it.
We’ll walk through some of the characteristics of B# here (sticking with the # symbol for keyboard simplicity). Perhaps you’ll be able to highlight whether this is just what the doctor ordered or somehow flawed.
The main issues that B# attempts to address are the size and lack of embedded features in C, C++, and Java. The virtual machines (VMs) used in C++ and Java implementations can be a couple of megabytes in size; B# in its full glory requires less than 24KB of Flash memory and 2KB of working RAM – and this can be reduced if some features are dropped. The B# VM itself is written in C.
With respect to embedded features, neither the C languages nor Java have explicit standard language support for isolating I/O registers, accessing interrupt vectors, and enabling or disabling interrupts. The focus of B# is specifically drivers and interrupt handlers, so such low-level access is fundamental. The syntax is intended to allow for portable interrupt handling and device register access.
In fact, B# is supposed to be transportable across systems with minimal porting work. Code is position-independent, I/O register access is architecture-independent, and it’s big-endian on every system. Its target independence means that you can emulate an embedded program on your host system in advance of your target hardware being available; the VM essentially acts like a virtual platform.
Mr. de Champlain summarizes the distinctions between the languages with a table that shows that, of the B#, C, C++, Java, and C# languages (having minimum runtime RAM footprints of 2K, 2K, 128K, 512K, and 512K, respectively), only B# natively supports classes, object root classes, abstract classes, interfaces, interrupt handlers, device I/O registers, multithreading, and, to a partial extent, garbage collection (more on that in a moment).
It inherits the basic procedural aspects of C and a stripped-down version of the object-oriented nomenclature of C#, eliminating features not needed for embedded. It supports classes, interfaces, and event handlers. No pointer (or address) manipulation is allowed, and the language is inherently type-safe.
Unlike Java, no automatic garbage collection is provided. Garbage collection usually commands its own background thread, bulking up the size of the program and adding some uncertainty on runtimes since you never quite know when the garbage collection will kick in. Instead, there is a memory defragmenter that can be explicitly called to clean up memory in a more efficient, deterministic fashion.
B# has five primitive value types:
- bool
- char
- int
- ioreg
- float
It has four “reference” types:
- [] (for arrays)
- handler (for callbacks and interrupts)
- string
- object
The operators are identical to C, except that you lose the *, &, and à symbols due to the lack of support for pointer manipulation. He’s added “new” and “delete”, for creating and destroying objects, and the “is” operator for checking type. Sequential expressions look like C (return, if, while, break, etc.).
Object members (or properties) tend to be cumbersome in many languages, with “get” and “set” (or “let”) functions used to implement external access to a member that’s often represented by a private internal variable (with the functions wrapping access to that variable for any number of reasons, at the very least error checking). These are eliminated in B#. Internal member variables are written with initial lower case; external references use the same variable name, but with initial upper case. The position of the variable – left or right side of the expression – determines whether it’s a read or a write; the member declaration determines whether it is allowed to be read and/or written using {get;} and {set;} attributes.
Interrupt handlers are implemented as public static functions inside a class. They are passed to a table on class initialization. Threads are also basically handler types. You can define a static function and then pass it to a new thread using Thread.New(<function name>) during class initialization.
The VM effectively acts as an OS, managing system resources.
- For the processor, it handles processor registers, interrupts, interrupt vectors, schedulers, and threads. You can modify or replace the scheduler if you want.
- For memory, it manages the code, data, and runtime stack.
- For devices, it controls hardware devices and I/O registers as well as managing the transfer between memory and devices.
There are three types of device register:
- command (write-only, declared as {set;}
- status (read-only, declared as {get;}
- data (read/write, declared as {get; set;}
The “iobase” statement sets the base address for I/O registers; you then declare the offset for a particular register instead of its actual address, which eliminates the need to manipulate the base address explicitly to get to a register (part of the no-pointer-arithmetic thing).
A compiler and VM are available for B#; there is also a community supporting it (although you have to get to it by emailing DeepObjectKnowledge; I didn’t see an open community page, so I have no idea how much activity or support there is).
I have to say, from where I sit, this seems to have some pretty attractive features. Then again, while I am a programmer of sorts (casual), I’m not a serious embedded programmer, so there may be issues that I’m not aware of (either because I don’t get it or because they weren’t mentioned in the presentation or other supporting documentation).
One thing that occurred to me is that, given the prevalence of legacy code in other languages, it’s not immediately obvious how new B# code would coexist with older legacy C (or other language) code. Legacy seems to be the primary barrier to new and different things. I checked in with Dr. de Champlain, and he confirmed that you can invoke C programs from B#, either for including legacy code or for those times when you need to bypass the B# VM for performance reasons.
Having C invoke B# routines, however, would require “metaprogramming” overhead that he judged too high, and so that is not supported. There is also no support for invoking other languages like Java.
Any such concerns aside, this seems to strike a pretty sweet balance between the desire for objects to simplify our lives and the need for living parsimoniously. No need to go all the way to a cave in a distant cliff to live out your days; a simple lean-to on the outskirts of town, within reach of other people and resources, can be tolerated.
Maybe not all objects are bad after all.
More info:


Leave a Reply
You must be logged in to post a comment.