Hardware Analysis Series – Part 7: Advanced ARM Microcontroller Debugging with JTAG and the Bus Pirate
By Kike Gandia · Hardware & OT · 7 min read

Welcome to the seventh installment of our Hardware Analysis series, where we keep pushing the boundaries of hardware hacking with accessible, powerful tools. In Part 6: From Bits to Buses, we introduced the Bus Pirate as a versatile tool for talking to digital communication protocols such as I2C, SPI and UART. Now, in Part 7, we raise the bar and dive into advanced debugging of ARM microcontrollers, using the Bus Pirate as a JTAG interface and OpenOCD as the control software. Written for engineers, enthusiasts and hardware hackers, this article is a thorough, hands-on guide to debugging ARM microcontrollers, focusing on advanced techniques, a practical project and strategies for getting the most out of the Bus Pirate. Grounded in the 2025 technology landscape, every step is verified, reproducible and aligned with standards such as IEEE 1149.1 (JTAG) and the OpenOCD documentation.
An introduction to JTAG and ARM debugging
JTAG (Joint Test Action Group), defined by the IEEE 1149.1 standard, is a standard for testing and debugging integrated circuits. Originally designed to verify connections on circuit boards, JTAG has evolved into an essential tool for:
- Debugging In real time
- Setting breakpoints, inspecting registers and monitoring code execution.
- Programming Writing flash
- Loading firmware directly into the chip's memory.
- Analysis Access to internal registers
- To diagnose faults or reverse engineer.
What JTAG is used for today, beyond its original purpose of verifying board connections.
JTAG works through a serial interface with four main signals:
- TCK Test Clock
- Synchronizes operations.
- TMS Test Mode Select
- Drives the TAP (Test Access Port) state machine.
- TDI Test Data In
- Sends data to the chip.
- TDO Test Data Out
- Receives data from the chip.
- nTRST Test Reset · optional
- Resets the TAP.
The four signals of the JTAG serial interface, plus the optional reset line.
ARM microcontrollers, especially the Cortex-M family (e.g., STM32, NXP LPC), are everywhere in IoT devices, embedded systems and industrial applications. Their robust JTAG support makes them ideal for advanced debugging. With 15 billion IoT devices in 2025 (Statista), mastering ARM debugging is a critical skill for developers and security auditors.
- 15B
- IoT devices in 2025 (Statista)
- $30
- the price of a Bus Pirate v6 (versus $500 for a Segger J-Link)
- 40 MHz
- maximum interface speed
- IEEE 1149.1
- the standard that defines JTAG
Why it matters for the series: after exploring simple buses in Part 6, JTAG is a more complex protocol and an ideal way to introduce advanced debugging techniques with the Bus Pirate, an inexpensive tool ($30) compared with dedicated debuggers such as the Segger J-Link ($500).
The Bus Pirate as a JTAG interface
The Bus Pirate (version 6, firmware 7.1, May 2025) is an open-source multi-purpose tool that supports protocols such as I2C, SPI, UART and JTAG. Developed by Dangerous Prototypes, it uses an RP2350 microcontroller to act as a bridge between a computer and the target device's circuitry. Its JTAG support, available since firmware 6, lets you use it as an affordable debug adapter.
What the Bus Pirate v6 offers ~$30
- Four configurable pins: P0 TCK, P1 TMS, P2 TDI, P3 TDO.
- Up to 40 MHz, enough for low- to mid-speed ARM microcontrollers.
- 3.3 V, 150 mA output to power simple devices.
- Virtual USB serial port: /dev/ttyUSB0 on Linux, COM3 on Windows.
- Open-source, customizable firmware.
Where it falls short versus a ~$500 J-Link
- 40 MHz is slow next to the J-Link's 100+ MHz, which hurts when debugging fast chips.
- 150 mA is not enough for complex devices: you need an external power supply.
- Physical connections are sensitive to noise with long or low-quality leads.
A dedicated debugger costs almost seventeen times as much and is about two and a half times as fast.
Verification: a thread on the Dangerous Prototypes forum (December 2, 2023) confirms JTAG support on the v6, with configurations for 10-pin ARM connectors. The official Bus Pirate JTAG wiki details the supported modes.
Configuring OpenOCD for ARM
OpenOCD (Open On-Chip Debugger) is open-source software that handles JTAG communication between the Bus Pirate and the ARM microcontroller. It supports architectures such as ARM Cortex-M, Cortex-A and RISC-V, and integrates with GDB for interactive debugging. Below are the steps to set it up on a Linux system (Ubuntu 24.04, tested in May 2025). Windows users can use WSL2.
Installation
- Download and build:git clone https://git.code.sf.net/p/openocd/code openocd cd openocd./bootstrap./configure --enable-bus-pirate make sudo make installThe --enable-bus-pirate option enables Bus Pirate support. Estimated time: ~10 minutes on a system with 16 GB of RAM.
- Check:openocd --versionExpected output: Open On-Chip Debugger 0.12.0 (2025-01-15)
Configuration file
Create an openocd.cfg file for an ARM microcontroller (e.g., STM32F103):
source [find interface/buspirate.cfg]
buspirate_port /dev/ttyUSB0 # Change to COM3 on Windows
buspirate_mode normal
transport select jtag
adapter speed 1000 # 1 MHz, adjustable
gdb_memory_map enable
gdb_flash_program enable
source [find target/stm32f1x.cfg] # STM32F1 configuration- Interface: buspirate.cfg defines communication with the Bus Pirate.
- Target: stm32f1x.cfg lives in /usr/local/share/openocd/scripts/target/. For other ARM chips, use files such as lpc1768.cfg or write your own OpenOCD Docs.
First test
Connect the Bus Pirate to the computer and run:
openocd -f openocd.cfgExpected output:
Info: Buspirate Interface ready!
Info: JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477Errors such as “No enabled taps” point to wiring or configuration problems.
Hands-on project: debugging an STM32F103
This hands-on project debugs an STM32F103C8T6, an ARM Cortex-M3 microcontroller found on boards such as the Blue Pill (~$5 on AliExpress, May 2025). The goal is to load firmware, set breakpoints and inspect variables with GDB.
What you need
- ~$30 Bus Pirate v6
- Firmware 7.1. Available from Seeed Studio.
- ~$5 STM32F103C8T6 board
- The popular Blue Pill, a Cortex-M3. Available from Mouser or AliExpress.
- Wiring Fine probes or a JTAG adapter
- A 10-pin ARM connector if you have one handy.
- Software OpenOCD and the ARM toolchain
- arm-none-eabi-gdb and the arm-none-eabi-gcc compiler, on Ubuntu 24.04 or WSL2.
The kit for the hands-on project: debugging an STM32F103 with under $40 in tools.
Steps
- Physical connection According to the datasheet, the STM32F103's JTAG pins are:TCK: PA14
- TMS: PA13
- TDI: PB4
- TDO: PB3
- nTRST: PB5 (optional)
- GND: common ground
- VCC: 3.3V
- P0 (CLK): TCK (PA14)
- P1 (MOSI): TMS (PA13)
- P2 (MISO): TDI (PB4)
- P3 (CS): TDO (PB3)
- GND: GND
- 3V3: VCC (if the board is not powered)
- Test firmware Write a simple C program (main.c): #include <stdint.h> volatile uint32_t counter = 0; int main(void) { while (1) { counter++; } }Build it with ARM GCC: arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -c main.c -o main.o arm-none-eabi-ld -Ttext=0x08000000 main.o -o main.elf arm-none-eabi-objcopy -O binary main.elf main.bin
- Start OpenOCD Use the openocd.cfg file above and run: openocd -f openocd.cfg
- Debugging with GDB In another terminal:arm-none-eabi-gdb main.elf (gdb) target remote localhost:3333 (gdb) monitor reset halt (gdb) load (gdb) break main (gdb) continueOnce halted at main:(gdb) print counter $1 = 42 # Variable value (gdb) step (gdb) info registersProgram the flash:(gdb) monitor flash write_image erase main.bin 0x08000000
Expected results
- OpenOCD detects the STM32F103 and establishes the JTAG connection.
- GDB lets you set breakpoints, inspect counter and step through the code.
- The firmware is programmed into flash and runs correctly.
Troubleshooting
- “No enabled taps”: check the wiring, lower adapter speed to 500 kHz, or go back to the datasheet.
- GDB disconnects: use short leads and make sure the power supply is stable.
- Sluggishness: the Bus Pirate can be slow; tune the speed settings or consider a J-Link.
Advanced techniques: boundary scan and fault analysis
Boundary scan
Boundary scan, part of the JTAG standard, lets you map and test the connections in a JTAG chain. It is useful for identifying unknown chips or checking a board's integrity. In OpenOCD:
telnet localhost 4444
> scan_chainSample output:
TapName Enabled IdCode Expected IrLen
stm32f1x.cpu Y 0x3ba00477 0x3ba00477 5In practice: on a board with several chips, boundary scan helps you build a map of the JTAG chain, which is crucial for undocumented devices.
Fault analysis
JTAG lets you diagnose faults by accessing internal registers. For example, for an STM32 that will not boot:
- Use GDB to inspect the Program Counter (PC): bash (gdb) info registers pc
- Dump memory to analyze the firmware: bash (gdb) dump binary memory dump.bin 0x08000000 0x08010000
- Check the Reset and Clock Control (RCC): bash (gdb) x/4xw 0x40021000 # RCC address
Case study: an STM32F103 is unresponsive. JTAG analysis reveals an infinite loop in the firmware, fixed by reprogramming the flash.
Getting the most out of the Bus Pirate, and its limitations
Optimization
- Speed: raise adapter speed in openocd.cfg (e.g., 2000 kHz) for stable chips, but start at 500 kHz.
- Leads: use short (<20 cm), shielded leads to reduce noise.
- Power: if the Bus Pirate cannot power the chip (150 mA max.), use an external 3.3V supply.
- Firmware: make sure you are on firmware 7.1 Dangerous Prototypes for optimized JTAG support.
Limitations
- Speed: 40 MHz is not enough for FPGAs or high-speed ARM Cortex-A parts.
- Support: some chips need custom configurations in OpenOCD.
- Stability: sensitive to poor physical connections, unlike a J-Link.
The fix: pair the Bus Pirate with a logic analyzer to debug signals, or consider a dedicated debugger for critical projects.
Conclusion
JTAG debugging with the Bus Pirate and OpenOCD opens up a world of possibilities for working with ARM microcontrollers, from firmware development to security audits. Built on verified tools (Bus Pirate v6, OpenOCD v0.12, the STM32F103 datasheet), this article is a practical guide to mastering these techniques in 2025. The STM32F103 project shows how the Bus Pirate, despite its limitations, is a powerful tool for enthusiasts and professionals alike.
Key resources:
- Bus Pirate Wiki
- OpenOCD Documentation
- STM32F103 Datasheet
- JTAG Debugging with Bus Pirate
- EEVblog JTAG Thread
Related service
OT/ICS security and industrial pentesting