Quickstart

Configuring OpenOCD for TCL connections

OpenOCD by default listens for TCL connections on TCP port 6666 on the local machine (127.0.0.1). This is typically sufficient for common use cases and no further confguration is necessary.

If needed, OpenOCD command tcl port can be used to change the port number (e.g. tcl port 1234).

To make OpenOCD accessible from remote network machines, not just from the localhost, use OpenOCD command bindto (e.g. bindto 0.0.0.0). Note that the TCL connection to OpenOCD is not encrypted nor authenticated, and for that reason it should only be used within trusted network environments.

Basic usage of PyOpenocdClient

One instance of class PyOpenocdClient represents one TCL connection to a running OpenOCD program.

PyOpenocdClient can be used in two ways:

  • Manually: Make an instance of this class and call connect() and disconnect() methods explicitly.

  • As a context manager (in with block): In this case the connection is established and closed automatically.

Both these approaches are shown below.

from py_openocd_client import PyOpenocdClient

# Manual use of PyOpenocdClient:
# connect() and disconnect() needs to be called.

ocd = PyOpenocdClient(host="some_hostname", port=1234)  # default is localhost:6666
ocd.connect()

# Now interact with OpenOCD. For example:
ocd.reset_halt()
ocd.cmd("load_image path/to/program.elf")
ocd.resume()
# ...

ocd.disconnect()
from py_openocd_client import PyOpenocdClient

# Use PyOpenocdClient as a context manager:
# The connection is established and closed automatically.

with PyOpenocdClient(host="some_hostname", port=1234) as ocd:

    # Now interact with OpenOCD. For example:
    ocd.reset_halt()
    ocd.cmd("load_image path/to/program.elf")
    ocd.resume()
    # ...

Executing TCL commands

Any TCL command can be sent to OpenOCD via the cmd() method.

PyOpenocdClient handles the outcome of the command (success or failure) this way:

from py_openocd_client import PyOpenocdClient, OcdCommandFailedError

with PyOpenocdClient(host="localhost", port=6666) as ocd:

    # Execute a single command, don't care about its output:
    ocd.cmd("poll off")

    # Execute a command and obtain its textual output:
    result = ocd.cmd("version")
    print(f"OpenOCD version is: {result.out}")

    # Execute a command and handle its possible failure:
    try:
        result = ocd.cmd("load_image path/to/program.elf")
    except OcdCommandFailedError as e:
        print("Image loading failed. "
              f"Command error code: {e.result.retcode}. "
              f"Command message: {e.result.out}.")
    else:
        print(f"Image loading successful. Command message: {result.out}")

Convenience methods for common commands

For easier use, PyOpenocdClient provides convenience methods (shortcuts) for frequently used OpenOCD commands. These methods execute the given command and parse the command output (if applicable) so that the command result is returned in the form of native Python data types.

Therefore it is not necessary to use the cmd() and then parse the command output manually.

Some of the convenience methods are shown in the example below. Please refer to the API Documentation for the full list.

from py_openocd_client import PyOpenocdClient

with PyOpenocdClient(host="localhost", port=6666) as ocd:

    # Examples of several of the convenience methods:

    # Read and write processor registers
    pc_value = ocd.get_reg("pc")  # Returns integer value of the register
    print(f"The value of the PC register is: {hex(pc_value)}")

    ocd.set_reg("gp", 0x1234)

    # Read and write memory
    mem_data = ocd.read_memory(0x1000, 32, 8)  # Returns a list of integers
    print(f"Eight 32-bit words starting at memory address 0x1000: {mem_data}")

    ocd.write_memory(0x2000, 16, [0x1234, 0x5678, 0xabcd])

    # Place or remove a breakpoint
    ocd.add_bp(0x2001000, 4, hw=True)
    ocd.remove_bp(0x2001000)

    # Halting, resuming and reset
    ocd.resume()
    ocd.halt()
    ocd.reset_halt()
    ocd.reset_run()

    # Checking target state
    print(f"The target state is {ocd.curstate()}")

    if ocd.is_halted():
        print("The target is halted")

    # Logging
    ocd.echo("A custom message to show in OpenOCD log")

    # Terminating OpenOCD
    ocd.shutdown()

Handling command timeouts

If execution of a command takes too long and a configured timeout is exceeded, OcdCommandTimeoutError gets raised.

The global default timeout – applicable to all commands sent by PyOpenocdClient – can be changed by set_default_timeout().

It is also possible to specify a timeout for an individual command which then takes precedence over the global timeout. That is done via the timeout parameter, available on certain methods.

from py_openocd_client import PyOpenocdClient

with PyOpenocdClient(host="localhost", port=6666) as ocd:

    # All commands from now on will have a timeout of 10 seconds:
    ocd.set_default_timeout(10.0)

    # ...

    # Override the default timeout for an individual command:
    ocd.cmd("load_image big_program.elf", timeout=30.0)