Quick Start
This page contains complete, runnable examples for the most common tasks. Each example assumes OpenOCD is already running on localhost:6666. Both async and sync versions are provided.
Connect and read target state
Section titled “Connect and read target state”The simplest possible script: connect, read the target state, and print it.
import asynciofrom openocd import Session
async def main(): async with Session.connect() as ocd: state = await ocd.target.state() print(f"Target: {state.name}") print(f"State: {state.state}") if state.current_pc is not None: print(f"PC: 0x{state.current_pc:08X}")
asyncio.run(main())from openocd import Session
with Session.connect_sync() as ocd: state = ocd.target.state() print(f"Target: {state.name}") print(f"State: {state.state}") if state.current_pc is not None: print(f"PC: 0x{state.current_pc:08X}")Output when the target is halted:
Target: stm32f1x.cpuState: haltedPC: 0x08001234Halt, step, and resume
Section titled “Halt, step, and resume”Control the target execution state.
import asynciofrom openocd import Session
async def main(): async with Session.connect() as ocd: # Halt the target state = await ocd.target.halt() print(f"Halted at PC=0x{state.current_pc:08X}")
# Single-step one instruction state = await ocd.target.step() print(f"Stepped to PC=0x{state.current_pc:08X}")
# Resume execution await ocd.target.resume() print("Target resumed")
asyncio.run(main())from openocd import Session
with Session.connect_sync() as ocd: state = ocd.target.halt() print(f"Halted at PC=0x{state.current_pc:08X}")
state = ocd.target.step() print(f"Stepped to PC=0x{state.current_pc:08X}")
ocd.target.resume() print("Target resumed")Read memory
Section titled “Read memory”Read memory at various widths and display a hexdump.
import asynciofrom openocd import Session
async def main(): async with Session.connect() as ocd: # Read 4 words (32-bit) from the vector table words = await ocd.memory.read_u32(0x08000000, count=4) for i, w in enumerate(words): print(f" [0x{0x08000000 + i*4:08X}] = 0x{w:08X}")
# Read raw bytes data = await ocd.memory.read_bytes(0x08000000, 32) print(f"\nFirst 32 bytes: {data.hex()}")
# Pretty hexdump dump = await ocd.memory.hexdump(0x08000000, 64) print(f"\n{dump}")
asyncio.run(main())from openocd import Session
with Session.connect_sync() as ocd: words = ocd.memory.read_u32(0x08000000, count=4) for i, w in enumerate(words): print(f" [0x{0x08000000 + i*4:08X}] = 0x{w:08X}")
data = ocd.memory.read_bytes(0x08000000, 32) print(f"\nFirst 32 bytes: {data.hex()}")
dump = ocd.memory.hexdump(0x08000000, 64) print(f"\n{dump}")Read and write registers
Section titled “Read and write registers”Access CPU registers by name, with convenience methods for common ARM Cortex-M registers.
import asynciofrom openocd import Session
async def main(): async with Session.connect() as ocd: await ocd.target.halt()
# Read individual registers pc = await ocd.registers.pc() sp = await ocd.registers.sp() lr = await ocd.registers.lr() print(f"PC=0x{pc:08X} SP=0x{sp:08X} LR=0x{lr:08X}")
# Read several at once values = await ocd.registers.read_many(["r0", "r1", "r2", "r3"]) for name, val in values.items(): print(f" {name} = 0x{val:08X}")
# Read all registers all_regs = await ocd.registers.read_all() print(f"\n{len(all_regs)} registers available")
# Write a register await ocd.registers.write("r0", 0x42)
await ocd.target.resume()
asyncio.run(main())from openocd import Session
with Session.connect_sync() as ocd: ocd.target.halt()
pc = ocd.registers.pc() sp = ocd.registers.sp() lr = ocd.registers.lr() print(f"PC=0x{pc:08X} SP=0x{sp:08X} LR=0x{lr:08X}")
values = ocd.registers.read_many(["r0", "r1", "r2", "r3"]) for name, val in values.items(): print(f" {name} = 0x{val:08X}")
all_regs = ocd.registers.read_all() print(f"\n{len(all_regs)} registers available")
ocd.registers.write("r0", 0x42)
ocd.target.resume()Program flash
Section titled “Program flash”Write a firmware image to flash memory with automatic erase and verification.
import asynciofrom pathlib import Pathfrom openocd import Session
async def main(): async with Session.connect() as ocd: firmware = Path("build/firmware.bin")
# Program flash (erases affected sectors, writes, then verifies) await ocd.flash.write_image(firmware, erase=True, verify=True) print("Flash programming complete")
# Reset and run the new firmware await ocd.target.reset(mode="run")
asyncio.run(main())from pathlib import Pathfrom openocd import Session
with Session.connect_sync() as ocd: firmware = Path("build/firmware.bin")
ocd.flash.write_image(firmware, erase=True, verify=True) print("Flash programming complete")
ocd.target.reset(mode="run")SVD register decoding
Section titled “SVD register decoding”Load an SVD file to decode peripheral registers into named bitfields. This is especially useful for reading GPIO, timer, and peripheral configuration registers.
import asynciofrom pathlib import Pathfrom openocd import Session
async def main(): async with Session.connect() as ocd: await ocd.target.halt()
# Load the SVD file for your chip await ocd.svd.load(Path("STM32F103xx.svd"))
# List available peripherals peripherals = ocd.svd.list_peripherals() print(f"Peripherals: {', '.join(peripherals[:5])}...")
# Read and decode a specific register odr = await ocd.svd.read_register("GPIOA", "ODR") print(odr) # GPIOA.ODR @ 0x4001080C = 0x00000010 # [ 0] ODR0 = 0x0 # [ 1] ODR1 = 0x0 # ... # [ 4] ODR4 = 0x1 # ...
# Decode a value without reading hardware decoded = ocd.svd.decode("GPIOA", "CRL", 0x44444444) print(decoded)
await ocd.target.resume()
asyncio.run(main())from pathlib import Pathfrom openocd import Session
with Session.connect_sync() as ocd: ocd.target.halt()
ocd.svd.load(Path("STM32F103xx.svd"))
peripherals = ocd.svd.list_peripherals() print(f"Peripherals: {', '.join(peripherals[:5])}...")
odr = ocd.svd.read_register("GPIOA", "ODR") print(odr)
decoded = ocd.svd.decode("GPIOA", "CRL", 0x44444444) print(decoded)
ocd.target.resume()JTAG chain scan
Section titled “JTAG chain scan”Discover all TAPs (Test Access Ports) on the JTAG chain.
import asynciofrom openocd import Session
async def main(): async with Session.connect() as ocd: taps = await ocd.jtag.scan_chain() for tap in taps: print( f" {tap.name:<25s} IDCODE=0x{tap.idcode:08X} " f"IR={tap.ir_length} enabled={tap.enabled}" )
asyncio.run(main())from openocd import Session
with Session.connect_sync() as ocd: taps = ocd.jtag.scan_chain() for tap in taps: print( f" {tap.name:<25s} IDCODE=0x{tap.idcode:08X} " f"IR={tap.ir_length} enabled={tap.enabled}" )Error handling
Section titled “Error handling”Catch specific exceptions for different failure modes.
from openocd import ( Session, ConnectionError, TargetError, TargetNotHaltedError, TimeoutError,)
with Session.connect_sync() as ocd: try: ocd.target.halt() pc = ocd.registers.pc() print(f"PC = 0x{pc:08X}") except TargetNotHaltedError: print("Target must be halted to read registers") except TimeoutError: print("Operation timed out") except TargetError as e: print(f"Target error: {e}")See the Error Handling guide for the full exception hierarchy.
Spawning OpenOCD from Python
Section titled “Spawning OpenOCD from Python”Instead of starting OpenOCD manually, let the library manage it:
import asynciofrom openocd import Session
async def main(): config = "-f interface/cmsis-dap.cfg -f target/stm32f1x.cfg"
async with Session.start(config, timeout=15.0) as ocd: state = await ocd.target.state() print(f"Target: {state.name}, State: {state.state}")
# OpenOCD process stops when the context manager exits
asyncio.run(main())from openocd import Session
config = "-f interface/cmsis-dap.cfg -f target/stm32f1x.cfg"
with Session.start_sync(config, timeout=15.0) as ocd: state = ocd.target.state() print(f"Target: {state.name}, State: {state.state}")Next steps
Section titled “Next steps”- Session Lifecycle — connection management in depth
- Target Control — halt, resume, step, and reset
- Memory Operations — typed reads and writes at any width
- Register Access — CPU register manipulation
- Error Handling — exception hierarchy and recovery