Python API examples
Hello World example code
This example shows basic connection, loading a firmware binary, and some simple target control.
#!/usr/bin/env python3
from pyocd.core.helpers import ConnectHelper
from pyocd.flash.file_programmer import FileProgrammer
import time
import logging
logging.basicConfig(level=logging.INFO)
with ConnectHelper.session_with_chosen_probe() as session:
board = session.board
target = board.target
flash = target.memory_map.get_boot_memory()
# Load firmware into device.
FileProgrammer(session).program("my_firmware.bin")
# Reset
target.reset_and_halt()
# Read some registers.
print("pc: 0x%X" % target.read_core_register("pc"))
target.step()
print("pc: 0x%X" % target.read_core_register("pc"))
target.resume()
time.sleep(0.2)
target.halt()
print("pc: 0x%X" % target.read_core_register("pc"))
target.reset_and_halt()
print("pc: 0x%X" % target.read_core_register("pc"))
ELF files and breakpoints
Expanding on the above example, this code demonstrates reading a symbol address from an ELF file and setting a breakpoint. Then the target is reset and run until the breakpoint is hit.
#!/usr/bin/env python3
from pyocd.core.helpers import ConnectHelper
from pyocd.core.target import Target
from pyocd.debug.elf.symbols import ELFSymbolProvider
# Connect to the target.
with ConnectHelper.session_with_chosen_probe() as session:
target = session.target
# Set ELF file on target.
target.elf = "my_firmware.elf"
# Look up address of main().
provider = ELFSymbolProvider(target.elf)
addr = provider.get_symbol_value("main")
print("main() address: 0x%X" % addr)
# Set breakpoint.
target.set_breakpoint(addr)
# Reset and run.
target.reset()
# Wait until breakpoint is hit.
while target.get_state() != Target.State.HALTED:
pass
# Print PC.
pc = target.read_core_register("pc")
print("pc: 0x%X" % pc)
assert pc == addr & ~0x01 # mask off LSB
# Remove breakpoint.
target.remove_breakpoint()
Note that you currently need to manually remove a breakpoint in order to step or run over it.
Alternative ways to create a session
It’s important to understand that the ConnectHelper.session_with_chosen_probe()
method doesn’t
itself open the session for you. Instead, it’s using the session object as a context manager that
does this.
Here is an example where the with
statement is separated from the creation of the session.
# Connect to the target.
session = ConnectHelper.session_with_chosen_probe()
# Manually open the session. When the 'with' statement exits, the session is closed.
with session:
# ... control the target
This example demonstrates complete manual control of session opening and closing.
# Connect to the target.
session = ConnectHelper.session_with_chosen_probe()
# Manually open the session.
session.open()
# ... control the target
# Close the session and connection.
session.close()
In reality you might want to put the call to close()
in a finally
clause of an exception handler.
The example here shows how the auto_open
parameter can be used to achieve a combination of the
above approaches. When set to False, the session will not be opened upon entry into a with
statement. This allows using a with
statement to ensure the session is properly closed, but with
manual opening so you could, perhaps, further configure the session before it is opened.
# Here we set auto_open to False, so the 'with' statement won't open the session.
session = ConnectHelper.session_with_chosen_probe(auto_open=False)
# When the 'with' statement exits, the session is closed.
with session:
# ... modify the session
# Manually open the session.
session.open()
# ... control the target
Selecting a probe and configuring the target connection is done as follows:
# Connect to the target with some options.
session = ConnectHelper.session_with_chosen_probe(unique_id = "E6616407E3646B29", options = {"frequency": 4000000, "target_override": "nrf52840"})
with session:
# ...
More options can be found here.
Semihosting
For in-target tests it is sometimes convenient to use semihosting, e.g. write coverage data into the hosts file system.
To execute semihosting requests a wait_for_halt()
function must be implemented. If writing the profile data is
explicitly done at end of main()
, a breakpoint on return is also helpful. Implementation could be like this:
#!/usr/bin/env python3
from pyocd.core.helpers import ConnectHelper
from pyocd.core.target import Target
from pyocd.debug.elf.symbols import ELFSymbolProvider
from pyocd.flash.file_programmer import FileProgrammer
from pyocd.debug import semihost
import time
import traceback
import logging
logging.basicConfig(level=logging.INFO)
image_name = "profiling.elf"
def wait_for_halt(target, semihost):
go_on = True
while go_on:
state = target.get_state()
if state == Target.State.HALTED:
try:
# Handle semihosting
go_on = semihost.check_and_handle_semihost_request()
if go_on:
# target was halted due to semihosting request
target.resume()
except Exception as e:
print("semihost exception/resume------", e)
print(traceback.format_exc())
target.resume()
go_on = True
else:
time.sleep(0.01)
session = ConnectHelper.session_with_chosen_probe(unique_id = "E6616407E3646B29", options = {"frequency": 4000000,
"target_override": "nrf52840",
"enable_semihosting": True,
"semihost_use_syscalls": False})
with session:
target = session.target
target_context = target.get_target_context()
semihost_io_handler = semihost.InternalSemihostIOHandler()
semihost = semihost.SemihostAgent(target_context, io_handler=semihost_io_handler, console=semihost_io_handler)
# Load firmware into device.
FileProgrammer(session).program(image_name)
# Set ELF file on target.
target.elf = image_name
provider = ELFSymbolProvider(target.elf)
# Look up address of main().
addr = provider.get_symbol_value("main")
print("main() address: 0x%X" % addr)
# Set breakpoint.
print("set breakpoint to entry of main()")
target.set_breakpoint(addr)
target.reset_and_halt()
print("execute")
target.resume()
# Wait until breakpoint is hit.
wait_for_halt(target, semihost)
# Print PC.
pc = target.read_core_register("pc")
print(" pc: 0x%X" % pc)
assert pc == addr & ~0x01 # mask off LSB
target.remove_breakpoint(addr)
# set breakpoint to return address and execute til there
lr = target.read_core_register("lr")
print(" lr: 0x%X (return address)" % lr)
print("set breakpoint to return of main()")
target.set_breakpoint(lr)
print("execute")
target.resume()
wait_for_halt(target, semihost)
pc = target.read_core_register("pc")
print(" pc: 0x%X" % pc)
assert pc == lr & ~0x01 # mask off LSB
target.remove_breakpoint(lr)