Debugging & Testing
Debugging embedded systems is uniquely challenging—you're dealing with real-time constraints, hardware interactions, and limited visibility. Mastering debugging tools and testing methodologies is essential for shipping reliable products.
Debug Interfaces
Modern microcontrollers provide dedicated hardware interfaces for debugging:
JTAG (Joint Test Action Group)
- Industry-standard debug interface
- 4-5 wire interface: TCK, TMS, TDI, TDO, (TRST optional)
- Supports boundary scan for manufacturing tests
- Full access to processor state and memory
- Allows daisy-chaining multiple devices
SWD (Serial Wire Debug)
- ARM-specific, uses only 2 wires: SWDIO and SWCLK
- Functionally equivalent to JTAG for most debugging
- Saves PCB space and pins
- Common on Cortex-M devices
💡 Pro Tip: SWD is preferred for Cortex-M projects due to fewer pins. Reserve JTAG for multi-core debugging or when boundary scan is needed.
Debug Probes & Tools
Hardware tools that connect your PC to the target MCU:
Popular Debug Probes
- ST-Link: Integrated on STM32 Nucleo/Discovery boards, low cost
- J-Link: Industry standard, fast, extensive device support (Segger)
- CMSIS-DAP: Open standard, many implementations available
- Black Magic Probe: Open source, works as GDB server itself
- PicoProbe: Use a Raspberry Pi Pico as a debug probe
Software Debugging Techniques
1. Breakpoints
Pause execution at specific lines of code to examine program state.
- Hardware Breakpoints: Limited number (usually 4-8), but work on any code including flash
- Software Breakpoints: Unlimited in RAM, modifies code to insert break instruction
- Conditional Breakpoints: Break only when a condition is true
2. Watch Expressions
Monitor variable values in real-time without breaking execution.
⚠️ Important: Mark watched variables as
volatile to prevent compiler optimization from hiding
their values during debugging!
3. Printf Debugging (UART/SWO)
Classic technique using serial output for runtime logging:
4. SWO/ITM Trace
ARM's Instrumentation Trace Macrocell allows printf over the debug probe—no extra UART needed!
Logic Analyzers & Oscilloscopes
Essential tools for debugging hardware-related issues:
Logic Analyzer
- Capture and decode digital signals
- Analyze protocol transactions (SPI, I2C, UART, CAN)
- Timing analysis between events
- Popular: Saleae, DSLogic, Sigrok-compatible devices
Oscilloscope
- View analog waveforms and signal quality
- Measure rise times, overshoot, ringing
- Debug power supply issues
- Mixed-Signal Oscilloscopes (MSO) combine analog + digital
Testing Methodologies
Unit Testing
Test individual functions in isolation, often on host PC:
Popular embedded testing frameworks:
Unity CppUTest Google Test Ceedling
Integration Testing
- Test multiple modules working together
- Verify communication between components
- Test on actual target hardware
Hardware-in-the-Loop (HIL) Testing
Simulate the physical environment while testing real firmware:
- Replace physical sensors/actuators with simulators
- Inject edge cases and fault conditions
- Automate regression testing
- Essential for automotive, aerospace, and safety-critical systems
Common Debugging Scenarios
Hard Fault Debugging (ARM Cortex-M)
Timing Issues
- Use GPIO toggling + oscilloscope to measure timing
- Check for interrupt latency with trace tools
- Profile code sections with DWT cycle counter
Static Analysis & Code Quality
- Compiler Warnings: Enable -Wall -Wextra -Werror
- Static Analyzers: PC-lint, Polyspace, Coverity, cppcheck
- MISRA C: Coding standard for safety-critical systems
- Code Review: Peer review catches many bugs early
🎯 Key Takeaway: Effective debugging requires the right mindset (be systematic!), the right tools, and experience. Build a debugging toolkit and document your troubleshooting steps!