Thought Leadership

Embedded code: clear or clever?

When developing embedded code, there are various priorities. Top of the list, obviously, is delivering the required functionality and performance. This can be challenging enough. A key requirement is a clear, unambiguous and stable specification. However, at a lower level, the code developer has lots of everyday decisions to make around a number of sometime opposing priorities …

The design of desktop applications is driven by a single criterion: user satisfaction. So, given the design [the user interface in particular] is up to scratch, the main thing is speed. Embedded systems are different as there may or may not be a UI; the device may or may not be real time; cost can be a big issue. The list goes on, but ultimately it results in some prioritization when implementing the code:

  1. code for highest performance
  2. code for predictable performance [deterministic]
  3. code for minimum size
  4. code for minimum power consumption
  5. code for maintainability

Of these, 1-4 are often in tension and finding the balance is the challenge and that depends on the application. To a significant extent these factors are influenced by the higher-level aspects of the implementation: using a real-time operating system, with a power-management framework perhaps; maybe implementing a multicore design. Beyond that, understanding the fine tuning of code generation is worthwhile, as a compiler generally knows best how to achieve many of these goals.

The outlier is #5. Software development is expensive. More time is spent maintaining code [fixing, updating and augmenting] than developing new applications. This means that any effort spent making the code clearer is an investment in the future. There are two bonuses: clearer code is generally more reliable, which means that it needs less maintenance; code written for clarity is very rarely slower or larger than a less clearly expressed algorithm.

Writing clear, maintainable code is possible in most programming languages. Although this may be challenging in, say, Forth of LISP. It is [very] easy to write highly obfuscated code in C, but writing clear code is not difficult. There are numerous coding style guides around and even using a programming standard like MISRA C, that is designed to help make code reliable, tends to lead to more maintainable code. To some extent, a “higher level” language may be helpful, as algorithms may be expressed more naturally. C++ is an obvious possibility. Here is an example:

If an application uses complex numbers, a means to represent them and operate on them is required. In C, a structure makes sense:

struct cx
{
   float real;
   float imag;
};

Then, we can create two variables, initialize them and add one to the other thus:

struct cx x, y;

x.real = 1.0;
x.imag = 2.0;

y.real = 3.0;
y.imag = 4.0;

x.real += y.real;
x.imag += y.imag;

This is reasonably clear and succinct, but can C++ do better? I would say the answer is yes. We can define a class to represent the data, which can include a constructor function to take care of initialization and a function to perform the addition:

class cx
{
   float real;
   float imag;
public:
   cx(float r, float i)
   {
      real = r;
      imag = i;
   }
   void add(cx n)
   {
      real += n.real;
      imag += n.imag;
   }
};

This enables complex variables to be set up and added thus:

cx x(1.0, 2.0), y(3.0, 4.0);

x.add(y);

Although this is neater/clearer that C, there is room for improvement. The add() function can be replaced by an operator overloading function [which has identical code]:

void operator+=(cx n)
{
   real += n.real;
   imag += n.imag;
}

The result is handling of complex numbers in a very natural way:

cx x(1.0, 2.0), y(3.0, 4.0);

x += y;

These features of C++ can certainly help clarify code, particularly the operator overloading. However, a word of warning. It is essential to maintain the intuitive functionality of the operator, as I have here. The += does exactly what the reader of the code would expect. Many years ago, when I was first learning C++, I read a book that demonstrated the overloading of the + operator, which would result in a statement like this:

x + y;

This would add y to x. Go figure.

Colin Walls

I have over thirty years experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, I am a member of the marketing team of the Mentor Graphics Embedded Systems Division, and am based in the UK. Away from work, I have a wide range of interests including photography and trying to point my two daughters in the right direction in life. Learn more about Colin, including his go-to karaoke song and the best parts of being British: http://go.mentor.com/3_acv

More from this author

Leave a Reply

This article first appeared on the Siemens Digital Industries Software blog at https://blogs.stage.sw.siemens.com/embedded-software/2020/07/13/embedded-code-clear-or-clever/