Unit Test Embedded Software in 3 easy steps

The most difficult step in unit testing embedded software can be getting your code to compile on your host system.  Once you can get the code to compile on a host machine it is easy to simply follow standard practices to test any C code.  This article will show you how to make your embedded software portable.

The major challenges to portability of embedded are:


  • Target architecture and word size
  • Non-standard compilers
  • Hardware specifics

The key to overcoming these obstacles is abstraction.  Typically we start with source code like this:


And we’d like to end with something like this:


You can achieve this by leaning heavily on typedefs and your pre-processor…

1. Abstract your data types.

It doesn’t matter what your target architecture is, the most important thing is to hash define your data types.   The easiest way to do this is to create a project Types.h where you define all your types.  It might look something like this depending on your target:

// TargetTypes.h
typedef uint24   uint24_t;
typedef int24    int24_t;
typedef ulong48  uint48_t;
typedef long48   int48_t;
typedef fix      fix24_t;
typedef lfix     fix48_t;
typedef acc      fix56_t;
typedef char     char24_t;

// HostTypes.h
typedef int      int24_t;
typedef unsigned uint24_t;
typedef long     long48_t;
typedef unsigned long long ulong48_t;
typedef unsigned long long uint48_t;
typedef float    fix;
typedef double   lfix;
// ...etc

This makes it possible to compile your code for both your host and your target architectures, just use a different Types.h depending on the platform; as a bonus it also makes it easier to port the code to other systems in the future.  Once your code is portable it is much easier to test.

2. Abstract your compiler

Compilers for embedded systems rarely follow the ANSI standard, typically adding keywords to define data storage specifics of interrupt routines.  For example, the Keil 8051 compiler has keywords “code” and “data” to specify memory locations; you can imagine how bad it is when you try to hash define that out!  If you compiler has some esoteric language extensions it is pretty safe just to hash define them out, but in my experience you really must be disciplined in the code to use keywords that you are sure will not clash.

// TagetTypes.h continued...
#define CODEMEM code
#define INTERRUPTMEM interrupt
#define XDATAMEM xdata
#define DATAMEM data

// HostTypes.h
// on the host make these directives disappear from the source
#define CODEMEM
#define XDATAMEM
#define DATAMEM

Now we can use these much safer constructs in the source code, safe in the knowledge that we won’t step on anyone’s toes.

3. Abstract your hardware

The final piece of the puzzle is hardware access.  This is sometimes the trickiest obstacle to overcome, but we can get there with the same approach.

// Registers.h
#ifdef TARGET
#define IOMEM_BASE 0x2FF
int32_t fake_registers[IO_MEM_RANGE];
uint32_t IOMEM_BASE = (int32_t)&fake_registers;

So there it is

The first step in unit testing embedded software is making it compile on a host machine.  This can be difficult but if you follow these simple tips you can save yourself a lot of pain.  Remember, the earlier in the project you do this the easier it is!

Happy testing!



Filed under software, testing

6 responses to “Unit Test Embedded Software in 3 easy steps

  1. Pingback: Unit Testing Legacy C | Mike Long’s Blog

  2. createaneinstein

    Hi.. The first two codes are not visible, so if not intentional can you repost those programs?

  3. createaneinstein

    Ah, this post on making the code portable is pretty interesting! Ya this going to make the unit testing easier. How much time we have to spend in making the code portable for an ARM controller you think?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s