feature article
Subscribe Now

An Object Lesson

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:

B# website

4 thoughts on “An Object Lesson”

  1. Simply put, there’s no need for such a thing as B#. Bjarne Stroustrup’s own words: C++ is a systems programming language that is designed such that there’s no room left between C++ and pure assembly language. Today’s tool chains achieve this goal and unleash both the expressive power of C++ and the efficiency of C (in some cases even better than C). In this regard, B# looks like a subset of C++, something that you could have had for a decade.

    A sidenote: C++ compiles to native code and runs on bare metal rather than a VM.

  2. Another note:
    C++ does not require 128K of RAM.
    scmRTOS is small micros real-time OS written on C++ and it fits into chips with 8K flash and 1K RAM.

  3. I agree with DanielaE and ReAl: C++ is a systems programming language by retaining the heritage of C, but its design rationale was to support and implement object-oriented principles. Don’t get me wrong, I still consider C++ as one of the most powerful and flexible OO language available, but it comes with a high price of complexity (great for medium and large applications, but harder to justify for small footprint embedded systems).

    Sure there are small RTOS, kernels, embedded apps written in C++ out there, but when you look at the source code and the overall design, most of them are written in a procedural way (the C core of C++) or in a modular way reinforcing only the encapsulation principle with the class. These implementations rarely profit from the powerful and flexible object features which Stroustrup provide in his great language. In other words, it is true that C++ can be more efficient that C in terms of space and speed, but B# was seeking simplicity to help embedded systems developers to focus on those object features that allow better decoupling and reuse (interface and abstract classes) and better abstractions by hiding the idiosyncrasies of microcontroller architecture with a lean virtual machine (ioreg, interrupt support). B# is not a subset of C++, its influences are more Edison, Oberon-2, and C#.

    To quote the excellent article of Bryon:
    “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.”

    Thanks for your interest in the B# Project!

    Michel de Champlain
    Chief Architect of B#

    P.S.: To honestly answer Bryon on “Why isn’t it more widespread?”: Recently, we have been reluctant to make more releases without proper documentation to help embedded developers to port the B# VM on different targets. Previous releases was supporting only few target boards (on Renesas and Arm). Unfortunately, we are a small team and we cannot port the B# VM to every single microcontrollers out there, so we plan to make available a good porting roadmap and a book that should be a good leverage for those who want to experiment and to do the port themselves.

Leave a Reply

featured blogs
Oct 9, 2024
Have you ever noticed that dogs tend to circle around a few times before they eventually take a weight off their minds?...

featured chalk talk

SiC-Based High-Density Industrial Charger Solutions
Sponsored by Mouser Electronics and onsemi
In this episode of Chalk Talk, Amelia Dalton and Prasad Paruchuri from onsemi explore the benefits of silicon carbide based high density industrial charging solutions. They investigate the topologies of Totem Pole PFC and Half Bridge LLC circuits, the challenges that bidirectional CLLC resonant DC-DC converters are solving today, and how you can take advantage of onsemi’s silicon carbide charging solutions for your next design.
May 21, 2024
31,185 views