API Documentation


PyOpenocdClient

class py_openocd_client.PyOpenocdClient(host: str = '127.0.0.1', port: int = 6666)

PyOpenocdClient is the main class which forms the interface of the py_openocd_client package. One instance of this class represents one TCL connection to a running OpenOCD process.

This class provides:

  • cmd() method to send any TCL command to OpenOCD and obtain the command result,

  • convenience methods (shortcuts) to issue some of the most common OpenOCD commands – halt(), resume(), read_memory(), get_reg(), …, etc.

Basic usage:

from py_openocd_client import PyOpenocdClient

ocd = PyOpenocdClient(host="localhost", port=6666)
ocd.connect()

# Now use the "ocd" instance to interact with OpenOCD:
ocd.reset_halt()
ocd.cmd("load_image path/to/your/program.elf")
ocd.resume()
# ...

# Disconnect when done
ocd.disconnect()

Usage as a context manager:

from py_openocd_client import PyOpenocdClient

# The context manager automatically establishes the connection.
# No need to call ocd.connect().
with PyOpenocdClient(host="localhost", port=6666) as ocd:

    # Now use the "ocd" instance to interact with OpenOCD:
    ocd.reset_halt()
    ocd.cmd("load_image path/to/your/program.elf")
    ocd.resume()
    # ...

    # The instance gets automatically disconnected at the end
    # of the "with" block. No need to call ocd.disconnect().
connect() None

Establish connection to the OpenOCD instance running on host and port specificed in the class constructor.

Raises OcdConnectionError:

  • if the connection fails,

  • if called on an already connected instance.

disconnect() None

Terminate the connection to the OpenOCD instance, if connected.

Note

Calling disconnect() on a non-connected instance is safe – it performs no operation and also does not raise any error.

reconnect() None

Terminate the current connection, if any, and establish a new one.

This is equivalent to calling disconnect() and then connect().

is_connected() bool

Determine if the instance is connected.

cmd(cmd: str, capture: bool = False, throw: bool = True, timeout: float | None = None) OcdCommandResult

Send a TCL command to OpenOCD, wait for its completion and return the command result. The result of the command is represented by OcdCommandResult.

cmd is the TCL command to execute, or possibly multiple TCL commands – a short TCL script.

capture determines whether to also obtain log entries produced by the command and return it as part of the command output. (Default: False)

throw determines whether to raise OcdCommandFailedError if the command fails. (Default: True)

timeout can be used to override the default timeout. If it is not specified, the default timeout will apply – see set_default_timeout().

If the command fails, OcdCommandFailedError is raised, unless suppresed by throw=False.

If the command timeout is exceeded while waiting for OpenOCD to provide the command result, OcdCommandTimeoutError is raised and the connection is re-established (reconnected).

If a connection error occurs during the command execution, OcdConnectionError is raised and the connection is terminated.

In the unlikely event OpenOCD responds unexpectedly (provides its response in an unexpected format), OcdInvalidResponseError is raised.

Note

Other convenience methods of this class (halt(), resume(), etc.) use internally the cmd() method, and therefore can also raise the above errors.

Basic usage:

with PyOpenocdClient("localhost", 6666) as ocd:

    # The simplest usage: Just execute a command and don't care
    # about its output. Should the command fail or not finish within
    # the timeout, an error will be raised.
    ocd.cmd("halt")

    # Second use case: Execute a command and obtain its textual output:
    result = ocd.cmd("version")
    print(f"Output of 'version' command was: {result.out}")

Command errors can be handled this way:

with PyOpenocdClient("localhost", 6666) as ocd:

    try:
        ocd.cmd("load_image path/to/your/program.elf", timeout=10.0)
    except OcdCommandTimeoutError as e:
        print(f"Image loading timed out - exceeded {e.timeout} seconds")
    except OcdCommandFailedError as e:
        print(
            "Image loading failed. "
            f"Return code: {e.result.retcode}. "
            f"OpenOCD's output: {e.result.out}"
        )
    else:
        print("Image loading successful.")

Note

The cmd() method wraps the user-provided command with additional TCL commands (like catch and return), and the resulting complex command is then sent to OpenOCD. This is needed so that both the return code and the textual output of the command can be obtained.

set_default_timeout(timeout: float) None

Set the default timeout for all commands.

Note that some methods of this class allow to explicitly override the default timeout on per-command basis.

halt() None

Halt the currently selected target by sending the halt command.

resume(new_pc: int | None = None) None

Resume the currently selected target by sending the resume command.

Optionally, a differet resume address can be set by the new_pc argument.

step(new_pc: int | None = None) None

Perform single-step on the currently selected target by sending the step command.

Optionally, a differet resume address can be set by the new_pc argument.

reset_halt() None

Reset and halt all targets by sending the command reset halt.

reset_init() None

Reset and halt all targets by sending the command reset init.

reset_run() None

Reset and resume all targets by sending the command reset run.

curstate() str

Determinte the state of the currently selected target via the <target_name> curstate command. Return the state as a string.

is_halted() bool

