As an embedded software engineer, it's easy to think that all the software for the product relies upon the hardware. Most embedded developers want to get to a development board right out of the gate and start writing software, including myself. It's not necessarily wrong; it's just familiar and allows us to understand the complexities and issues of the hardware. However, if we design our application code correctly, then we can use simulation and testing on most of our code without the underlying hardware. There are several different ways that a developer can simulate their code to prove it out before actually integrating it with the hardware.
First, and perhaps the easiest way to simulate code is developing and testing it on a PC. Developers can use GCC or G++ to run their code on a computer and then generate and verify the output. It's pretty easy for Linux and Mac developers to do this since they directly access a terminal that supports GCC or G++. Windows developers might need to install Cygwin or Mingw, which is pretty trivial to setup.
Earlier I mentioned that properly designed software could be simulated or tested on a PC. Properly designed software is architected to minimize dependencies and designed to be flexible and isolate components. The latter architecture allows them to be run and tested without bringing in the entire code base. They can be executed on the PC, and the inputs can be fed in via a file. Then, the outputs can be written to a file to be analyzed or even plotted if necessary.
A good example of this technique is from one of my recent projects where we focused most of our software development effort 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 incorrectly?"
Typically, an embedded software developer would play 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 amount of time. Due to how 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 allowed a developer to perform a sanity check on the part of the software. If it matched, there was an issue with how the algorithm was integrated into the embedded processor. If it didn't match, then the C implementation needed some adjustments.
This brings us to a second option for simulating embedded software, i.e., 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 been simulated in Matlab. I knew exactly what it was supposed to output based on known inputs. Comparing the embedded C 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 mean, and what the outputs should look like for those inputs. Sometimes we can get away with this, but it is often critical that the developer understand the details if an issue arises.
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 to get the job done. 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. This simulation can prove that the system is working the way it should or help in troubleshooting 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.
Jacob Beningo is an embedded software consultant who currently works with clients in more than a dozen countries to dramatically transform their businesses by improving product quality, cost and time to market. He has published more than 200 articles on embedded software development techniques, is a sought-after speaker and technical trainer, and holds three degrees which include a Master of Engineering from the University of Michigan. Feel free to contact him at firstname.lastname@example.org at his website www.beningo.com, and sign-up for his monthly Embedded Bytes Newsletter.