Raspberry Pi Pico with pw_system#
Warning
This target is in an early state and is under active development. Usability is not very polished, and many features/configuration options that work in upstream Pi Pico CMake build have not yet been ported to the GN build.
This target configuration uses pw_system on top of FreeRTOS and the Raspberry Pi Pico SDK HAL rather than a from-the-ground-up baremetal approach.
Setup#
To use this target, Pigweed must be set up to use FreeRTOS and the Pico SDK
HAL. The supported repositories can be downloaded via pw package
, and then
the build must be manually configured to point to the locations the repositories
were downloaded to.
pw package install freertos
pw package install pico_sdk
gn gen out --export-compile-commands --args="
dir_pw_third_party_freertos=\"//environment/packages/freertos\"
PICO_SRC_DIR=\"//environment/packages/pico_sdk\"
"
Tip
Instead of the gn gen out
with args set on the command line above you can
run:
gn args out
Then add the following lines to that text file:
dir_pw_third_party_freertos = getenv("PW_PACKAGE_ROOT") + "/freertos"
PICO_SRC_DIR = getenv("PW_PACKAGE_ROOT") + "/pico_sdk"
Linux#
On linux, you may need to update your udev rules at
/etc/udev/rules.d/49-pico.rules
to include the following:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE:="0666"
KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE:="0666"
Building#
The Pi Pico is configured to output logs and test results over USB serial at a baud rate of 115200.
Once the pico SDK is configured, the Pi Pico will build as part of the default GN build:
ninja -C out
Flashing#
Flashing the Pi Pico is two easy steps:
While holding the button on the Pi Pico, connect the Pico to your computer via the micro USB port.
Copy the desired UF2 firmware image to the RPI-RP2 volume that enumerated when you connected the Pico.
Running unit tests#
Unlike most other targets in Pigweed, the RP2040 uses RPC-based unit testing. This makes it easier to fully automate on-device tests in a scalable and maintainable way.
Step 1: Start test server#
To allow Ninja to properly serialize tests to run on device, Ninja will send
test requests to a server running in the background. The first step is to launch
this server. By default, the script will attempt to automatically detect an
attached Pi Pico running an application with USB serial enabled, then using
it for testing. To override this behavior, provide a custom server configuration
file with --server-config
.
$ python -m rp2040_utils.unit_test_server
Tip
If the server can’t find any attached devices, ensure your Pi Pico is already running an application that utilizes USB serial.
Warning
If you connect or disconnect any boards, you’ll need to restart the test server for hardware changes to take effect.
Step 2: Configure GN#
By default, this hardware target has incremental testing disabled. Enabling the
pw_targets_ENABLE_RP2040_TEST_RUNNER
build arg tells GN to send requests to
a running rp2040_utils.unit_test_server
.
$ gn args out
# Modify and save the args file to use pw_target_runner.
pw_targets_ENABLE_RP2040_TEST_RUNNER = true
Step 3: Build changes#
Now, whenever you run ninja -C out pi_pico
, all tests affected by changes
since the last build will be rebuilt and then run on the attached device.
Alternatively, you may use pw watch
to set up Pigweed to trigger
builds/tests whenever changes to source files are detected.
Building and running the demo application#
This target has an associated demo application that can be built and then flashed to a device with the following commands:
Build#
ninja -C out pw_system_demo
Flash#
Using a uf2 file:
Copy to
out/rp2040.size_optimized/obj/pw_system/system_example.uf2
your Pico when it is in USB bootloader mode. Hold down the BOOTSEL button when plugging in the pico and it will appear as a mass storage device.Using a Pico Probe and openocd:
This requires installing the Raspberry Pi foundation’s OpenOCD fork for the Pico probe. More details including how to connect the two Pico boards is available in
Appendix A: Using Picoprobe
of the Getting started with Raspberry Pi Pico guide.Install RaspberryPi’s OpenOCD Fork:
git clone https://github.com/raspberrypi/openocd.git \ --branch picoprobe \ --depth=1 \ --no-single-branch \ openocd-picoprobe cd openocd-picoprobe ./bootstrap ./configure --enable-picoprobe --prefix=$HOME/apps/openocd --disable-werror make -j2 make install
Setup udev rules (Linux only):
cat <<EOF > 49-picoprobe.rules SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000[43a]", MODE:="0666" KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000[43a]", MODE:="0666" EOF sudo cp 49-picoprobe.rules /usr/lib/udev/rules.d/49-picoprobe.rules sudo udevadm control --reload-rules
Flash the Pico:
~/apps/openocd/bin/openocd -f ~/apps/openocd/share/openocd/scripts/interface/picoprobe.cfg -f ~/apps/openocd/share/openocd/scripts/target/rp2040.cfg -c 'program out/rp2040.size_optimized/obj/pw_system/bin/system_example.elf verify reset exit'
Connect with pw_console#
Once the board has been flashed, you can connect to it and send RPC commands via the Pigweed console:
pw-system-console -d /dev/{ttyX} -b 115200 \
--proto-globs pw_rpc/echo.proto \
--token-databases \
out/rp2040.size_optimized/obj/pw_system/bin/system_example.elf
Replace {ttyX}
with the appropriate device on your machine. On Linux this
may look like ttyACM0
, and on a Mac it may look like cu.usbmodem***
.
When the console opens, try sending an Echo RPC request. You should get back the same message you sent to the device.
>>> device.rpcs.pw.rpc.EchoService.Echo(msg="Hello, Pigweed!")
(Status.OK, pw.rpc.EchoMessage(msg='Hello, Pigweed!'))
You can also try out our thread snapshot RPC service, which should return a stack usage overview of all running threads on the device in Host Logs.
>>> device.snapshot_peak_stack_usage()
Example output:
20220826 09:47:22 INF PendingRpc(channel=1, method=pw.thread.ThreadSnapshotService.GetPeakStackUsage) completed: Status.OK
20220826 09:47:22 INF Thread State
20220826 09:47:22 INF 5 threads running.
20220826 09:47:22 INF
20220826 09:47:22 INF Thread (UNKNOWN): IDLE
20220826 09:47:22 INF Est CPU usage: unknown
20220826 09:47:22 INF Stack info
20220826 09:47:22 INF Current usage: 0x20002da0 - 0x???????? (size unknown)
20220826 09:47:22 INF Est peak usage: 390 bytes, 76.77%
20220826 09:47:22 INF Stack limits: 0x20002da0 - 0x20002ba4 (508 bytes)
20220826 09:47:22 INF
20220826 09:47:22 INF ...
You are now up and running!
See also
The pw_console User Guide for more info on using the the pw_console UI.