In embedded systems, the term firmware is very common and describes the software that runs close to the hardware usually with limited resources and commonly in a deterministic execution time frame. Don’t be fooled, however; Firmware can be many thousands of code lines and be a complete application.
How such a piece of software is debugged? It is often stated that debugging is an art. Debugging embedded systems is even more difficult. Electronics that control physical resources (like motors) cannot freeze while stepping in the code, making the process challenging. It would be really hard to trace a problem in this case. So experts in the field use multiple approaches often not found in usual software development projects to trace intermittent errors or problems that relate to the unpredictable environments in real-time.
Software/firmware quality is something that cannot be easily assessed by non-experts. There are a few guidelines though, which give an indication of the written code quality.
How many bugs are revealed during testing?
How difficult are these faults to be pinpointed?
How easy is to change operation or add features?
How fast can you port to other microcontroller architectures?
The first rule of debugging in embedded systems is to avoid creating bugs in the first place. A good architectural design and coding practice are required to achieve a low bug count and reduce debug time. On a medium scale of an embedded project expect a significant amount of time before you see any actual line of code. This time goes for architectural decisions and tests that will pay off later with faster coding and a quality product.
From more than 40 man-years of embedded firmware experience, we have mastered these techniques. Using Test-Driven Development methods, layered architectures, timing evaluations, best coding practices, and system testing we achieve our goals on time. Furthermore, we leave support for debugging in cases these are needed during later phases of the product’s lifecycle. There is also strong experience in production-grade safety-critical systems that can help create such applications or provide consulting on the process.
We use C and Assembly, creating code that can be ported to different microcontroller architectures fast and support development or product with Python and GUI scripting. Our debug strategies include a combination of debuggers, oscilloscopes, and logic analyzers to effectively pinpoint difficult to resolve issues if ever arise.