On this page
Debug and Programming Interfaces
JTAG/SWD are the interfaces for taking over the CPU from the outside (breakpoints, single-stepping, flashing, boundary scan), while DFU and UART bootloaders are the chip’s built-in flashing channels. Use SWD for development, flash the bootloader first for mass production followed by batch DFU, and use OTA for field upgrades—different stages use different interfaces.
Overview
The "interfaces" around an MCU actually serve three different purposes: debugging (pausing the CPU, breakpoints, single-stepping, reading/writing memory), flashing (writing firmware into Flash), and production testing (verifying soldering without running firmware). To understand each interface, first determine which category it belongs to and what prerequisites it depends on:
| Interface | Pins | Capabilities | Prerequisites |
|---|---|---|---|
| JTAG | 4~5 | Debug + Flash + Boundary Scan | External Debugger |
| SWD | 2 | Debug + Flash (ARM Cortex) | External Debugger |
| UART Bootloader | 2 | Flash only | Built into Chip Boot ROM |
| USB DFU | 1 USB cable | Flash only | Built into Chip Boot ROM |
| ISP/ICSP | 6 pin | Flash (AVR family) | Programmer |
Key distinction: JTAG/SWD take over the CPU from the outside—the chip can be debugged and recovered even if it's bricked; DFU/UART bootloaders cooperate with the chip for flashing—no dedicated hardware is needed, but if the firmware misconfigures the boot pins, you won't be able to enter the bootloader.
JTAG (IEEE 1149.1)
Born in the 1980s for testing PCB soldering (Joint Test Action Group), it later became a debugging standard as well.
| Pin | Full Name | Function |
|---|---|---|
| TMS | Test Mode Select | Drives the internal state machine |
| TCK | Test Clock | Clock signal |
| TDI | Test Data In | Data input |
| TDO | Test Data Out | Data output |
| TRST | Test Reset | Optional reset |
Multiple chips can be daisy-chained (TDI → TDO → next chip's TDI), allowing one debugger to control the entire board. Voltage must match the target (1.8V~5V), with typical speeds of 1~50MHz.
Among its three uses, boundary scan best reflects its origins: JTAG can directly control/read the voltage levels of every pin on a chip, verifying whether traces between two chips on a PCB are properly soldered without running any firmware—this is the foundation of production line testing. Debugging (pausing CPU, breakpoints, reading/writing memory/Flash) and flashing were capabilities added later.
SWD (Serial Wire Debug)
A streamlined alternative designed by ARM for Cortex: compressing JTAG's 4~5 lines down to 2 lines—SWDIO (bidirectional data) + SWCLK (clock), plus the necessary GND. Debugging capabilities are not compromised: breakpoints/single-stepping/register access, Flash programming, and multi-core debugging via the DP/AP mechanism, with speeds reaching 50MHz+ (CoreSight).
| JTAG | SWD | |
|---|---|---|
| Pins | 4~5 | 2 |
| Features | Full + Boundary Scan + Daisy Chain | Debug + Flash, sufficient for most needs |
| Coverage | Almost all chips (including FPGA/DSP) | ARM Cortex series |
| PCB Footprint | Large | Small, easy to route two lines |
The selection logic is straightforward: always use SWD for Cortex-M development; for non-ARM, complex SoCs, or when boundary scan is needed → use JTAG; if unsure, leave the full JTAG port available (JTAG pins can be multiplexed to output SWD).
Debugger Hardware and OpenOCD
| Debugger | Interface | Price | Positioning |
|---|---|---|---|
| ST-Link V2 | SWD | $2~10 (clone) | First choice for learning STM32 |
| DAP-Link (CMSIS-DAP) | SWD+JTAG | $5~15 | Open-source, universal ARM |
| J-Link (SEGGER) | SWD+JTAG | $20~1000 | Professional: fast speed, RTT, unlimited breakpoints |
| FT2232H | JTAG | $10~20 | Versatile companion for OpenOCD |
| Raspberry Pi Pico | SWD | $4 | Becomes a debugger after flashing picoprobe |
The hub on the software side is OpenOCD—it translates between third-party tools:
flowchart LR
GDB["gdb-multiarch<br>(breakpoints/single-stepping/variables)"] <-->|"GDB remote protocol<br>:3333"| O["OpenOCD"]
O <-->|USB| P["Debugger<br>ST-Link / J-Link / DAP"]
P <-->|SWD / JTAG| T["Target Chip"]
()
The interface side supports ST-Link/J-Link/DAP-Link/FTDI, etc., and the target side covers almost all ARM + RISC-V + MIPS—it is the de facto standard in the open-source ecosystem.
Built-in Chip Flashing Channels
USB DFU
The chip's Boot ROM (factory-fused, cannot be erased) detects specific conditions and makes the chip enumerate as a USB device, allowing the Host to send firmware directly via USB:
- STM32: Pull BOOT0 high on power-on → System Memory bootloader
- nRF52: Specific register values + reset
- RP2040: Hold BOOTSEL while powering on → appears directly as a USB drive; drag and drop firmware to flash (best DFU experience)
The advantage is zero additional hardware—users only need a USB cable to flash; the disadvantage is that it can only flash, not debug.
UART Bootloader
Also a Boot ROM behavior, but the medium is changed to serial (XMODEM/YMODEM/custom protocol):
- STM32: System bootloader listens on USART1
- ESP32: ROM bootloader, esptool enters automatically (or pull GPIO0 low)
- AVR: Not present at factory; must first flash one using ISP (Arduino bootloader is this)
- MSP430: BSL
As long as there is a serial port, you can flash, but the cost is speed—115200bps is about 10KB/s, so a few hundred KB of firmware takes tens of seconds.
Three Channels in the Product Lifecycle
flowchart LR
DEV["Development Phase<br>SWD/JTAG<br>Debug + Flash anytime"] --> FAC["Production Line<br>First flash bootloader via SWD<br>Then batch flash via DFU"]
FAC --> FIELD["Field<br>APP built-in DFU/OTA<br>User self-service upgrade"]
Logic Analyzer: Bus-Level Debugging
Debuggers solve "where the code is wrong," while logic analyzers solve "what exactly is happening on the lines"—when firmware looks correct but peripherals ignore you, use this to settle the matter. Saleae / DSLogic / PulseView all have built-in protocol decoders: I2C (auto-decode address+data+ACK), SPI (frame-by-frame display), UART (convert to ASCII by baud rate), CAN/LIN, 1-Wire; they also support protocol-level triggering (e.g., "start capturing when address 0x68 appears on I2C").
Typical troubleshooting (using an unresponsive I2C sensor as an example):
flowchart TD
S["I2C Sensor Not Working"] --> C["Capture SDA/SCL Waveforms"]
C --> Q{"ACK after Address?"}
Q -->|No ACK| A["Wrong Address / Wiring Error / Chip Not Powered"]
Q -->|Has ACK| B{"Register Read/Write Values Correct?"}
B -->|Incorrect| D["Check Register Timing in Datasheet"]
B -->|Correct| E["Problem Not on Bus → Return to Firmware Logic"]
SPI Flash instability is similar: capture CS timing, CLK frequency, and data integrity to rule out physical layer issues first. Details of bus protocols can be found in Serial Bus.
Quick Selection Guide
| Chip/Scenario | Recommendation |
|---|---|
| STM32 Development | SWD (ST-Link) |
| nRF52 Development | SWD (J-Link / DAP-Link) |
| ESP32 Development | Serial (Built-in bootloader, esptool) |
| RP2040 Development | SWD or USB Drag-and-Drop |
| AVR (Arduino) | ISP (6-pin) |
| ARM Linux Kernel Debug | JTAG (OpenOCD + GDB) |
| FPGA | JTAG (Vivado/Quartus Built-in) |
| Field Firmware Upgrade | DFU / OTA |
| Sensor/Peripheral Unresponsive | Logic Analyzer Capture Bus |
| Production Line Testing | JTAG Boundary Scan |
References
- JTAG: IEEE 1149.1 · ARM Debug Interface (ADIv5) Manual
- OpenOCD: openocd.org/doc
- SEGGER: wiki.segger.com (RTT/J-Link documentation quality is extremely high)
- Sigrok/PulseView: sigrok.org (Open-source logic analysis)
Keywords: JTAG, SWD, SWDIO, SWCLK, OpenOCD, DFU, Boot ROM, bootloader, ST-Link, J-Link, DAP-Link, Boundary Scan, Logic Analyzer