3 Overlooked Embedded Software Elements

Have you ever wondered, while you and your team are busy writing software if the very foundation of how embedded software systems are built has changed and left you in the dust? What if while you were busily focusing on getting your product out the door, fighting bugs, and dealing with supply issues, there were techniques and processes that you were completely overlooking that could save the day? I’ve found three elements that embedded software teams often overlook and underutilize that could dramatically improve their software.

The overlooked elements can be seen below in Figure 1. Take a moment to look at the figure and identify the missing pieces from your software.

3 Overlooked Elements in Modern Embedded Software

Figure 1 – Modern embedded software is built upon several layers of autogenerated tools that configure the platform, software model, and product features.

I suspect that many of you have the blocks in gray that include Platform Configuration and the light blue section labeled Handwritten Application Code. But what about the rest? Now, let’s dig in and explore how the three overlooked elements, Configuration Management, Modeling Tools, and Test Harnesses, can help you.

Element #1 – Model Generated Code

A modeling tool can help you build out a visualization of critical pieces of your software system. From that model, it can be possible to simulate the behavior off-target to tweak behavior, features, etc. You can then convert the model to target specific code with a functional model! If the model needs to be tweaked, it can be done off-target, and then a button click or two can regenerate the target code.

You can gain a huge advantage in development costs and time-to-market by leveraging tools that model embedded software; However, many teams overlook their use. There are a few outdated arguments developers use, such as:

  • The generated code is garbage
  • The tools are too complex
  • The tools cost too much

Perhaps there are still some tools that have these issues, but over the last few years, I’ve seen tremendous strides being made that have decreased costs, simplified the tools, and a dramatic improvement in the autogenerated code. Even when some of these arguments hold, is the overall net benefit still in your best interest? You’d have to do a trade study, but I would put money on it that it probably still is.

Element #2 – Configuration Generated Code

The second often overlooked element in modern embedded software is how teams configure their products. During my many hours reviewing code for dozens of companies, I often see teams failing to develop a strategic method for configuration management. Most companies have multiple products SKUs that reuse significant portions of their code. I often see code that uses copy and pastes and a plethora of conditional statements to compile code into and out of a codebase conditionally. The trick is to develop and include autogenerated configuration code specific to your product that you integrate into your build system.

For example, there might be a product that has three different SKUs. Each SKU perhaps has a different number of tasks due to specific sensors being present, headless, etc. Instead of conditionally compiling or duplicating the code base for all three, the differences can be coded into a configuration file that is used to generate the code automatically. The developers can then use their build system to specify which SKU they want to generate and build. Alternatively, you can build out your SKUs in different repositories that use git modules to create the SKU-specific repository and build out the DevOps pipelines for each SKU.

A simple block diagram view of how the configuration generated code works can be found below in Figure 2.

Figure 2 – Configuration management can be done using configuration files, templates, and a script that creates the final code modules.

Element #3 – Test Driven Code

The last area that is often overlooked, although sometimes thought about, is automated testing. Unit testing and automated testing have found their way into nearly all areas of computer engineering, but it still struggles to gain adoption within the embedded systems space. While test code and harnesses are not part of your code per se, if appropriately leveraged, they can dramatically improve your software quality and help you catch bugs quickly.

For example, I was recently working on a project where I developed a packet decoding module. The customer required a significant update to the packet’s protocol, which required updating the code. Even though the protocol was different, the interface stayed the same, and many of the tests could be used as-is or with slight modification. As I made my updates, I ran my test harness and discovered that not all the tests were passing. I had overlooked a corner case, but my tests caught it! If I didn’t have my tests, I probably would have pushed the updates and introduced a bug just waiting to wreak havoc on the system at the worst possible time.

Getting in the habit of writing unit tests and building test automation into your DevOps can make a difference. The trick is taking the time to invest upfront so that you can take advantage of it later on. It’s the classic case of the tortoise and the hare; it feels like you’re going slow, but you’ll win the race in the end.


I know how much you have on your plate, and it can be hard to stay up to date or find time to implement the latest technologies in your development cycle. However, the three overlooked elements in modern embedded software are areas that can help you manage your projects better, accelerate timelines, and improve your chances of delivering your products on time. I hope this post gives you a few ideas on where to focus your improvements in the future.

14 thoughts on “3 Overlooked Embedded Software Elements”

  1. Auto-generated software is magic code. I prefer to know exactly what my code is doing, so that when something goes wrong I can speak to it. “Maybe the problem is somewhere in the autogenerated stuff??” Not a good answer.

  2. Is there some names of tools to make model generated code or configuration generated code ?

    1. Thanks for the question. From a platform configuration standpoint, if you look at MPLAB X, STM32CubeMx, etc those are examples. For configuration-generated code, I can’t think of any publicly available examples, although my next book will have some. For model-driven generated code, you can look at tools like Matlab, although there are some good UML based tools like Visual Paradigm, IAR StateFlow, etc.

      1. There’s an interesting tradeoff here between Jim’s comment above, and run time efficiency. STM32CubeMx generates a lot of code, and has a memory footprint that is outsized with respect to the functionality performed in the firmware. However, you can review the code (if you ignore the large amount of boilerplate and conditionally compiled code it generates) to see exactly what it does. Arguably, they could vastly simplify the generated firmware source if they performed much more work at code generation time in the generator software. However, you would lose visibility into how the source was generated, _unless_ they release the generator source also.

        I’ve successfully used COG (https://nedbatchelder.com/code/cog/) to include Python generated C source. The Python source gets committed to the repository along with the C source, and the generation can be included in the build system cleanly. This allows one have both source visibility as well as the benefits of auto generation.

        1. Yes, the STM32CubeMx tool does generate “bloated” code that can be trimmed back quite a bit for most applications. Definitely a trade-off.

          Thanks for the comment and tool suggestion for Python!

          1. I’ve been working with STM32CubeMx off and on for a while. Alot depends on how you use the tool. I’ve found if you keep yourself to basic peripheral configuration and use LL only (a thin layer on top of CMSIS vs bloated HAL that makes some questionable design choices) you can get rid of most of the bloat and keep most of the advantages. Alas still generated from ST templates. Like any tool, needs to somehow be verified fit for use per the criticality of your application.

          2. George – We’ve also used the LL drivers in some projects. They provide less functionality, so require more development effort. I guess it’s good that ST provides a memory footprint vs. development effort tradeoff, but one of the main selling points of auto generation is the reduced development effort.

    2. For model-based generation of state machines, there is the QM tool for Miro Samek’s QP Framework, as well as Yakindu Statechart Tools for a platform-agnostic version (which supports additional languages as well, like Python).

  3. SCADE Suite is also good model-based code generator that generates qualified code to DO-178C level A. Used it on a couple of aerospace projects.

  4. Just coming from the 3 days debugging a problem involving a generated code I may be somewhat jaded.
    The problem was not a bug in the code generator (mercilessly!), but actually hardware (broken wires, just-discovered flaws of the measuring instrumentation). But having generated code did not help at all in the process, mildly speaking.

    Frequently I find that the code generation tools suffer from a photo-tripod-like problem.
    The tripod conundrum goes like this:
    You can have a tripod which has two of the following properties:
    1 – it is cheap
    2 – it is stable
    3 – it is light
    but you cannot have one which has all the three.

    You can have a tool which fulfills two of the following:
    1 – it is cheap or free
    2 – it is well documented and fit for purpose
    3 – the generated code is of a god quality and understandable
    but very often you have only one or NONE.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.