7 Tips for debugging embedded software
Debugging is one task every developer wants to avoid but it is unfortunately a necessary evil of software development. In fact, as EDN's Embedded Study revealed, embedded development projects on average spend more than 20% of their total effort on debugging alone. When the time comes to roll-up your sleeves and start a debugging session, here are some tips to help you along.
Tip #1 – Take controlled baby steps
When a bug creeps into embedded software, the developer's first instinct is often to jump into the code and start making changes. Instead of making changes in a controlled and directed manner, though, the developer's approach is usually haphazard and nearly random. Embedded software development isn’t the Wild West. The resolution of even the simplest bugs should involve reviewing available data, evaluating it, hypothesizing the most likely cause, updating the code, and then testing the update. In the event that the change does not solve the problem new data should at least come to light, which then helps the process to be repeated.
Tip #2 – Increase assertion density
The ASSERT macro is a great tool that returns an error message at runtime if the asserted condition is false. Developers can use this macro to verify that assumptions within their code are holding true. Surprisingly, many developers don’t take the time to put assertions into their code. The ASSERT density of a code base can often be the difference between long and painful debug sessions or the trapping of a failed assumption the moment it happens. ASSERT can help a developer discover bugs or assumption failure immediately. What is the ASSERT density of your code base?
Tip #3 – Use a data logger
Information about how the software is operating is the greatest tool an embedded software engineer can have when debugging. Having performance information such as when tasks start and complete, whether they are preempted, and similar details can be critical. A log of actions taken is a great way for a developer to gain insight into the software's behavior. A log can be as simple as a RAM buffer, a file written to external flash, or as complex as encoded data transmitted to a remote location.
Tip #4 – Use advanced breakpoints
Developers are familiar with using standard break points that can be turned on in an IDE by simply double clicking on a lie of code's left margin. However, many IDEs also have far more advanced breakpoint capabilities, ones that developers rarely utilize. An example of an advanced break point is setting a line to break when a variable reaches a certain value. The use of advanced break points can drastically decrease debugging time and make difficult to catch bugs far easier to spot.
Tip #5 – Review the datasheets again
Debugging peripherals can be especially difficult. Modern microcontrollers can have dozens of registers involved in setting up a single peripheral, and these peripheral settings are not always obvious or well documented. Even worse, the details on how to properly set the peripheral up are usually not all within a single datasheet. Instead, the information is in the form of "bread crumbs" scattered amongst the family and peripheral datasheets, and sometimes even in application notes. Looking at just one document is not enough. When hardware is misbehaving, you'll need to review the datasheets again and again.
Tip #6 – Monitor the call stack
Developers will sometimes question how they ever got to a specific line of code in the first place. IDEs contain a call stack window that can reveal exactly that information. The call stack shows what functions were called and in what order, revealing information that can be very useful for tracing a bug.
Tip #7 – Take a break
Debugging can be a taxing exercise. Diving deep into the workings of software and hardware can give a developer tunnel vision. A developer sometimes needs to step back by either moving on to a different task or by taking a break. Getting away from the system by going for a walk or doing something relaxing will allow the subconscious mind to work on the solution while the conscious mind rests, so that when it's time to start looking at the code again, additional insights will usually follow.
Whether you spend a lot of time debugging or very little, the fact is as embedded software developers it is impossible to avoid. Using the tips in this article can help make debugging more successful, and thus a little bit more palatable.
Jacob Beningo is a Certified Software Development Professional (CSDP) whose expertise is in embedded software. He works with companies to decrease costs and time to market while maintaining a quality and robust product. 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 here.