B# - A programming language for small footprint embedded systems applications: Part 1
B# (pronounced “be sharp”) is a tiny, object-oriented, and multi-threaded programming language that is specially dedicated for small footprint embedded systems.
Because B# has its roots in the C family of languages, it will be immediately familiar to C, C++, Java, and C# programmers. In addition to supporting modern object-oriented features such as namespaces, abstract and concrete classes, interfaces, and delegates, the B# language caters to the embedded systems programmer with efficient boxing/unboxing conversions, multi-threading statements, field properties, device addressing registers, interrupt handlers, and deterministic memory defragmenter.
Each of these features is directly supported by the constructs of B# and its underlying virtual machine in order to create, use, and reuse more portable and decoupled software components across different embedded systems applications. This series of articles highlights and illustrates these key B# concepts with short programming excerpts, but leaves the details of other more common features to a more complete overview.
Motivation and Unique Key Features
Despite the evolution of object-orientation and the development of advanced language features such as interfaces, delegates, and properties, the linga franca for embedded systems programmers continues to be the C programming language. Developed in the early 1970’s, the C language has maintained its foothold over the years for four key reasons: availability, portability, flexibility, and accessibility.
It has also served, at least syntactically, as the foundation for C++, Java, and C#, among many other experimental languages. C is no doubt venerable, but it is also old [1, 2]. And, unfortunately , C++ and Embedded C++ are often not suitable for small-scale architectures with tight memory (< 64KBytes) constraints.
Our programming language called B# (pronounced “be sharp”) introduces embedded systems developers to a fully-fledged, object-oriented programming language that is designed explicitly for small footprint embedded systems [3, 4].
In addition to the traditional object-oriented features of encapsulation, inheritance, and polymorphism, the B# language includes efficient boxing/ unboxing conversions, field properties, device addressing registers, interrupt handlers, deterministic memory defragmenter, and multi-threading capabilities.
In order to support these features efficiently, high-level B# code is mapped directly to a compact instruction set which is interpreted by an optimized embedded virtual machine called B#EVM. The intermediary of a stack-based virtual machine allows the embedded systems developer to write interrupt handlers and to access device registers in a uniform manner, independent of the underlying target architecture (memory-mapped or port-mapped).
Several advantages accrue. First, resultant B# binary code is more compact. The stack architecture of B#EVM precludes specifying registers and addressing modes. Hence, the opcode of B#EVM is reduced to only eight bits from the 16- or 32-bit opcodes of several modern microcontrollers. Second, the B#EVM which directly supports object-oriented features promotes the reusability of software components expressed in binary format on any architecture where the B#EVM is available. It is worth noting that the implementation of the B#EVM, written in full ANSI C, is the only porting effort required for each specific architecture.
Third, not being dedicated to any specific microcontroller architecture, the development of a toolkit (compiler, assembler, monitor, and so on) for a virtual machine like B#EVM is far easier to test, debug, and maintain and therefore, far more cost effective with respect to the development of embedded systems applications.
Finally , B#EVM has its own multi-threading kernel and avoids the inclusion of third party kernels.
The paper is divided into two main sections. In this first part in a series, an overview of the key and unique features of the B# language itself are reviewed, while Part 2 outlines outlines the three major components of the embedded virtual machine B#EVM.
The B# Language
Each B# program consists of one or more source files.Eac h file is composed of types which, in turn, are composed of members.Classes, interfaces, and delegates are examples of different types and fields, methods, properties, interrupt handlers, and device registers are examples of different members. Classes are grouped into namespaces that may extend beyond a single file, but unlike C#, namespaces cannot be nested.
Unified Type System. B# has a unified type system. All B# types inherit from a single root object type. Thus, all types share a set of common operations and values of any type can be manipulated in a consistent manner. B# is also strongly-typed and supports both value and reference types.
Value Types. B# has five value types: boolean (bool), character (char), signed integer (int), unsigned integer (uint), and floating-point (float). For the sake of simplicity and internal stack evaluation efficiency, the five value types are all represented and manipulated as (maximum) 32-bit values.
Reference Types. Whereas value types contain variable data, reference types contain addresses of objects. B# provides a set of predefined reference types familiar to Java or C# developers including object, array, and string. Two additional types, delegate and ioreg for device addressing, are also included. The object type is similar to the untyped pointer (void*) in the C programming language.
Efficient Boxing/Unboxing Conversions. The type system of B# has the ability to obtain type information of every variable at runtime and to treat value types as objects. These runtime capabilities are achieved by keeping minimal information on types in order to provide efficient and flexible boxing/unboxing conversions.
These conversions are an elegant mechanism inspired from C# and
adapted for our needs. Consider the use of boxing/unboxing in the B#
An int value is converted to object and back again to int. Boxing happens when a valuetype variable is converted to a reference type. Unlike C#, an object box is already allocated and therefore, the value does not need to be copied into the box. Unboxing is the complementary process, but contrary to C#. B# avoids copying a value into and out of a box by providing a pre-allocated wrapping mechanism within the B#EVM stack.
This wrapping mechanism uses a tag that is set for each variable and identifies its type. When a value-type variable is converted to a reference type (or vice versa), the tag field is reset. In this way, the unified type systems of B# provides value types with the benefits of reference types without introducing unnecessary overhead.
Expressions and Multi-threading Statements. The operators of B#, their precedence and associativity, are identical to those in C. Only the pointer operators *, &, and -> are excluded and only the operators, new for object creation and is for type testing, are also included. Expressions are formed by combining literal values and variables with B# operators.
B# also borrows several sequential statements from C including statement lists, block statements, expression statements, return, if, while, and break. In addition, the lock and start statements of B# are inspired from Edison.
The lock statement, originally called when in Edison, is used for mutual exclusion and synchronization. The start statement, originally called cobegin in Edison, is used to initiate threads. The addition of multi-thread and synchronization statements facilitates the development of embedded systems where concurrent activities are often implicit.
In the following example, two threads, SerialPortThread and ParallelPortThread, are initiated
with access to a shared buffer.
Classes and Objects. In B#, classes are the most fundamental types.A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). A class provides a specification for dynamically created instances of the class, also known as objects.
Classes support inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes. New classes are created using class declarations. A class declaration starts with a header that specifies the modifiers of the class, the name of the class, the base class (if any), and the interfaces implemented by the class.
Class Members. In B#, the members of a class are either static members or instance members. Static members belong to classes and instance members belong to objects (instances of classes). The following table provides an overview of the kinds of members a class can contain.
|Table 1. Class Members in B#|
Field Properties. A field property is a natural extension of fields and is similar to properties in C#. In addition to declaring a field, a field property also specifies the read and/or write access to the field itself using the get and set accessors, respectively.
Each accessor is defined as a block statement which is executed when the field value is read or written. In essence, therefore, a field property is a field declaration followed by a get and/or set accessor.
In the following example, the Device
module defines a Status field
property. A property is always assumed to be an implicit private field with public accessors. Unlike C#, field
properties in B# denote storage locations.Therefore, it is unnecessary
to declare the private field status.
The value of a field property can be read by invoking the get accessor or written by invoking the set accessor. In a set accessor, the new value for the field property is passed via an implicit parameter named value. Accessing a field property is like getting or setting the value itself. For example, the Status property can be read and written in the same way that fields can be read and written:
Device Registers. The type ioreg represents input/output device register addressing for embedded processors based on the ISO/IEC standard.It is used for both port- and memory mapped device registers, but submerges the distinction between the two kinds of registers to the level of the virtual machine B#EVM.
Therefore, the embedded systems developer is not required to specify whether or not a device is either port- or memory-mapped: the ioreg provides a uniform way of handling both. The type ioreg is the base class of three other predefined classes, ioreg8, ioreg16, and ioreg32, which allow read/write access from/to 8-bit, 16-bit, and 32-bit device registers, respectively.
Access to the device registers is defined using a mechanism similar
to field properties. The only difference between the two is that the
address of a ioreg field must
be initialized at declaration. The following example declares three
device registers as read only, write only, and read/write:
Interrupt Handlers. An interrupt handler (also called an interrupt service routine) is a special method which is executed when an external hardware interrupt is triggered. Each handler is specified by adding the interrupt keyword in front of a method, making it implicitly static and internal with no return value.
The interrupt number is declared after the name of the handler and
is mapped internally by the B#EVM.The following method is a real-time
clock handler set to the interrupt vector 8:
Later, in the second part in this series, we will discuss the inner workings of the embedded virtual machine B#EVM.
Michel de Champlain will present a full day tutorial at the Embedded Systems Conference (ESC-504: Java Jumpstart in Room C2) starting at 8:30 a.m. on April 7. At 4:30 p.m. after the class, he will present a 30 minute presentation on B#.
Michel is chief scientist of DeepObjectKnowledge Inc., an
object-oriented training/mentoring firm located in Montreal, Quebec,
Canada. He is also a former associate professor in Computer Engineering
at Concordia University and a regular speaker at the Embedded Systems
Conference. He can be contacted at mdec@DeepObjectKnowledge.com.
Brian is an associate professor of Computer Science/Studies at Trent University located in Peterborough, Ontario, Canada. His main research interests are programming languages and parallel job scheduling. He can be contacted at email@example.com.
 M.Barr, Is C Passing?, Embedded.com, May 2002.
 J.W. Grenning, Why are you still using C?, Embedded.com, April 2003.
 M.de Champlain, B# Grammar, presents the grammatical summary of the B# programming language. Its syntax is described in a concise fashion using the EBNF notation. www.DeepObjectKnowledge.com\BSharpProject or www.BSharpLanguage.org.
 M.de Champlain and B.G Patrick, B# Project: Object Design for Developping Small Embedded Systems Applications, will be published by Newnes/Elsevier, Fall 2006.