openocd-jtag — Claude Code skill: what it does, how to install
Configures OpenOCD for JTAG and SWD hardware targets, flashes MCU firmware, and manages bare-metal GDB debug sessions.
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a claude-codeWhat openocd-jtag does
This skill provides target workflows for debugging microcontrollers such as STM32, nRF52, ESP32, and RP2040. It guides the agent through building openocd.cfg configurations for CMSIS-DAP and J-Link adapters, choosing between SWD and JTAG transports, and serving GDB on port 3333.
Standard software breakpoints modify instruction memory directly and fail when code executes out of flash. The skill enforces hardware breakpoints (hbreak) and memory watchpoints (watch, rwatch) instead. Note that hardware registers are strictly limited by the MCU design, offering around 4 to 8 breakpoints on standard Cortex-M chips.
Reference snippets also include telnet commands on port 4444, non-interactive flashing via program ... verify reset exit, and a troubleshooting table for hardware connection errors. When device identification fails, the agent immediately checks power lines and configuration scripts.
What it helps with
- generate OpenOCD configuration files for CMSIS-DAP and J-Link adapters
- flash ELF and raw binary firmware directly from the command line
- connect arm-none-eabi-gdb to a running OpenOCD session on port 3333
- configure hardware breakpoints and memory watchpoints on bare-metal firmware
- resolve unable to find JTAG device and scan chain interrogation errors
Example prompts for the agent
- Show me a single command to flash firmware.elf to an STM32 using OpenOCD.
- Create an openocd.cfg file for J-Link and nRF52 over SWD.
- How do I set a hardware watchpoint on a memory address in GDB?
How to install openocd-jtag
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a claude-code2Manually: put the files in place
~/.claude/skills/openocd-jtag/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/openocd-jtag/
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a codex2Manually: put the files in place
.agents/skills/openocd-jtag/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a cursor2Manually: put the files in place
.cursor/skills/openocd-jtag/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install mohitmishra786/low-level-dev-skills openocd-jtag2Manually: put the files in place
.github/skills/openocd-jtag/SKILL.md1Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a gemini-cli2Platform CLI
gemini skills install https://github.com/mohitmishra786/low-level-dev-skills --path skills/embedded/openocd-jtagManually: put the files in place
.devin/skills/openocd-jtag/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about openocd-jtag
How to install openocd-jtag in Claude Code?
Run npx skills add mohitmishra786/low-level-dev-skills --skill openocd-jtag -a claude-code. The file installs directly to ~/.claude/skills/openocd-jtag/SKILL.md.
What does the openocd-jtag skill do?
It gives your coding agent reference guides for OpenOCD configuration, flashing routines, transport selection, and bare-metal GDB workflows.
Why does this skill advise using hbreak instead of break?
Regular breakpoints patch code memory with trap instructions, failing in execute-in-place flash. The hbreak command uses dedicated hardware debug registers instead.
Source text
SKILL.md · MIT
---
name: openocd-jtag
description: OpenOCD skill for embedded hardware debugging. Use when configuring OpenOCD for JTAG or SWD targets, flashing firmware, connecting GDB to bare-metal targets, setting hardware watchpoints, or using J-Link with OpenOCD. Activates on queries about OpenOCD, JTAG, SWD, GDB remote target, flash programming, hardware breakpoints, J-Link, or connecting GDB to an MCU.
---
# OpenOCD / JTAG Debugging
## Purpose
Guide agents through configuring OpenOCD for JTAG and SWD targets, flashing firmware to microcontrollers, attaching GDB for bare-metal debugging, setting hardware watchpoints, and configuring J-Link and CMSIS-DAP adapters.
## Triggers
- "How do I connect GDB to my MCU with OpenOCD?"
- "How do I flash firmware using OpenOCD?"
- "How do I set up J-Link with OpenOCD?"
- "What's the difference between JTAG and SWD?"
- "How do I set a hardware watchpoint in GDB?"
- "OpenOCD says 'Error: unable to find JTAG device' — how do I fix it?"
## Workflow
### 1. JTAG vs SWD
| Feature | JTAG | SWD (Serial Wire Debug) |
|---------|------|------------------------|
| Pins | 4+ (TCK, TMS, TDI, TDO, TRST) | 2 (SWCLK, SWDIO) |
| Multi-target | Yes (daisy chain) | No (one target) |
| Speed | Up to 30 MHz | Up to 10 MHz |
| Availability | Full JTAG: Cortex-A/R, RISC-V | SWD: Cortex-M only |
| Cable cost | More complex | Simpler 2-wire |
Most Cortex-M microcontrollers support both. Use SWD when pin count is limited.
### 2. OpenOCD configuration
```tcl
# openocd.cfg — CMSIS-DAP (ST-Link v2, DAPLink)
source [find interface/cmsis-dap.cfg]
source [find target/stm32f4x.cfg]
adapter speed 4000 # kHz
# For SWD explicitly
transport select swd
# J-Link adapter
source [find interface/jlink.cfg]
jlink serial 123456789 # optional: select by serial
source [find target/nrf52.cfg]
adapter speed 8000
```
```bash
# Run OpenOCD (keeps running, serves GDB on port 3333)
openocd -f openocd.cfg
# Common interface config files
ls $(openocd --help 2>&1 | grep "scripts" | head -1)/interface/
# cmsis-dap.cfg, jlink.cfg, ftdi/olimex-arm-usb-ocd.cfg, stlink.cfg ...
# Common target config files
ls $(openocd --help 2>&1 | grep "scripts" | head -1)/target/
# stm32f4x.cfg, nrf52.cfg, esp32.cfg, rp2040.cfg, at91sam4s.cfg ...
```
### 3. Connecting GDB
```bash
# In terminal 1: start OpenOCD
openocd -f openocd.cfg
# In terminal 2: start GDB
arm-none-eabi-gdb firmware.elf
# GDB commands
(gdb) target extended-remote :3333 # connect to OpenOCD
(gdb) monitor reset halt # reset and halt target
(gdb) load # flash ELF to target
(gdb) monitor reset init # re-initialize after flash
(gdb) break main # set software breakpoint
(gdb) continue
# One-liner for quick debugging
arm-none-eabi-gdb -ex "target extended-remote :3333" \
-ex "monitor reset halt" \
-ex "load" \
-ex "break main" \
-ex "continue" \
firmware.elf
```
### 4. Flashing firmware
```bash
# Flash via OpenOCD telnet interface
telnet localhost 4444
# OpenOCD telnet commands
> reset halt
> program firmware.elf verify reset
> exit
# Or via GDB
(gdb) monitor flash write_image erase firmware.bin 0x08000000
(gdb) monitor reset run
# Flash only (no debug) — script mode
openocd -f openocd.cfg \
-c "program firmware.elf verify reset exit"
# For raw binary
openocd -f openocd.cfg \
-c "program firmware.bin 0x08000000 verify reset exit"
```
### 5. Hardware breakpoints and watchpoints
Software breakpoints (`break`) patch instruction memory with trap instructions — they don't work in flash-execute-in-place without debug registers. Use hardware breakpoints instead:
```bash
# Hardware breakpoint (uses debug register, limited count: 4-8 on Cortex-M)
(gdb) hbreak function_name
(gdb) hbreak *0x08001234
# Hardware watchpoint — triggers on memory read/write
(gdb) watch global_variable # write watchpoint
(gdb) rwatch some_buffer # read watchpoint
(gdb) awatch sensor_value # read OR write watchpoint
# List breakpoints/watchpoints
(gdb) info breakpoints
# Cortex-M typically has: 4–8 hardware breakpoints, 2–4 watchpoints
```
### 6. OpenOCD commands reference
```bash
# Via telnet (port 4444) or GDB monitor
monitor reset halt # reset and hold at reset vector
monitor reset init # reset and run init scripts
monitor reset run # reset and run freely
monitor halt # halt running target
monitor resume # resume execution
monitor mdw 0x20000000 # memory display word at address
monitor mww 0x40021000 0x1 # memory write word
monitor reg r0 # read register
monitor arm disassemble 0x08000000 16 # disassemble 16 instructions
# Flash operations
monitor flash list
monitor flash erase_sector 0 0 0 # erase sector 0
monitor flash write_bank 0 firmware.bin 0
```
### 7. Common errors
| Error | Cause | Fix |
|-------|-------|-----|
| `unable to find JTAG device` | Wrong interface, cable, or power | Check USB connection; power target; verify interface config |
| `JTAG scan chain interrogation failed` | Wrong target config or bad SWD mode | Match config to exact MCU; try `transport select swd` |
| `flash 'stm32f4x' is not supported` | Wrong target | Check MCU part number; use correct `.cfg` |
| `Error: timed out while waiting for target halted` | Target running, not halted | `monitor halt`; check BOOT pins |
| `Cannot access memory at address` | MMU, memory protection, or wrong address | Check MPU config; use correct flash/RAM address |
| `Warn: target not examined yet` | OpenOCD not connected to target | Check power and connections |
### 8. J-Link configuration
```tcl
# openocd.cfg for J-Link
source [find interface/jlink.cfg]
jlink usb 0 # use first J-Link found
transport select swd # or jtag
adapter speed 4000
source [find target/stm32l4x.cfg]
```
J-Link GDB Server (alternative to OpenOCD):
```bash
# Segger's own GDB server
JLinkGDBServer -if SWD -device STM32L476RG -port 3333 &
arm-none-eabi-gdb -ex "target remote :3333" firmware.elf
```
## Related skills
- Use `skills/embedded/freertos` for FreeRTOS-aware debugging with OpenOCD
- Use `skills/embedded/zephyr` for Zephyr's `west debug` integration
- Use `skills/debuggers/gdb` for GDB session management
- Use `skills/embedded/linker-scripts` for understanding memory map for flash addresses
© mohitmishra786 · MIT · mohitmishra786/low-level-dev-skills