Skip to content

Commit

Permalink
[openocd] Add support for custom OpenOCD path
Browse files Browse the repository at this point in the history
Based on discussion #845

Raspberry Pi Pico provides its own version of OpenOCD
which can be used with Raspberry Pi Picoprobe.

Assuming you have RPi Pico stuff stored under ~/projects/pico/...:

 1. Build and install OpenOCD

  cd ~/projects/pico
  git clone https://github.com/raspberrypi/openocd.git
  cd openocd
  ./bootstrap
  mkdir build
  cd build
  ../configure --prefix=$(realpath ../install)
  make install

 2. Use it in your build terminal

   export MODM_OPENOCD_BINARY=$HOME/projects/pico/openocd/install/bin/openocd
   scons program

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
╭────────────── build/scons-release/pico-blinky.elf
╰───OpenOCD───> rp2040
Open On-Chip Debugger 0.11.0-g4f2ae61 (2022-04-12-12:01)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'swd'
Info : Hardware thread awareness created
Info : Hardware thread awareness created
Info : RP2040 Flash Bank Command
Info : clock speed 5000 kHz
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x00000001
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x10000001
Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints
Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
** Programming Started **
Info : RP2040 B0 Flash Probe: 2097152 bytes @10000000, in 512 sectors

target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
Info : Writing 4096 bytes starting at 0x0
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
** Programming Finished **
** Verify Started **
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0000012a msp: 0x20041f00
** Verified OK **
shutdown command invoked
scons: done building targets
  • Loading branch information
