Introduction to the API
Using pyOCD’s Python API, you have extreme flexibility and precise control, and can do anything
SWD allows, at the expense of more complexity compared to
pyocd commander. Using pyOCD like this is
particularly useful for situations where other debuggers become ineffective, such as device and
board bringup, or automated testing.
This document assumes familiarity with the Arm CoreSight debug architecture.
See the architecture documentation for an overview of the classes and how they are connected.
pyOCD provides a handful of helper routines that make it very easy to enumerate and connect to
available debug probes. These routines are all available as static methods on the
ConnectHelper.session_with_chosen_probe() is the primary connection helper. This method returns
Session object, or None. If only a single probe is available, a new session for that
probe is returned immediately. But if there are multiple probes available, then by default, it will
present a simple console UI that lets the user select which probe they want to use. Other options
allow automatically picking the first available probe.
One of the most useful parameters for
unique_id. Pass whole or
part of a probe’s unique ID (aka serial number) to programmatically select a specific probe.
Session options may be passed to
session_with_chosen_probe() in two ways. The
parameter accepts a dictionary of session options. Or, you may pass options as keyword parameters.
The two methods may be combined.
The DP is controlled through an instance of the
DebugPort class (in
DebugPort object via the ‘dp’ attribute of the target instance, i.e.,
DebugPort class has
write_reg(addr, data) methods. ‘addr’ must be an
integer in the set (0x0, 0x4, 0x8, 0xC).
x = session.board.target.dp.read_reg(0x4) session.board.target.dp.write_reg(0x8, 0x1)
For completeness, the DebugPort class also has
writeAP(addr, data) methods. They work as described below, except that the
require the APSEL in the address (i.e., 0x010000fc to read ID of APSEL=1). The AP will automatically be
CoreSight APs are represented with
AccessPort classes defined in
pyocd.coresight.ap. These include
MEM_AP subclass and
AHB_AP subclass of that.
To get the AP objects you can use the ‘aps’ attribute of the
DebugPort. This attribute is a dict
with the keys being the APSEL number and values being AccessPort instances. For instance, use
session.board.target.aps to get the AP with APSEL=1, assuming it exists (if not, you’ll get an
AccessPort also has
write_reg(addr, data) methods. For these methods,
an integer of the register offset. Note that you do not need to include the APSEL in the address, and
you do not need to modify the DP’s SELECT register prior to accessing AP registers. The AP will
automatically be selected in the DP as required.
AHB_AP class has the memory access methods that are available on
the target, but the access is, of course, performed through that specific AP. This is particularly
useful for multicore devices or Cortex-A class devices.
Example showing access of the proprietary MDM-AP of NXP Kinetis MCUs:
mdm_ap = session.board.target.dp.aps idr = mdm_ap.read_reg(0xfc) # Read IDR. mdm_ap.write_reg(0x4, 0x1)
To control reset, there are several options.
DebugPort has methods for driving the hardware reset signal:
DebugPort.reset(), asks the debug probe to perform a hardware reset of the target.
DebugPort.assert_reset(asserted)to directly control the nRESET signal. Pass True to drive nRESET low, False to drive high.
A wider range of reset options is provided by these
Target.reset(reset_type=None). Normally performs a software reset unless the optional parameter is set to False.
Target.reset_and_halt(reset_type=None)to perform a halting reset. Again, the reset defaults to software but may be set to hardware.
reset_type parameter on the
Target reset methods can be set to one of the
ResetType.HW: Hardware reset using the nRESET signal.
ResetType.SW: Uses the core’s default software reset method.
ResetType.SW_SYSRESETREQ: Software reset using SYSRESETREQ, which usually resets the entire system on most MCUs.
ResetType.SW_VECTRESET: Software reset using VECTRESET, only available on v7-M targets. This resets only the core itself. If requested on non-v7-M targets, it will fall back to
ResetType.SW_EMULATED: Restores the core to reset conditions by writing registers. However, this will not trigger a reset vector catch.
CortexM objects have
default_software_reset_type properties that
let you control the overall default reset type (any one of the
ResetType enums), as well as the
ResetType.SW is selected, respectively.
Another option for performing a halting reset is by setting vector catch with the target’s
method, then using a normal reset. This has the benefit of always halting at reset, if you leave the
vector catch enabled.
Example timed reset using the DP:
import time dp = session.board.target.dp # Timed reset. dp.assert_reset(True) time.sleep(1.0) dp.assert_reset(False)
You are encouraged to look through the code to see what additional functionality is available. The most interesting places to look at are:
- pyocd.core.target: defines Target class, which is the main API.
- pyocd.core.coresight_target: Represents the chip as a whole, provides access to DP and APs, as well as each of the cores.
- pyocd.coresight.cortex_m: CortexM class to control a core, implements Target API and adds some stuff.
- pyocd.flash.loader: high level flash programming of raw binary data.
- pyocd.flash.eraser: high level flash erasing.
- pyocd.flash.file_programmer: high level file programming.
- pyocd.flash.flash: low level flash programming API in the @ref pyocd.flash.flash.Flash “Flash”
class. Each flash memory region has a @ref pyocd.flash.flash.Flash “Flash” class instance
associated with it, accessible from the
flashproperty on the region. To get the boot flash memory region, call
flashattribute of this region then returns the boot flash memory’s @ref pyocd.flash.flash.Flash “Flash” instance.