Breakpoints and Watchpoints
The BreakpointManager subsystem wraps OpenOCD’s bp, rbp, wp, and rwp commands to manage breakpoints that pause execution at a specific instruction address, and watchpoints that trigger on data memory access.
Access it through the session:
# Asyncsession.breakpoints
# Syncsync_session.breakpointsHardware vs. software breakpoints
Section titled “Hardware vs. software breakpoints”Breakpoints come in two flavors, each with different tradeoffs:
Software breakpoints replace the instruction at the target address with a special breakpoint instruction (e.g. BKPT on ARM). When the CPU executes that address, it traps into debug mode. The original instruction is restored transparently. Software breakpoints are plentiful but require writable memory — they do not work in flash unless the debugger patches flash.
Hardware breakpoints use dedicated comparator registers built into the CPU core (e.g. the Flash Patch and Breakpoint unit on Cortex-M). They work on any memory region including flash, but the number available is limited — typically 4 to 8 on Cortex-M devices.
Setting breakpoints
Section titled “Setting breakpoints”add(address, length=2, hw=False) sets a breakpoint at the given instruction address.
The length parameter indicates the instruction size:
2for Thumb instructions (16-bit, the default on Cortex-M)4for ARM instructions (32-bit)
import asynciofrom openocd import Session
async def main(): async with await Session.connect() as session: # Software breakpoint on a Thumb instruction await session.breakpoints.add(0x0800_1234, length=2)
# Hardware breakpoint on an ARM instruction await session.breakpoints.add(0x0800_5678, length=4, hw=True)
asyncio.run(main())from openocd import Session
with Session.connect_sync() as session: # Software breakpoint on a Thumb instruction session.breakpoints.add(0x0800_1234, length=2)
# Hardware breakpoint on an ARM instruction session.breakpoints.add(0x0800_5678, length=4, hw=True)Removing breakpoints
Section titled “Removing breakpoints”remove(address) removes the breakpoint at the specified address.
async with await Session.connect() as session: await session.breakpoints.add(0x0800_1234) # ... debug ... await session.breakpoints.remove(0x0800_1234)with Session.connect_sync() as session: session.breakpoints.add(0x0800_1234) # ... debug ... session.breakpoints.remove(0x0800_1234)Listing breakpoints
Section titled “Listing breakpoints”list() returns all active breakpoints as a list of Breakpoint dataclasses.
async with await Session.connect() as session: await session.breakpoints.add(0x0800_1234) await session.breakpoints.add(0x0800_5678, hw=True)
bps = await session.breakpoints.list() for bp in bps: print(f"BP #{bp.number}: 0x{bp.address:08X} " f"type={bp.type} len={bp.length} enabled={bp.enabled}")with Session.connect_sync() as session: session.breakpoints.add(0x0800_1234) session.breakpoints.add(0x0800_5678, hw=True)
bps = session.breakpoints.list() for bp in bps: print(f"BP #{bp.number}: 0x{bp.address:08X} " f"type={bp.type} len={bp.length} enabled={bp.enabled}")Data watchpoints
Section titled “Data watchpoints”Watchpoints monitor data memory access rather than instruction execution. They trigger when the CPU reads from, writes to, or accesses a specific address range.
Setting a watchpoint
Section titled “Setting a watchpoint”add_watchpoint(address, length, access="rw") creates a data watchpoint.
The access parameter controls which operations trigger the watchpoint:
"r"— read access only"w"— write access only"rw"— any access (read or write)
async with await Session.connect() as session: # Break on any write to a 4-byte variable await session.breakpoints.add_watchpoint( address=0x2000_0100, length=4, access="w" )
# Break on any access to a buffer await session.breakpoints.add_watchpoint( address=0x2000_0200, length=16, access="rw" )with Session.connect_sync() as session: session.breakpoints.add_watchpoint( address=0x2000_0100, length=4, access="w" ) session.breakpoints.add_watchpoint( address=0x2000_0200, length=16, access="rw" )Removing a watchpoint
Section titled “Removing a watchpoint”remove_watchpoint(address) removes the watchpoint at the given address.
await session.breakpoints.remove_watchpoint(0x2000_0100)Listing watchpoints
Section titled “Listing watchpoints”list_watchpoints() returns all active watchpoints.
async with await Session.connect() as session: await session.breakpoints.add_watchpoint(0x2000_0100, 4, "w")
wps = await session.breakpoints.list_watchpoints() for wp in wps: print(f"WP #{wp.number}: 0x{wp.address:08X} " f"len={wp.length} access={wp.access}")with Session.connect_sync() as session: session.breakpoints.add_watchpoint(0x2000_0100, 4, "w")
wps = session.breakpoints.list_watchpoints() for wp in wps: print(f"WP #{wp.number}: 0x{wp.address:08X} " f"len={wp.length} access={wp.access}")Data types
Section titled “Data types”Breakpoint
Section titled “Breakpoint”| Field | Type | Description |
|---|---|---|
number | int | Breakpoint index |
type | Literal["hw", "sw"] | Hardware or software breakpoint |
address | int | Instruction address |
length | int | Instruction length in bytes (2 = Thumb, 4 = ARM) |
enabled | bool | Whether the breakpoint is active |
Watchpoint
Section titled “Watchpoint”| Field | Type | Description |
|---|---|---|
number | int | Watchpoint index |
address | int | Watched memory address |
length | int | Size of watched region in bytes |
access | Literal["r", "w", "rw"] | Access type that triggers the watchpoint |
Error handling
Section titled “Error handling”Breakpoint and watchpoint operations raise BreakpointError (a subclass of OpenOCDError) when OpenOCD reports a failure.
from openocd.breakpoints import BreakpointError
try: session.breakpoints.add(0x0800_1234, hw=True)except BreakpointError as e: print(f"Could not set breakpoint: {e}")Common failure causes:
- No hardware breakpoint comparators available (reduce the number of HW breakpoints)
- Target not halted when attempting to set a software breakpoint
- Invalid address or length
Method reference
Section titled “Method reference”| Method | Return Type | Description |
|---|---|---|
add(address, length=2, hw=False) | None | Set a breakpoint |
remove(address) | None | Remove a breakpoint |
list() | list[Breakpoint] | List active breakpoints |
add_watchpoint(address, length, access="rw") | None | Set a data watchpoint |
remove_watchpoint(address) | None | Remove a watchpoint |
list_watchpoints() | list[Watchpoint] | List active watchpoints |