JTAG & SWD Debug Interfaces
JTAG and SWD connect your PC's debugger to the chip for flashing, breakpoints and live inspection. Learn JTAG signals and the TAP state machine, boundary scan and daisy chains, ARM Serial Wire Debug (2 pins) and its packet format, the CoreSight debug architecture (DAP, AP, breakpoints, watchpoints, SWO/ITM, ETM trace), debug probes and connectors, and how to secure the debug port in production.
Every time you click 'Debug' in your IDE, a probe (ST-LINK, J-Link, CMSIS-DAP) talks to the MCU's debug access port. It can halt the CPU, read and write any memory or register, program Flash, and set hardware breakpoints — all without any code running on the target.
JTAG (IEEE 1149.1) was invented for testing PCB connections (boundary scan) and later reused for debugging. ARM's SWD replaces JTAG's 4–5 pins with just 2 (SWDIO, SWCLK), which matters on small MCUs.
An analogy
The debug port is a service hatch on a machine: a technician can stop the machine, inspect every gear and change settings while it is paused. In the field you lock the hatch so nobody else can open it.
What a debug probe can do
Through SWD/JTAG the host can:
- Program and verify Flash
- Halt, step and resume the CPU; read/write registers
- Set hardware breakpoints (typically 6–8 on Cortex-M) and data watchpoints (4)
- Read memory and peripheral registers while running (non-intrusive on Cortex-M)
- Stream trace data: SWO/ITM printf, PC sampling, exception trace, ETM instruction trace
JTAG TAP and boundary scan
JTAG devices contain a Test Access Port controlled by a 16-state machine driven by TMS on each TCK edge. Instructions select data registers: IDCODE, BYPASS, or the boundary-scan register that controls/observes every pin — letting factory testers check solder joints without firmware. Multiple chips can be daisy-chained TDO→TDI, sharing TCK/TMS.
SWD protocol
SWD sends packets on a single bidirectional line. Each transaction: host sends an 8-bit request (start, AP/DP select, read/write, register address, parity, stop, park), a turnaround bit, the target answers with a 3-bit ACK (OK/WAIT/FAULT), then 32 data bits and parity. Everything else — memory access, Flash programming — is built from DP/AP register accesses.
Connectors, reliability and security
Use a standard 10-pin 1.27 mm Cortex debug connector (or Tag-Connect footprint), keep NRST connected so the probe can 'connect under reset' when firmware disables SWD pins or sleeps deeply, and add series resistors/ESD protection on exposed lines. In production, disable or lock debug (STM32 RDP level 1/2, nRF APPROTECT, secure debug with certificates) — an open debug port gives attackers your firmware and keys.
Formulas
- SWD transaction:
8-bit request + turnaround + 3-bit ACK + 32 data bits + parity (+ turnaround) ≈ 46 clocks - Raw SWD bandwidth:
≈ f_SWCLK × 32/46 bits per second (memory reads) - Flash programming time:
t ≈ image size / effective rate (limited by Flash write, not SWD) - JTAG chain length:
Total IR length = Σ IR lengths of devices; each device adds 1 bypass bit in DR scans
Worked example: Flash time
Given: 512 KB image; Effective programming rate 200 KB/s
Find: Time.
- 512 / 200
Answer: ≈ 2.6 s (Flash write speed limits, not SWD clock)
Worked example: Can't connect
Given: Firmware reconfigures PA13/PA14 as GPIO at startup
Find: How to recover?
- SWD pins are lost after boot
- Hold NRST, connect, then halt before firmware runs
Answer: 'Connect under reset' (or boot into system memory via BOOT0)
Worked example: Watchpoint use
Given: A global 'mode' gets corrupted randomly
Find: Debug approach.
- Set a data watchpoint on write to &mode
- CPU halts at the exact instruction writing it
Answer: Hardware watchpoint (DWT) finds the culprit, often a buffer overflow nearby
Flashing and debugging from the command line
# Start a GDB server for an STM32F4 over an ST-LINK (OpenOCD)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
# In another terminal: flash and debug with GDB
arm-none-eabi-gdb build/app.elf
(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) load # program Flash from the .elf
(gdb) break main
(gdb) continue
# Alternative: SEGGER J-Link
JLinkExe -device STM32F407VG -if SWD -speed 4000 -autoconnect 1
J-Link> loadfile build/app.hex
J-Link> r
J-Link> gOpenOCD (or J-Link GDB server / pyOCD) translates GDB's remote protocol into SWD transactions. The same flow works in VS Code, CubeIDE or any IDE underneath.
printf over SWO with ITM (no UART needed)
#include "core_cm4.h"
int _write(int fd, char *buf, int len) /* newlib hook for printf */
{
for (int i = 0; i < len; i++) ITM_SendChar(buf[i]); /* stimulus port 0 */
return len;
}
/* Enable SWO in the debugger (trace clock = core clock, e.g. 2 MHz SWO),
then view output in the IDE's SWV console or 'JLinkSWOViewer'. */ITM writes take only a few cycles and don't use a UART pin — excellent for logging in timing-sensitive code, as long as a debug probe with SWO is attached.
Common mistakes
- Wrong: Remapping SWD pins as GPIO without a recovery path. — Right: Keep NRST on the connector; use connect-under-reset.
- Wrong: Leaving debug unlocked in shipped products. — Right: Set readout protection / secure debug.
- Wrong: Using software breakpoints in Flash. — Right: Cortex-M uses limited hardware breakpoints; plan their use.
Applications
- Development: Everyday flashing, stepping and inspection.
- Production: Programming and boundary-scan testing in the factory.
- Performance analysis: SWO PC sampling and ETM trace for profiling.
- Failure analysis: Reading crash state from returned units (if unlocked).
Key takeaways
- JTAG: TAP + boundary scan; SWD: 2-pin ARM debug.
- Probes flash, halt, break, watch and trace.
- Keep NRST for recovery; use SWO for cheap logging.
- Lock debug in production.
Going further
- ETM instruction trace: Records every executed instruction — needs a trace port and probe.
- Multi-core debug: Cross-trigger interface halts cores together.
- Secure debug authentication: Challenge–response unlock for field returns.