:imagesdir: doc/png :source-highlighter: rouge :toc: :toclevels: 5
YAPicoprobe allows a Pico / RP2040 to be used as USB -> SWD and UART bridge. This means it can be used as a debugger and serial console for another Pico or any other SWD compatible controller.
YAPicoprobe is a fork of the original https://github.com/raspberrypi/picoprobe[Picoprobe] and was created due to my lazyness to follow the PR discussions and delays with unknown outcome.
Another reason for this fork is that I wanted to play around with SWD, RTT, PIO etc pp, so the established development process was a little bit hindering.
Finally there is Yet Another Picoprobe around, the YAPicoprobe.
NOTE: Pico2 / RP2350 can also be used as probe hardware. This is an experimental feature.
WARNING: Pico2 / RP2350 targets are currently not supported.
WARNING: Pico2 target is only working at <= 300kHz reliably. +
time /home/hardy/.pico-sdk/openocd/0.12.0+dev/openocd.exe -c "gdb_port 50000" -c "tcl_port 50001" -c "telnet_port 50002" -s /home/hardy/.pico-sdk/openocd/0.12.0+dev/scripts -f /home/hardy/.vscode/extensions/marus25.cortex-debug-1.12.1/support/openocd-helpers.tcl -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 349" -c "program {pio_blink.elf} verify reset; shutdown;"
Other RP2040 hardware will work as well, e.g. https://mcuoneclipse.com/2023/04/08/open-source-picolink-raspberry-pi-rp2040-cmsis-dap-debug-probe/[picoLink] is happy with the firmware image for the Pico.
Firmware images can be downloaded from https://github.com/rgrr/yapicoprobe/releases[github].
Wires between Pico probe and target board are shown below. At least three wires (plus supply) are required: SWCLK, SWDIO and Gnd. The Reset line is optional. If target UART RX/TX are used, additional two wires are needed. Sigrok inputs go extra.
[.text-center] image::board_schematic_bb.png[Wiring, 60%]
More information about setup can be found in the https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf[Pico Getting Started Guide]. See "Appendix A: Using Picoprobe".
For information about cabling between Pico Debug Probe and target refer to the corresponding https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html[documentation].
For details about probe pin assignments see the link:doc/hardware.adoc[hardware section]. Ochamodev wrote a nice https://github.com/ochamodev/raspberry_pico_setup_guide[setup guide], containing the steps from installation until debugging in VSCode.
.Tool Compatibility [%autowidth] [%header] |=== |Tool | Linux | Windows (10) | Example command line
|OpenOCD 0.11 & 0.12
|yes
|yes
|openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 25000" -c "program {firmware.elf} verify reset; shutdown;"
|pyOCD 0.34 .. 0.36
|yes
|yes
|pyocd flash -f 400000 -t nrf52840 firmware.elf
|probe-rs 0.23 ..
|yes
|?
|probe-rs benchmark --protocol swd --address 0x20000000 --chip RP2040
|cp / copy
|yes
|yes
|cp firmware.uf2 /media/picoprobe
|===
NOTE: For best RP2040 support, OpenOCD bundled with PlatformIO is recommended.
See <
YAPicoprobe tries to identify the connecting tool and sets some internal parameters for best performance. Those settings are:
.Parameter Optimization [%autowidth] [%header] |=== |Tool | Parameter
|pyOCD / CMSIS-DAPv2 |DAP_PACKET_COUNT=1 + DAP_PACKET_SIZE=512
|OpenOCD / CMSIS-DAPv2 |DAP_PACKET_COUNT=1 + DAP_PACKET_SIZE=512
|probe-rs / CMSIS-DAPv2 |DAP_PACKET_COUNT=8 + DAP_PACKET_SIZE=512
|unknown / CMSIS-DAPv2 |DAP_PACKET_COUNT=1 + DAP_PACKET_SIZE=64
|CMSIS-DAPv1 HID |DAP_PACKET_COUNT=1 + DAP_PACKET_SIZE=64 |===
The tools above allow specification of the adapter speed. This is the clock frequency between probe and target device.
Unfortunately DAP converts internally the frequency into delays which are always even multiples of clock cycles.
That means that actual clock speeds are 125MHz / (2*n)
, n>=3
-> 20833kHz, 12500kHz, 10417kHz, ...
Normally the requested frequency is rounded down according to the possible values from above. But if the specified frequency is completely out of range, the allowed maximum target SWD frequency is used, e.g. for the RP2040 24MHz.
Actually usable frequency depends on cabling and the DAP speed. If the DAP cannot access memory with speed determined by the host, it responds with WAIT and the host needs to retry.
Effects of cabling should be clear: the longer the cables plus some more effects, the worse the signals. Which effectively means slowing down clock frequency is required to get the data transported.
pyocd reset -f 5000000 -t rp2040
sets SWCLK to 5MHz.Via MSC the so called "drag-n-drop" supported is implemented. Actually this also helps in copying a UF2 image directly into the target via command line.
MSC write access, i.e. flashing of the target, is device dependent and thus works only for a few selected devices which are in my range of interest. Those devices are the RP2040 (and its flash "win w25q16jv") and the Nordic nRF52 family (namely nRF52832/833/840). + For the RP2040 some special flash routines has been implemented. For nRF52 flashing regular DAPLink modules have been taken. Which also implies, that extending the probes capabilities shouln't be too hard.
Because CMSIS-DAP access should be generic, flashing of other SWD compatible devices is tool dependant (OpenOCD/pyOCD).
https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/[RTT] allows transfer from the target to the host in "realtime" via the SWD interface.
The RTT control block on the target is automatically detected. Currently channels 0 and 1 are supported.
To get the RTT channels running, code on the target has to be either instrumented or adopted.
RTT channel 0 is used for bidirectional console communication. This channel is directed into the UART CDC of the target device.
Communication is birectional, but don't expect high transfer rates from host to target.
RTT channel 1 is used for communication with Seggers https://www.segger.com/products/development-tools/systemview/[SystemView]. YAPicoprobe provides the data over TCP at port 19111 which is the default for SystemView communication. Default IP address of the probe (if not configured otherwise) is 192.168.14.1.
.LED Indications [%autowidth] [%header] |=== | State | Indication
| no target found | 5Hz blinking
| DAPv1 connected | LED on, off for 100ms once per second
| DAPv2 connected | LED on, off for 100ms twice per second
| MSC active | LED on, off for 100ms thrice per second
| UART data from target | slow flashing: 300ms on, 700ms off
| target found | LED off, flashes once per second for 20ms
| RTT control block found | LED off, flashes twice per second for 20ms
| RTT data received | LED off, flashes thrice per second for 20ms
| sigrok running | 10Hz flashing
| sigrok waiting for auto trigger | 10Hz negative flashing (flicker) |===
pyocd reset -t rp2040
or similar.The Pico Debug Probe has four additional LEDs. Assignment is as follows:
.Pico Debug Probe Additional LEDs [%autowidth] [%header] |=== | LED | Color | Indication
| UART_TX | yellow | 5ms flash, if target sends data
| UART_RX | green | 20ms flash, if target gets data
| DAP_TARGET_RUNNING | yellow | set by host tool
| DAP_CONNECTED | green | set by host tool
|===
Several parameters can be configured via the Debug CDC of the probe. These parameters include the network selection and CPU/SWCLK frequencies.
Because configuration of the probe is seen as once in a life time, the interface is kept very simple.
Following procedure applies:
pwd
<cmd>
lock
- lock the configuration parameters
killall
- kill all current configuration parameters
reset
- restart the probe
show
- shows the current configuration (initially empty)<variable>=<value>
f_cpu
- set CPU frequency in MHz
f_swd
- set SWD frequency in kHz
net
- set the net of the probes IP address 192.168.<net>.1
nick
- set nickname of the probe. Use this with care because it also changes
the USB serial number (which might be intended)
pwd
- set a password for locking the configuration. Unlocking is done subsequently
with pwd:<your-pwd>
r_start
/ r_end
- RAM start/end for generic target to override default 0x20000000..0x20040000.
** rtt
- enable/disable RTT access, default is RTT enabled (0: disable, 1:enable).pwd:<your-pwd>
)Under Linux one wants to use the following udev rules for convenience.
SUBSYSTEM=="usb", ATTR{idVendor}=="2e8a", ATTR{idProduct}=="000c", MODE:="0666"
ACTION=="add", SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]", ATTRS{interface}=="YAPicoprobe CDC-UART", MODE:="0666", SYMLINK+="ttyPicoTarget" ACTION=="add", SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]", ATTRS{interface}=="YAPicoprobe CDC-DEBUG", MODE:="0666", SYMLINK+="ttyPicoProbe" ACTION=="add", SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]", ATTRS{interface}=="YAPicoprobe CDC-SIGROK", MODE:="0666", SYMLINK+="ttyPicoSigRok ACTION=="add", SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]", ATTRS{interface}=="YAPicoprobe CDC-SysView", MODE:="0666", SYMLINK+="ttyPicoSysView"
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", RUN+="/usr/bin/logger --tag picoprobe-mount Mounting what seems to be a Raspberry Pi Picoprobe", RUN+="/usr/bin/systemd-mount --no-block --collect --fsck=0 -o uid=hardy,gid=hardy,flush $devnode /media/picoprobe" ACTION=="remove", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", RUN+="/usr/bin/logger --tag picoprobe-mount Unmounting what seems to be a Raspberry Pi Picoprobe", RUN+="/usr/bin/systemd-umount /media/picoprobe"
SystemView connectivity over TCP/IP is on most systems not configuration free.
If everything is configured fine, the probe has the default address 192.168.14.1 and the host computer gets 192.168.14.2.
On Debian the configuration is as follows:
ip a
shows its network interface, e.g. enxfe<your-probe>
.
If the network interface already shows an IP address everything is fine and you are readysudo dhclient enxfe<your-probe>
/etc/network/interfaces
:On my system this unfortunately leads to error messages (which are harmless) if the probe is not connected.
A certain version of Win10 is required for USB-NCM connectivity. Exact version is unknown.
The driver needs to be installed manually. Procedure is roughly as follows:
YaPicoprobe NCM
with an exclamation markipconfig
on a command line shows 192.168.14.2
for an Ethernet adapter, the procedure has most likely
succeeded and SystemView is ready for operationIt is said, that USB-NCM is working out of the box. This has not been tested.
https://platformio.org/[PlatformIO] configuration in platformio.ini
is pretty straight forward:
The firmware image can alternativly copied directly (and faster) via MSC with custom upload:
I'm sure there are smarter ways to specify the image path.
Optional: there is also a special PlatformIO handling in the probe: it ignores the defensive 1MHz clock setting which is used by
the above contained OpenOCD. Standard clock is thus 15MHz. If this is too fast, set the frequency with
pyocd reset -f 1100000 -t rp2040
or similar. If this is too slow, use pyocd reset -f 50000000 -t rp2040
.
To use RTT for debug/console output the following has to be done:
platformio.ini
:...
...
Building from source is done with the help of a stub Makefile which eases integration into Eclipse (but can be
used from command line as well). The Makefile creates via cmake a build.ninja
which is responsible for
the actual build process.
To build the project, there must be somewhere a recent https://github.com/raspberrypi/pico-sdk[Pico SDK] and
the environment variable PICO_SDK_PATH
must point to it.
NOTE: I'm most of the time on the master branch of TinyUSB which is part of the Pico SDK. Originally TinyUSB 0.15.0 is being used by Pico SDK 1.5.1. + So if you experience unexpected behaviour, I recommend to update TinyUSB and retry.
If you want to adopt YAPicoprobe options to your needs, check CMakeLists.txt and invoke cmake accordingly.
Requirements:
make cmake-create-debug
make all
mkdir _build; cd _build cmake .. -D
If you want to know the several options use the one liner in the build directory:
cmake -LH . | sed -n -e '/OPT_/{x;1!p;g;$!N;p;D;}' -e h
. +
Or use simply make show-options
in the projects root.
[%autowidth] [%header] | === |
---|
| https://github.com/raspberrypi/picoprobe[Picoprobe] | the original
| https://github.com/essele/pico_debug[pico_debug] | another probe which gave ideas for PIO code
| https://github.com/pico-coder/sigrok-pico[sigrok-pico] | original RP2040 based sigrok logic analyzer / oscilloscope
| https://github.com/ARMmbed/DAPLink[DAPLink] | The SWD probe software for a lot of targets and boards
|===
[%autowidth] [%header] | === |
---|
| https://documentation-service.arm.com/static/5f900b1af86e16515cdc0642[Debug Interface v5.2 Architecture Specification] | if the link does not work, try https://developer.arm.com/documentation/ihi0031/latest/[this]
https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst[Semihosting Information] |
---|
https://github.com/raspberrypi/pico-sdk[Raspberry Pi Pico SDK] |
---|
https://github.com/pyocd/pyOCD[pyOCD on github] |
---|
| https://github.com/openocd-org/openocd[OpenOCD on github] | https://openocd.org/[Official Homepage]
https://github.com/probe-rs/probe-rs[probe-rs on github] |
---|
https://wiki.segger.com/Use_SystemView_without_RTOS[Use SystemView without RTOS] |
---|
https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement[NCM Specification] |
---|
|===