cocasema committed Apr 12, 2022
1 parent ec18352 commit 0b296c5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 25 deletions.
48 changes: 48 additions & 0 deletions src/modm/board/rp_pico/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,56 @@ See https://www.raspberrypi.com/products/raspberry-pi-pico
## Programming
### UF2
The RP2040 ships with a [UF2 bootloader in ROM](https://github.com/microsoft/uf2).
To upload your application, connect the RP2040 via USB, convert the ELF to UF2
format by calling `scons uf2` or `make uf2` and copy the generated `.uf2` file
to the mounted virtual disk.
### OpenOCD
Another option is to use Picoprobe and custom version of OpenOCD provided by RPi.
You would need to build and program one of the boards with Picoprobe firmware,
configure and build RPi OpenOCD, and connect the boards via SWD.
Wiring diagram and detailed description is available in [Pico Documentation](https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf#Appendix%20A:%20Using%20Picoprobe).
The how-to shows steps for building and installing openocd into your the system,
but if you still want to be able to work with other boards, this can be easily avoided,
using the updated instructions:
```
$ cd ~/pico
$ sudo apt install automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-
dev
$ git clone https://github.com/raspberrypi/openocd.git --branch rp2040 --depth=1 --no-single
-branch
$ cd openocd
$ ./bootstrap
$ mkdir build
$ cd build
$ ../configure --enable-picoprobe --prefix=$(realpath ../install)
$ make -j4
$ make install
```
[Additional steps needed](https://forums.raspberrypi.com/viewtopic.php?t=312867) to get access to the device from a non-privileged user:
Edit (or create) /etc/udev/rules.d/60-openocd.rules file, and append these lines to it:
```
# Raspberry Pi Picoprobe
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess"
```
Once you have both of your Pico boards connected according to the wiring diagram, you can run
`scons program` to program the dev board:
```
export MODM_OPENOCD_BINARY=$HOME/pico/openocd/install/bin/openocd
scons program
```
"""

def prepare(module, options):
Expand All @@ -49,3 +94,6 @@ def build(env):
env.template("../board.cpp.in", "board.cpp")
env.copy('.')

env.outbasepath = "modm/openocd/modm/board/"
env.copy(repopath("tools/openocd/modm/rp2040_picoprobe.cfg"), "rp2040_picoprobe.cfg")
env.collect(":build:openocd.source", "modm/board/rp2040_picoprobe.cfg")
4 changes: 4 additions & 0 deletions tools/build_script_generator/scons/resources/SConscript.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#!/usr/bin/env python3

from os.path import join, abspath, realpath, dirname
from os import environ
import shutil
Import("env")

Expand Down Expand Up @@ -128,6 +129,9 @@ env["CONFIG_AVRDUDE_OPTIONS"] = "{{ avrdude_options }}"
env["CONFIG_AVRDUDE_BAUDRATE"] = "{{ avrdude_baudrate }}"
%% endif
%% elif core.startswith("cortex-m")
modm_openocd_binary = environ.get("MODM_OPENOCD_BINARY")
if modm_openocd_binary:
env.Append(MODM_OPENOCD_BINARY = modm_openocd_binary)
env.Append(MODM_OPENOCD_CONFIGFILES = "$BASEPATH/modm/openocd.cfg")
env.Append(MODM_OPENOCD_GDBINIT = "$BASEPATH/modm/openocd_gdbinit")
env.Append(MODM_GDBINIT = "$BASEPATH/modm/gdbinit")
Expand Down
33 changes: 16 additions & 17 deletions tools/build_script_generator/scons/site_tools/openocd.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@
# -----------------------------------------------------------------------------
def debug_openocd(env, source, alias="debug_openocd"):
def call_debug_openocd(target, source, env):
config_openocd = env.Listify(env.get("MODM_OPENOCD_CONFIGFILES", []))
config_searchdirs = env.Listify(env.get("MODM_OPENOCD_SEARCHDIRS", []))
backend = OpenOcdBackend(config=map(env.subst, config_openocd),
search=map(env.subst, config_searchdirs))
openocd_args = _prepare_openocd_args(env)
backend = OpenOcdBackend(**openocd_args)
config = env.Listify(env.get("MODM_OPENOCD_GDBINIT", []))
config += env.Listify(env.get("MODM_GDBINIT", []))
commands = env.Listify(env.get("MODM_GDB_COMMANDS", []))
Expand All @@ -42,37 +40,38 @@ def call_debug_openocd(target, source, env):
# -----------------------------------------------------------------------------
def program_openocd(env, source, alias="program_openocd"):
def call_program_openocd(target, source, env):
config = env.Listify(env.get("MODM_OPENOCD_CONFIGFILES", []))
searchdir = env.Listify(env.get("MODM_OPENOCD_SEARCHDIRS", []))
openocd.program(source=str(source[0]),
config=map(env.subst, config),
search=map(env.subst, searchdir))
openocd_args = _prepare_openocd_args(env)
openocd.program(source=str(source[0]), **openocd_args)

action = Action(call_program_openocd, cmdstr="$PROGRAM_OPENOCD_COMSTR")
return env.AlwaysBuild(env.Alias(alias, source, action))

# -----------------------------------------------------------------------------
def reset_openocd(env, alias="reset_openocd"):
def call_reset_openocd(target, source, env):
config = env.Listify(env.get("MODM_OPENOCD_CONFIGFILES", []))
searchdir = env.Listify(env.get("MODM_OPENOCD_SEARCHDIRS", []))
openocd.reset(config=map(env.subst, config),
search=map(env.subst, searchdir))
openocd_args = _prepare_openocd_args(env)
openocd.reset(**openocd_args)

action = Action(call_reset_openocd, cmdstr="$RESET_OPENOCD_COMSTR")
return env.AlwaysBuild(env.Alias(alias, '', action))

# -----------------------------------------------------------------------------
def run_openocd(env, alias="run_openocd"):
def call_run_openocd(target, source, env):
config = env.Listify(env.get("MODM_OPENOCD_CONFIGFILES", []))
searchdir = env.Listify(env.get("MODM_OPENOCD_SEARCHDIRS", []))
openocd.call(config=map(env.subst, config),
search=map(env.subst, searchdir), verbose=True)
openocd_args = _prepare_openocd_args(env)
openocd.call(verbose=True, **openocd_args)

action = Action(call_run_openocd, cmdstr="$RUN_OPENOCD_COMSTR")
return env.AlwaysBuild(env.Alias(alias, '', action))

# -----------------------------------------------------------------------------
def _prepare_openocd_args(env):
return {
"binary": env.subst(env.get("MODM_OPENOCD_BINARY", "openocd")),
"config": map(env.subst, env.Listify(env.get("MODM_OPENOCD_CONFIGFILES", []))),
"search": map(env.subst, env.Listify(env.get("MODM_OPENOCD_SEARCHDIRS", []))),
}

# -----------------------------------------------------------------------------
def generate(env, **kw):
env.AddMethod(program_openocd, "ProgramOpenOcd")
Expand Down
20 changes: 12 additions & 8 deletions tools/modm_tools/openocd.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,19 @@

# -----------------------------------------------------------------------------
class OpenOcdBackend:
def __init__(self, commands=None, config=None, search=None):
def __init__(self, commands=None, config=None, search=None, binary=None):
self.commands = utils.listify(commands)
self.config = utils.listify(config)
self.search = utils.listify(search)
self.binary = binary
self.process = None

def init(self, elf):
return ["target extended-remote :3333"]

def start(self):
self.process = call(self.commands, self.config, self.search,
self.process = call(commands=self.commands, config=self.config,
search=self.search, binary=self.binary,
blocking=False, silent=True)

def stop(self):
Expand All @@ -66,8 +68,9 @@ def stop(self):


# -----------------------------------------------------------------------------
def call(commands=None, config=None, search=None, blocking=True, silent=False, verbose=False):
def call(commands=None, config=None, search=None, blocking=True, silent=False, verbose=False, binary=None):
commands = utils.listify(commands)
binary = binary or "openocd"
config = utils.listify(config)
search = utils.listify(search)
if silent:
Expand All @@ -78,7 +81,8 @@ def call(commands=None, config=None, search=None, blocking=True, silent=False, v
# See http://openocd.org/doc/html/Running.html
# os.environ.get("OPENOCD_SCRIPTS", "")

command_openocd = "openocd {} {} {}".format(
command_openocd = "{} {} {} {}".format(
binary,
" ".join(map('-s "{}"'.format, search)),
" ".join(map('-f "{}"'.format, config)),
" ".join(map('-c "{}"'.format, commands))
Expand Down Expand Up @@ -126,13 +130,13 @@ def log_rtt(backend, channel=0):
tn.interact()

# -----------------------------------------------------------------------------
def program(source, config=None, search=None):
def program(source, config=None, search=None, binary=None):
commands = ["modm_program {{{}}}".format(source)]
call(commands=commands, config=config, search=search)
call(commands=commands, config=config, search=search, binary=binary)

def reset(config=None, search=None):
def reset(config=None, search=None, binary=None):
commands = ["reset", "shutdown"]
call(commands=commands, config=config, search=search)
call(commands=commands, config=config, search=search, binary=binary)

# -----------------------------------------------------------------------------
def add_subparser(subparser):
Expand Down
6 changes: 6 additions & 0 deletions tools/openocd/modm/rp2040_picoprobe.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Script for working with RP2040 boards using Picoprobe

# Must be specified by the user via `modm:build:openocd.cfg` option

source [find interface/picoprobe.cfg]
source [find target/rp2040.cfg]

0 comments on commit 0b296c5

Please sign in to comment.