Hardware Debugging with JTAG and Logic Analyzers

Firmware fails in ways desktop software rarely does: a device hangs only when the motor is running, an I²C sensor returns garbage once an hour, the board resets when the radio transmits, or a hard fault happens before the serial port is initialized. printf debugging changes timing, may not be available, and cannot see what is happening on the wires.

Hardware debugging tools fill that gap. A debug probe connected over SWD or JTAG lets you halt the processor, step through code, inspect memory and registers, and set watchpoints on real hardware. A logic analyzer shows exactly what happens on digital signals — bus transactions, chip selects, interrupts — with timing. An oscilloscope shows the analog truth when digital assumptions break down. Knowing which tool answers which question saves days.

TL;DR

Quick Example

Flashing and debugging an STM32 with OpenOCD and GDB:

Measuring how long an interrupt handler takes by toggling a spare GPIO and watching it on a logic analyzer:

Core Concepts

Debug Interfaces and Probes

Common probes: ST-LINK (STM32 boards), SEGGER J-Link (wide support, RTT), CMSIS-DAP and DAPLink (open standard), ESP-PROG and built-in USB-JTAG on newer ESP32 chips, plus vendor-specific probes. Match voltage levels, keep wires short, and connect ground.

Debug Software

Build with debug symbols (-g) and, for stepping, lower optimization for the module you are debugging — highly optimized code reorders and removes variables.

Breakpoints, Watchpoints, and Non-Halting Debugging

Microcontrollers support a small number of hardware breakpoints (often four to eight), needed for code in flash. Watchpoints stop execution when a memory address is read or written — the fastest way to find memory corruption. Halting the CPU breaks real-time behavior (motors, radios, watchdogs), so use non-halting techniques: SEGGER RTT (fast logging through RAM buffers read by the probe), SWO/ITM trace, and data watch tracing.

Diagnosing Faults

On Cortex-M, invalid memory accesses, divide-by-zero (when enabled), unaligned access, and stack overflows end in a HardFault or a configurable fault. The Configurable Fault Status Register (CFSR), HardFault Status Register (HFSR), and fault address registers say what kind of fault occurred; the exception stack frame holds the program counter and link register at the time of the fault, which map back to source lines through the ELF file. In production firmware, save these registers and part of the stack to retained RAM or flash in the fault handler and upload them on the next boot as a crash dump.

Logic Analyzers

A logic analyzer samples many digital lines and displays them over time, with protocol decoders for I²C, SPI, UART, CAN, and more (for example Saleae Logic or the open source sigrok/PulseView). Sample at least four times faster than the fastest signal edge rate of interest (much faster for accurate timing), use triggers to capture rare events, and record long captures with sufficient memory. They answer questions such as "did the device NACK?", "was chip select asserted?", and "how long was the gap?". See I2C, SPI, and UART.

When to Use an Oscilloscope

Logic analyzers assume clean 0s and 1s. When signals are not clean — slow rise times from weak pull-ups, ringing on long cables, ground bounce, brown-outs when a radio transmits, noisy power rails — only an oscilloscope shows the analog waveform. Mixed-signal oscilloscopes combine both views.

Practical Techniques

Best Practices

Wire Debug Access Into Every Board Revision

Include SWD or JTAG headers and a spare debug GPIO and UART on prototypes and, where possible, production boards.

Prefer Non-Halting Diagnostics for Real-Time Bugs

Use RTT, trace, GPIO toggles, and logic analyzers when halting would change the behavior.

Capture Faults in the Field

Implement fault handlers that save registers and context for upload after reboot.

Pick the Tool by the Question

Debugger for code state, logic analyzer for digital protocols and timing, oscilloscope for electrical problems.

Common Mistakes

Debugging Optimized Builds Without Knowing It

Blaming Firmware for an Electrical Problem

Undersampling With a Logic Analyzer

FAQ

What is the difference between JTAG and SWD?

Both are debug interfaces. JTAG uses four or five signals and supports daisy chains and boundary scan; SWD, used on Arm Cortex-M devices, needs only two signals and provides equivalent debug access.

Do I need a J-Link or will an ST-LINK work?

For STM32 development an ST-LINK is sufficient. J-Link probes support many vendors and add features such as fast flashing and RTT; CMSIS-DAP probes are open and widely supported.

How do I debug a HardFault?

Read the fault status and address registers, find the stacked program counter and link register from the exception frame, map them to source with the ELF file, and inspect the stack and memory at the time of the fault.

What is a logic analyzer used for?

Capturing digital signals over time to verify protocols, timing, and sequences — decoding I²C, SPI, and UART traffic, measuring delays, and catching rare glitches with triggers.

When do I need an oscilloscope?

When the problem is electrical rather than logical: voltage levels, slow or ringing edges, noise, power dips, or timing at analog thresholds.

Related Topics

References