Skip to content

Hardware Setup

This guide covers the physical and configuration setup needed before mcjtag can talk to your target. It assumes you already have a debug probe and a target board — if you are looking for a recommendation, the DAP-Link + Blue Pill kit is what mcjtag is developed against.

Both are debug transport protocols supported by ARM cores. The choice depends on your hardware and what you need to do.

FeatureSWDJTAG
Signal count2 (SWDIO + SWCLK)4+ (TDI, TDO, TMS, TCK)
Pin budgetLower — fits on small boardsHigher — needs a header or adapter
Chain scanningSingle target onlyMultiple devices on one chain
SpeedGenerally equalGenerally equal
Chip supportARM Cortex-M/A/R onlyARM, RISC-V, FPGA, any JTAG device
RecommendationUse for most Cortex-M workUse when you need chain scanning or non-ARM targets

If your target is an ARM Cortex-M and you only have one chip to debug, SWD is simpler. If you have multiple devices on a chain, or your target is RISC-V or an FPGA, use JTAG.

Probe PinTarget PinNotes
SWDIOSWDIOBidirectional data line
SWCLKSWCLKClock, driven by the probe
GNDGNDRequired — the most common wiring mistake is a missing ground
3.3VVCCOnly if the target needs power from the probe. Many boards have their own supply.
Probe PinTarget PinNotes
TDITDITest Data In — serial data from probe to target
TDOTDOTest Data Out — serial data from target to probe
TMSTMSTest Mode Select — controls the TAP state machine
TCKTCKTest Clock — driven by the probe
GNDGNDRequired
nRSTRESETOptional but recommended. Allows the probe to reset the target.
  • Missing GND — The debug interface will not work without a shared ground reference. If you see “no JTAG TAPs found” or “target not examined yet”, check ground first.
  • Swapped TDI/TDO — These are named from the perspective of the target. TDI goes into the target, TDO comes out. Some probe boards label them from their own perspective, which reverses the sense.
  • nRST floating — If the target has a reset pin that is not connected to the probe, reset_halt and reset_run may not work reliably. Use a pull-up if you cannot wire it.

Budget-friendly open-source probe. Many USB dongles and dev boards include a DAP-Link interface. mcjtag ships with example configs for this probe.

source [find interface/cmsis-dap.cfg]
transport select swd
adapter speed 1000
source [find target/stm32f1x.cfg]

Supports both SWD and JTAG depending on the firmware variant.

Built into STMicroelectronics Nucleo and Discovery boards. Also available as a standalone USB dongle (ST-Link/V2, ST-Link/V3).

source [find interface/stlink.cfg]
transport select hla_swd
adapter speed 1000
source [find target/stm32f4x.cfg]

Note: ST-Link uses a proprietary protocol (hla_swd or hla_jtag), which has some limitations compared to CMSIS-DAP. For example, you cannot do raw JTAG shift operations through jtag_shift().

Professional probe from Segger. Fast, reliable, and well-supported. Requires the J-Link software package to be installed alongside OpenOCD.

source [find interface/jlink.cfg]
transport select swd
adapter speed 4000
source [find target/nrf52.cfg]

Various low-cost adapters based on FTDI chips (FT2232H, FT232H). Configuration depends on the specific board layout.

source [find interface/ftdi/olimex-arm-usb-ocd-h.cfg]
transport select jtag
adapter speed 2000
source [find target/stm32f1x.cfg]

An OpenOCD config file has four logical sections. The order matters.

# 1. Interface — what debug probe are you using?
source [find interface/cmsis-dap.cfg]
# 2. Transport — SWD or JTAG?
transport select swd
# 3. Speed — adapter clock in kHz. Start low and increase if stable.
adapter speed 1000
# 4. Target — what chip is being debugged?
source [find target/stm32f1x.cfg]

OpenOCD ships with configs for hundreds of chips. Common ones:

Chip FamilyConfig File
STM32F1 (Blue Pill, etc.)target/stm32f1x.cfg
STM32F4 (Nucleo-F4, etc.)target/stm32f4x.cfg
STM32H7target/stm32h7x.cfg
nRF52 (Nordic)target/nrf52.cfg
RP2040 (Raspberry Pi Pico)target/rp2040.cfg
ESP32target/esp32.cfg
GD32F1 (GigaDevice)target/stm32f1x.cfg (compatible)
Generic Cortex-Mtarget/cortex_m.cfg

If you are unsure which config to use, target/cortex_m.cfg works for any ARM Cortex-M device. You lose chip-specific flash programming support, but all register and memory operations work.

To find configs on your system:

Terminal window
find /usr/share/openocd/scripts/target -name "*.cfg" | sort

Start at 1000 kHz (1 MHz). If you get reliable connections, you can increase to 4000 or higher. If you see errors or intermittent failures, drop to 100.

Long wires, breadboard connections, and noisy environments all degrade signal integrity and may require lower speeds.

Instead of starting OpenOCD manually, set OPENOCD_CONFIG and mcjtag handles it:

Terminal window
# Pass the config file path
OPENOCD_CONFIG=/path/to/my-board.cfg uvx mcjtag

mcjtag will start OpenOCD as a subprocess, connect to it, and stop it when the session ends. The config file should be a complete OpenOCD config (interface + transport + speed + target).

You can also pass host and port for an existing OpenOCD instance:

Terminal window
OPENOCD_HOST=192.168.1.100 OPENOCD_PORT=6666 uvx mcjtag

Before involving mcjtag, confirm OpenOCD works on its own:

Terminal window
openocd -f /path/to/your/config.cfg

Healthy output looks like:

Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: FW Version = 0254
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: Cortex-M3 r1p1 processor detected
Info : stm32f1x.cpu: target has 6 breakpoints, 4 watchpoints

If OpenOCD fails here, mcjtag will also fail. Fix the OpenOCD setup first.