Mastering debugging embedded code with JTAG and SWD for STM32 is the skill that separates professional embedded developers from hobbyists. Hardware debugging lets you step through code, inspect memory, set breakpoints, and catch bugs that serial print debugging can never reveal. This guide covers complete JTAG/SWD setup for STM32.
Table of Contents
- JTAG vs SWD Explained
- Hardware Setup: ST-Link and J-Link
- OpenOCD Configuration
- VS Code Debug Setup
- GDB Commands for Embedded
- Debugging Tips for Indian Projects
- Frequently Asked Questions
JTAG vs SWD Explained
Both JTAG and SWD provide hardware debugging and programming access to STM32 processors, but SWD (Serial Wire Debug) is a 2-wire Arm-specific protocol (SWDIO + SWDCLK) that occupies fewer pins than JTAG’s 4–5 signals. For STM32 development, SWD is the standard choice — it’s faster, uses fewer pins, and is what ST-Link probes use by default.
JTAG (Joint Test Action Group) uses TDI, TDO, TMS, TCK, and optionally TRST. It’s used when you need boundary scan testing or are working with JTAG-only targets. Most Indian STM32 projects use SWD.
Hardware Setup: ST-Link and J-Link
Debug probes available in India:
- ST-Link V2 clone (₹150–300): SWD-only, sufficient for most STM32 work. Widely available from Indian online stores. Works with STM32CubeIDE, OpenOCD, and PlatformIO.
- ST-Link V3SET (₹1,800–2,500): Official from ST via Mouser India. Multi-protocol (JTAG, SWD), faster, supports virtual COM port and bridge functions.
- J-Link EDU/BASE (₹5,000–8,000): SEGGER’s professional probe. Fastest flash programming, reliable for commercial development.
- Onboard ST-Link (Nucleo boards): Nucleo-F103RB, Nucleo-F411RE include ST-Link V2.1 onboard — can debug external targets via CN4 SWD header.
SWD connection: 3 wires minimum (SWDIO, SWDCLK, GND). Add NRST for reliable reset.
OpenOCD Configuration
# Install OpenOCD
sudo apt install openocd
# openocd.cfg for STM32F103 Blue Pill with ST-Link V2
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f1x.cfg]
# Start OpenOCD server
openocd -f openocd.cfg
# Output: Listening on port 3333 (GDB), 4444 (telnet), 6666 (TCL)
# openocd.cfg for STM32F411 Black Pill
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f4x.cfg]
VS Code Debug Setup
With PlatformIO in VS Code, debug setup is largely automatic. For manual setup:
// .vscode/launch.json
{
"configurations": [{
"name": "Debug STM32",
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"executable": "${workspaceFolder}/build/firmware.elf",
"device": "STM32F411CE",
"runToEntryPoint": "main",
"svdFile": "${env:HOME}/.platformio/packages/framework-stm32cubef4/SVD/STM32F411xx.svd"
}]
}
Install extensions: Cortex-Debug by marus25 and ARM Assembly (optional). The SVD file enables peripheral register viewing — see exactly what’s in UART_DR, ADC_DR, etc., in the debug view.
GDB Commands for Embedded
# Connect GDB to OpenOCD
arm-none-eabi-gdb build/firmware.elf
(gdb) target extended-remote localhost:3333
# Load and run
(gdb) load # Flash firmware
(gdb) monitor reset # Reset target
(gdb) continue # Run
# Breakpoints
(gdb) break main # Break at function
(gdb) break sensor.c:45 # Break at file:line
(gdb) info breakpoints
# Inspection
(gdb) print temperature # Print variable
(gdb) print/x *0x40011000 # Print memory (hex)
(gdb) x/10wx 0x20000000 # Examine 10 words at SRAM start
(gdb) info registers # Show all CPU registers
(gdb) bt # Backtrace (call stack)
# Stepping
(gdb) step # Step into function
(gdb) next # Step over function
(gdb) finish # Run until function returns
Debugging Tips for Indian Projects
- Enable compiler optimisation at -O0 for debugging (code location matches source lines exactly)
- FreeRTOS task-aware debugging: OpenOCD can show all task stacks — enable in Cortex-Debug settings
- Semihosting: printf() output over SWD to OpenOCD console — no UART needed for debug output
- Watch expressions: set watches on critical variables that update automatically at each breakpoint
- Memory fault: set break on HardFault_Handler to catch null pointer and out-of-bounds accesses
Frequently Asked Questions
Can I debug ESP32 with JTAG?
Yes. ESP32 supports JTAG via the 4-wire JTAG port (TDI, TDO, TMS, TCK). ESP32-S3 has built-in USB JTAG. Use OpenOCD with ESP32 config + ESP-PROG or direct USB connection on ESP32-S3.
What is SWV (Serial Wire Viewer)?
SWV/ITM (Instrumentation Trace Macrocell) allows printf-style debugging over the SWD SWDTCK and SWO pins without occupying UART. Available on Cortex-M3 and M4 targets. J-Link and ST-Link V3 support SWV; cheap ST-Link V2 clones usually don’t.
Is hardware debugging worth it for hobby projects in India?
For complex projects (FreeRTOS, BLE, multi-peripheral), definitely yes. A ₹200 ST-Link clone with OpenOCD and VS Code gives professional debugging capability. Finding a FreeRTOS stack overflow or I2C lockup that Serial.print can’t reveal makes it invaluable.
Add comment