Determine if the currently selected target is halted.

is_running() bool

Determine if the currently selected target is running.

get_reg(reg_name: str, force: bool = False) int

Read the value of a target’s register. This is a convenience wrapper over the OpenOCD’s get_reg command.

reg_name is the name of the register to read.

If force is set to true, the value of the register is read directly from the target, as opposed to reading it from OpenOCD’s internal cache.

set_reg(reg_name: str, reg_value: int, force: bool = False) None

Write a new value to a target’s register. This is a convenience wraper over the OpenOCD’s set_reg command.

reg_name is the name of the register to which the reg_value shall be written.

If force is set to true, the new value is written to the register immediately (as opposed to keeping it in the OpenOCD’s internal cache).

read_memory(addr: int, bit_width: int, count: int = 1, phys: bool = False, timeout: float | None = None) List[int]

Read data from memory and return them as a list of integers. This is a convenience wrapper over the OpenOCD’s read_memory command.

addr is the memory address to read from – the address of the first read data item.

bit_width is the size of the data transfer (in bits). Allowed values are 8, 16, 32 and 64.

count is the number of data items to read. Default is 1. If count is higher than 1, the next values are read from the subsequent memory addresses (address incremented by bit_width / 8).

phys is a boolean flag that makes OpenOCD use physical addressing (as opposed to the default virtual addressing). This argument is only meaningful for targets that actually use virtual memory.

timeout can be optionally used to override the default timeout.

write_memory(addr: int, bit_width: int, values: List[int], phys: bool = False, timeout: float | None = None) None

Write data to memory. This is a convenience wrapper over the OpenOCD’s write_memory command.

addr is the memory address to write the data to – the address of the first written data item.

bit_width is the size of the data transfer (in bits). Allowed values are 8, 16, 32 and 64.

values is a list of integers – list of the values to write. The first item is written to the address addr and the next values are written to the next memory words (whose addresses increment by bit_width / 8).

phys is a boolean flag that makes OpenOCD use physical addressing (as opposed to the default virtual addressing). This argument is only meaningful for targets that actually use virtual memory.

timeout can optionally be used to override the default timeout.

list_bp() List[BpInfo]

Obtain a list of the currently set breakpoints. Each breakpoint is represented by an instance of py_openocd_client.BpInfo.

This is a convenience wrapper over the OpenOCD’s bp command.

Warning

Only HW and SW breakpoints are supported by list_bp() at the moment. Context and hybrid breakpoints are not supported.

You can still set and use these less common types of breakpoints manually (by cmd()). However, list_bp() will not be able to recognize them.

add_bp(addr: int, size: int, hw: bool = False) None

Add one breakpoint at address addr of the given size.

If hw is True, hardware breakpoint will be used instead of software (default: False).

This is a convenience wrapper over the OpenOCD’s command bp <addr> <size> [hw].

remove_bp(addr: int) None

Remove breakpoint located at given address addr.

This is a convenience wrapper over the OpenOCD’s command rbp <addr>.

remove_all_bp() None

Remove all breakpoints.

This is a convenience wrapper over the OpenOCD’s command rbp all.

list_wp() List[WpInfo]

Obtain a list of the currently set watchpoints. Each watchpoint is represented by an instance of py_openocd_client.WpInfo.

This is a convenience wrapper over the OpenOCD’s wp command.

add_wp(addr: int, size: int, wp_type: WpType = WpType.ACCESS) None

Add a single watchpoint to address addr of the given size.

Type of the watchpoint can be set by wp_type and the default is WpType.ACCESS.

This is a convenience wrapper over the OpenOCD’s command wp <addr> <size> <r|w|a>.

remove_wp(addr: int) None

Remove watchpoint located at given address addr.

This is a convenience wrapper over the OpenOCD’s command rwp <addr>.

remove_all_wp() None

Remove all breakpoints.

This is a convenience wrapper over the OpenOCD’s command rwp all.

echo(msg: str) None

Print a text message on the OpenOCD’s output.

This is useful if the user wishses to print extra text to the OpenOCD log, for example to aid with subsequent log analysis.

version() str

Return the OpenOCD version string, produced by the version command.

version_tuple() Tuple[int, int, int]

Return the OpenOCD version as a tuple containing three items – major, minor and patch version.

This is useful for OpenOCD version checks:

if ocd.version_tuple() >= (0, 12, 0):
    # Some code that relies on OpenOCD version at least 0.12.0
    # ...
else:
    raise RuntimeError("Sorry, OpenOCD 0.12.0 or newer is required.")
target_names() List[str]

Obtain a list of all target names.

OpenOCD’s command target names is used.

This method is useful when there is more than one target in the debug session.

select_target(target_name: str) None

Select a specific target, identified by its target_name.

OpenOCD’s command targets <target_name> is used.

This method is useful when there is more than one target in the debug session.

set_poll(enable_polling: bool) None

Enable or disable periodic OpenOCD’s polling of the target state.

OpenOCD’s commands poll on or poll off are used.

exit() None

Alias for disconnect().

shutdown() None

