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.
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.