As an embedded software engineer, it’s really easy to think that all the software for the product is reliant upon the hardware. Most embedded developers that I encounter want to get a development board right out of the gate and start writing software, including myself most of the time. It’s not necessarily wrong, it’s just familiar and allows us to understand the complexities and issues that are associated with the hardware. The fact is though, if we designed our application code correctly, we could simulate and test most of our application code without the underlying hardware. Simulating and debugging off-target hardware is more efficient and cost-effective. In today’s post, we’ll explore three tips for successfully simulating embedded software.
Simulating Embedded Software Tip #1 – Focus on the Business Logic
Embedded developers need to recognize that the business logic of their product, the secret sauce that differentiates their products, can be written so that it is hardware independent. Hardware-independent code can be simulated and tested within a PC environment with no target hardware required.
Developers don’t need to cross-compile the business logic for their target but instead can compile it using GCC or g++. The application can then be executed on the computer with simulated inputs and outputs. Simulation can help dramatically speed up development and prove it out before the hardware team ever delivers prototypes boards.
I’ve generally found this is easier for Linux and Mac developers who have direct access to a Linux-style terminal. Windows developers might find they need to install Cygwin or Mingw, both of which are pretty trivial to set up. However, it has been rumored that new versions of Windows will soon, or perhaps already do ship, with a Linux-based terminal.
Simulating Embedded Software Tip #2 – Architect the Software Wisely
Earlier I mentioned that properly designed software can be simulated or tested on a PC. “Properly designed” software is software that is architected to minimize dependencies and designed to be flexible with isolated components. Careful software architecture development allows components and modules to be tested separately before being integrated into the product. In fact, it’s not uncommon for me to perform most of my business logic testing on a PC. A PC environment allows us to rapidly test inputs, outputs, plot data, and test corner cases that would be difficult on-target.
A good example of how this technique can work is from a recent project that I was working on where we focused most of our software development on the end hardware since it was available. Eventually, we ran into an issue where an application algorithm just was not providing the expected output. It was close but just not quite right. This left us with an interesting question, “Was there some interaction with the hardware or RTOS or was the algorithm just coded wrong?”.
Normally, an embedded software developer would monkey around with the software on the hardware for weeks trying to figure out what could be causing the problem. In that type of situation, a team is gambling with finding a solution in any reasonable period of time. Due to the way that the software was designed and implemented, I was able to extract the algorithm, which one would have considered to be hardware dependent, and then wrap it in test code that I executed on a PC. I was then able to plot the output and compare it to the expected results. This allows for a developer to perform a sanity check on part of the software in a controlled and isolated environment. If it matches, there is an issue with the way the algorithm is integrated into the embedded processor. If it doesn’t match, then the target implementation might need some adjustments.
Simulating Embedded Software Tip #2 – Leverage Tools Like Matlab
This brings us to the last option for simulating embedded software that we will discuss today, using a tool such as Matlab. Matlab can allow a team to simulate state machines, algorithms and dig into how a system will behave. In fact, in many automotive and aerospace applications teams will even let Matlab generate the embedded code for them and the team then just needs to maintain their model! In the above example, the algorithm I was working with had actually been simulated in Matlab. I knew exactly what it was supposed to output based on known inputs. Comparing the embedded code simulation with the Matlab output then provided the details to show whether there was an issue with the algorithm or something in the embedded system.
Simulations can also help the embedded developer understand the system as a whole. Sometimes we blindly implement algorithms without really understanding how they work, what the inputs really mean, and what the outputs should look like for those inputs. Sometimes we can get away with this, but if an issue arises, it’s often critical that the developer understand the details. The simulation can help with that especially if all the knobs and dials are included. A developer can increase parameter A and see how it changes the output. Then parameter B can be adjusted and so forth until they fully understand how the system can work. I’ve found that in many cases, it’s not the algorithm so much as its interaction with real-time behaviors that is the issue.
Embedded software developers don’t have to be dependent upon the hardware in order to get the job done. Certainly, it is great when the hardware is available, and it can allow developers to get through hurdles on the hardware. At the end of the day though, many algorithms and application features can be simulated and tested off target. In fact, this simulating can help to prove that the system is working the way it should or to help troubleshoot small nuances that might otherwise take considerable time to debug. Developers need to add off-target simulation to their bag of tricks if they aren’t already doing so.