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:

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

Worked example: Flash time

Given: 512 KB image; Effective programming rate 200 KB/s

Find: Time.

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?

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.

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> g

OpenOCD (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

Applications

Key takeaways

Going further