Lecture 11
Lecture 11
embedded systems
Mariusz Janiak
p. 331 C-3, 71 320 26 44
Shunryu Suzuki
In the beginner’s mind there are many possibilities; in
the expert’s mind there are few
The secrets of debugging are not mysterious. Know your tools. Avoid
the common, dangerous mistakes if you can, then check to make
sure you’ve succeeded. Be proactive. Save data to help you compare
the past with the present, even though ”nothing has changed.” Keep
your eyes and your mind open. And accept the responsibility of
excellence.
General debugging techniques
1
How to debug embedded systems, http://www.edn.com
General debugging techniques
Avoiding bugs
Coding style: use clear, consistent style and useful naming
standards
Document everything, from architecture and interface
specification documents to comments on code lines
Hold code reviews
Program defensively
Check function return values
Be suspicious of cut/paste
Consider using an integrated development environment (IDE)
with dynamic syntax checking
General debugging techniques
General advice
Try to understand as much of what is happening as possible
“it compiles” is NOT the same as “it works”
When in doubt, ask
Then test the answer
Error messages are generally just a vague hint and can be
misleading
Don’t always trust the “comments/documents”, they can be
out-of-date
General debugging techniques
What is a debugger?
A debugger is not an IDE – though the two can be integrated,
they are separate entities
A debugger loads in a program (compiled executable, or
interpreted source code) and allows the user to trace through
the execution.
Debuggers typically can do disassembly, stack traces, expression
watches, and more
No need for precognition of what the error might be
Allows for “live” error checking – no need to re-write and
re-compile when you realize a certain type of error may be
occurring
General debugging techniques
Debugging techniques
Execution tracing
running the program
print
trace utilities
single stepping in debugger
hand simulation
Interface checking
check procedure parameter number/type (if not enforced by
compiler) and value
defensive programming: check inputs/results from other modules
documents assumptions about caller/callee relationships in
modules, communication protocols, etc
Assertions – include range constraints or other information with data
Skipping code – comment out suspect code, then check if error
remains
General debugging techniques
Debugging hints
Understand the problem before you fix it
Debug on the host as much as possible
Most common “Heisenbugs” are memory or thread related.
Find memory problems early
Reproduce and isolate the problem – find the smallest system
which demonstrates the bug
Insert checks for invariants and have the program stop
everything when one is violated
Verify each layer with small, simple tests
Keep a log of events and assumptions (git)
General debugging techniques
Tools
Source-level debugger
Simple printf statement
In-circuit emulators (ICE) and JTAG debuggers
Data monitors
Operating system monitors
Profilers
Memory testers
Execution tracers
Coverage testers
General debugging techniques
Summary
Testing for memory leaks and corruption
Scanning for performance bottlenecks
Collecting a variable trace of key sequences
Ensuring sufficient CPU-bandwidth margin
Evaluating test coverage effectiveness
Tracing operating-system resource usage
Recording execution sequences (semaphores, process
interactions) of key activities
Checking for error returns from common application
programming interfaces
The End