Shut down the OpenOCD process by sending the shutdown command to it. PyOpenocd client also gets immediately disconnected from OpenOCD.

raw_cmd(raw_cmd: str, timeout: float | None = None) str

Low-level method that sends a TCL command to OpenOCD in its “raw” form – exactly as the user has entered it, without wrapping it into any additional TCL commands.

After the command completes, its textual output is returned as a simple string. Return code of the command is not obtained.

Warning

The raw_cmd() method does not have the ability to recognize whether the TCL command succeeded or failed. That’s because the return code of the command cannot be obtained.

For that reason, the method cmd() should always be preferred over raw_cmd().

raw_cmd is the raw TCL command to execute (or possibly multiple TCL commands – a short TCL script).

timeout can be used to override the timeout for this command. If not specified, the default timeout will apply – see set_default_timeout().

If the command timeout is exceeded while waiting for OpenOCD to provide the command result, OcdCommandTimeoutError is raised and the connection is re-established.

If connection error occurs during the command execution, OcdConnectionError is raised and the connection is terminated.


Command result

class py_openocd_client.OcdCommandResult(retcode: int, cmd: str, raw_cmd: str, out: str)

This class represets result of an executed and completed TCL command.

An instance of this class is returned by PyOpenocdClient.cmd().

retcode: int

Return code of the command.

Zero value means a successfully completed command. Non-zero value means a failed command (an error during command execution).

cmd: str

The original command that the user requested to exeucte.

raw_cmd: str

The actual “raw” command that was sent by PyOpenocdClient to OpenOCD for execution.

This is typically the user-entered command (cmd) wrapped in other TCL commands so that PyOpenocdClient is able to obtain both the output and the return code of the user-entered command.

out: str

Textual output of the command.


Exceptions

exception py_openocd_client.OcdCommandFailedError(result: OcdCommandResult)

Exception which denotes that a TCL command failed; that is, the command ended with a non-zero return code.

property result: OcdCommandResult

Result of the command – an instance of py_openocd_client.OcdCommandResult. It allows to access the error code and the command output.

Example of use:

try:
    res = ocd.cmd("some command")
    print(f"Command succeeded. Output: {res.out}")
except OcdCommandFailedError as e:
    print(f"Command failed with error code {e.result.retcode}. "
          f"Output: {e.result.out}")
exception py_openocd_client.OcdConnectionError

Exception that denotes connection errors, for instance:

  • connection to OpenOCD could be established

  • OpenOCD closed the connection

  • OpenOCD responded unexpectedly (protocol broken)

Note

If this exception is raised, the connection is automatically terminated.

If the user wishes to continue issuing more commands, new connection needs to be established manually (by calling connect() or reconnect()).

exception py_openocd_client.OcdCommandTimeoutError(msg: str, raw_cmd: str, timeout: float)

Exception that is raised whenever a TCL command does not complete within the configured timeout.

If this exception occurs, it is advisable to:

  • investigate why the command execution takes long time, and/or

  • re-issue the command with a larger timeout.

Note

If this exception occurs, then reconnection is automatically performed: the current connection to OpenOCD is closed and a new one established.

property raw_cmd: str

Raw command which did not complete within the timeout.

property timeout: float

Timeout value that got exceeded.

exception py_openocd_client.OcdInvalidResponseError(msg: str, raw_cmd: str, out: str)

Exception which means that a TCL command produced invalid (unexpected) output. That is, PyOpenocdClient could not parse and/or interpret that command output.

property raw_cmd: str

Raw command that produced the invalid response.

property out: str

The actual invalid response of the command.

exception py_openocd_client.OcdBaseException

Base exception class for all exceptions of PyOpenocdClient.


Other data types

class py_openocd_client.BpInfo(addr: int, size: int, bp_type: BpType, orig_instr: int | None)

Information about a single breakpoint.

addr: int

Address of the breakpoint.

size: int

Size of the breakpoint.

bp_type: BpType

Breakpoint type.

orig_instr: int | None

Original instruction. Only relevant to SW breakpoints.

class py_openocd_client.WpInfo(addr: int, size: int, wp_type: WpType, value: int, mask: int)

Information about a single watchpoint.

addr: int

Address of the watchpoint.

size: int

Size of the watchpoint.

wp_type: WpType

Watchpoint type.

value: int

Data value to compare.

mask: int

Mask for data value comparison.

Only the data bits whose corresponding mask bit is 0 are compared against the value.

Watchpoint whose mask is “all ones” does not perform any data comparison.

enum py_openocd_client.BpType(value)

Breakpoint type (enum).

Valid values are as follows:

HW = <BpType.HW: 'hw'>
SW = <BpType.SW: 'sw'>
CONTEXT = <BpType.CONTEXT: 'context'>
HYBRID = <BpType.HYBRID: 'hybrid'>
enum py_openocd_client.WpType(value)

Watchpoint type (enum).

Valid values are as follows:

READ = <WpType.READ: 'r'>
WRITE = <WpType.WRITE: 'w'>
ACCESS = <WpType.ACCESS: 'a'>