1.. _target-raspberry-pi-pico: 2 3================= 4Raspberry Pi Pico 5================= 6.. warning:: 7 8 This target is in an early state and is under active development. Usability 9 is not very polished, and many features/configuration options that work in 10 upstream Pi Pico CMake build have not yet been ported to the GN build. 11 12This target configuration uses :ref:`pw_system<module-pw_system>` on top of 13FreeRTOS and the `Raspberry Pi Pico SDK 14<https://github.com/raspberrypi/pico-sdk>`_ HAL rather than a baremetal 15approach. 16 17---------------- 18First-time setup 19---------------- 20GN 21== 22 23To use this target, Pigweed must be set up to use FreeRTOS and the Pico SDK 24HAL. When using bazel, dependencies will be automatically installed. For the GN 25build, the supported repositories can be downloaded via ``pw package``, and then 26the build must be manually configured to point to the locations the repositories 27were downloaded to. 28 29.. warning:: 30 31 The GN build does not distribute the libusb headers which are required by 32 picotool. If the picotool installation fails due to missing libusb headers, 33 it can be fixed by installing them manually. 34 35 .. tab-set:: 36 37 .. tab-item:: Linux 38 :sync: linux 39 40 .. code-block:: sh 41 42 sudo apt-get install libusb-1.0-0-dev 43 44 .. admonition:: Note 45 :class: tip 46 47 These instructions assume a Debian/Ubuntu Linux distribution. 48 49 .. tab-item:: macOS 50 :sync: macos 51 52 .. code-block:: sh 53 54 brew install libusb 55 brew install pkg-config 56 57 .. admonition:: Note 58 :class: tip 59 60 These instructions assume a brew is installed and used for package 61 management. 62 63.. code-block:: console 64 65 $ pw package install freertos 66 $ pw package install pico_sdk 67 $ pw package install picotool 68 69 $ gn gen out --export-compile-commands --args=" 70 dir_pw_third_party_freertos=\"//environment/packages/freertos\" 71 PICO_SRC_DIR=\"//environment/packages/pico_sdk\" 72 " 73 74.. tip:: 75 76 Instead of the ``gn gen out`` with args set on the command line above you can 77 run: 78 79 .. code-block:: console 80 81 $ gn args out 82 83 Then add the following lines to that text file: 84 85 .. code-block:: 86 87 dir_pw_third_party_freertos = getenv("PW_PACKAGE_ROOT") + "/freertos" 88 PICO_SRC_DIR = getenv("PW_PACKAGE_ROOT") + "/pico_sdk" 89 90.. _target-raspberry-pi-pico-first_time_setup-setting_up_linux_udev_rules: 91 92Setting up udev rules 93===================== 94On linux, you may need to update your udev rules at 95``/etc/udev/rules.d/49-pico.rules`` to include the following: 96 97.. code-block:: none 98 99 # RaspberryPi Debug probe: https://github.com/raspberrypi/debugprobe 100 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE:="0666" 101 KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE:="0666" 102 # RaspberryPi Legacy Picoprobe (early Debug probe version) 103 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE:="0666" 104 KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE:="0666" 105 # RP2040 Bootloader mode 106 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE:="0666" 107 KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE:="0666" 108 # RP2040 USB Serial 109 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE:="0666" 110 KERNEL=="ttyACM*", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000a", MODE:="0666" 111 112-------- 113Building 114-------- 115 116.. tab-set:: 117 118 .. tab-item:: GN 119 :sync: GN 120 121 Once the Pico SDK is configured, the Pi Pico will build as part of the default 122 GN build: 123 124 .. code-block:: console 125 126 $ ninja -C out 127 128 The pw_system example is available as a separate build target: 129 130 .. code-block:: console 131 132 $ ninja -C out pw_system_demo 133 134 .. tab-item:: bazel 135 :sync: bazel 136 137 .. code-block:: console 138 139 $ bazel build --config=rp2040 //... 140 141 The pw_system example is available as a separate build target: 142 143 .. code-block:: console 144 145 $ bazel build --config=rp2040 //pw_system:system_example 146 147-------- 148Flashing 149-------- 150Using the mass-storage booloader 151================================ 152Hold down the BOOTSEL button when plugging in the pico and it will appear as a 153mass storage device. Copy the UF2 firmware image (for example, 154``out/rp2040.size_optimized/obj/pw_system/system_example.uf2``) to 155your Pico when it is in USB bootloader mode. 156 157.. tip:: 158 159 This is the simplest solution if you are fine with physically interacting 160 with your Pico whenever you want to flash a new firmware image. 161 162.. _target-raspberry-pi-pico-flashing-using_openocd: 163 164Using OpenOCD 165============= 166To flash using OpenOCD, you'll either need a 167`Pico debug probe <https://www.raspberrypi.com/products/debug-probe/>`_ or a 168second Raspberry Pi Pico to use as a debug probe. Also, on Linux you'll need to 169follow the instructions for 170:ref:`target-raspberry-pi-pico-first_time_setup-setting_up_linux_udev_rules`\. 171 172First-time setup 173---------------- 174First, flash your first Pi Pico with ``debugprobe_on_pico.uf2`` from `the 175latest release of debugprobe <https://github.com/raspberrypi/debugprobe/releases/latest>`_. 176 177Next, connect the two Pico boards as follows: 178 179- Pico probe GND -> target Pico GND 180- Pico probe GP2 -> target Pico SWCLK 181- Pico probe GP3 -> target Pico SWDIO 182 183If you do not jump VSYS -> VSYS, you'll need to connect both Pi Pico boards 184to USB ports so that they have power. 185 186For more detailed instructions on how how to connect two Pico boards, see 187``Appendix A: Using Picoprobe`` of the `Getting started with Raspberry Pi Pico 188<https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf>`_ 189guide. 190 191Flashing a new firmware 192----------------------- 193Once your Pico is all wired up, you'll be able to flash it using OpenOCD: 194 195.. code-block:: console 196 197 $ openocd -f interface/cmsis-dap.cfg \ 198 -f target/rp2040.cfg -c "adapter speed 5000" \ 199 -c "program out/rp2040.size_optimized/obj/pw_system/bin/system_example.elf verify reset exit" 200 201Typical output: 202 203.. code-block:: none 204 205 xPack Open On-Chip Debugger 0.12.0+dev-01312-g18281b0c4-dirty (2023-09-05-01:33) 206 Licensed under GNU GPL v2 207 For bug reports, read 208 http://openocd.org/doc/doxygen/bugs.html 209 Info : Hardware thread awareness created 210 Info : Hardware thread awareness created 211 adapter speed: 5000 kHz 212 Info : Using CMSIS-DAPv2 interface with VID:PID=0x2e8a:0x000c, serial=415032383337300B 213 Info : CMSIS-DAP: SWD supported 214 Info : CMSIS-DAP: Atomic commands supported 215 Info : CMSIS-DAP: Test domain timer supported 216 Info : CMSIS-DAP: FW Version = 2.0.0 217 Info : CMSIS-DAP: Interface Initialised (SWD) 218 Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 0 219 Info : CMSIS-DAP: Interface ready 220 Info : clock speed 5000 kHz 221 Info : SWD DPIDR 0x0bc12477, DLPIDR 0x00000001 222 Info : SWD DPIDR 0x0bc12477, DLPIDR 0x10000001 223 Info : [rp2040.core0] Cortex-M0+ r0p1 processor detected 224 Info : [rp2040.core0] target has 4 breakpoints, 2 watchpoints 225 Info : [rp2040.core1] Cortex-M0+ r0p1 processor detected 226 Info : [rp2040.core1] target has 4 breakpoints, 2 watchpoints 227 Info : starting gdb server for rp2040.core0 on 3333 228 Info : Listening on port 3333 for gdb connections 229 Warn : [rp2040.core1] target was in unknown state when halt was requested 230 [rp2040.core0] halted due to debug-request, current mode: Thread 231 xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 232 [rp2040.core1] halted due to debug-request, current mode: Thread 233 xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 234 ** Programming Started ** 235 Info : Found flash device 'win w25q16jv' (ID 0x001540ef) 236 Info : RP2040 B0 Flash Probe: 2097152 bytes @0x10000000, in 32 sectors 237 238 Info : Padding image section 1 at 0x10022918 with 232 bytes (bank write end alignment) 239 Warn : Adding extra erase range, 0x10022a00 .. 0x1002ffff 240 ** Programming Finished ** 241 ** Verify Started ** 242 ** Verified OK ** 243 ** Resetting Target ** 244 shutdown command invoked 245 246.. tip:: 247 248 This is the most robust flashing solution if you don't want to physically 249 interact with the attached devices every time you want to flash a Pico. 250 251------------------ 252Running unit tests 253------------------ 254Unlike most other targets in Pigweed, the RP2040 uses RPC-based unit testing. 255This makes it easier to fully automate on-device tests in a scalable and 256maintainable way. 257 258Step 1: Start test server 259========================= 260To allow Ninja to properly serialize tests to run on device, Ninja will send 261test requests to a server running in the background. The first step is to launch 262this server. By default, the script will attempt to automatically detect an 263attached Pi Pico running an application with USB serial enabled or a Pi Debug 264Probe, then use it for testing. To override this behavior, provide a custom 265server configuration file with ``--server-config``. 266 267.. code-block:: console 268 269 $ python -m rp2040_utils.unit_test_server 270 271.. tip:: 272 273 If the server can't find any attached devices, ensure your Pi Pico is 274 already running an application that utilizes USB serial. 275 276.. Warning:: 277 278 If you connect or disconnect any boards, you'll need to restart the test 279 server for hardware changes to take effect. 280 281Step 2: Configure GN 282==================== 283By default, this hardware target has incremental testing disabled. Enabling the 284``pw_targets_ENABLE_RP2040_TEST_RUNNER`` build arg tells GN to send requests to 285a running ``rp2040_utils.unit_test_server``. 286 287.. code-block:: console 288 289 $ gn args out 290 # Modify and save the args file to use pw_target_runner. 291 pw_targets_ENABLE_RP2040_TEST_RUNNER = true 292 293Step 3: Build changes 294===================== 295Now, whenever you run ``ninja -C out pi_pico``, all tests affected by changes 296since the last build will be rebuilt and then run on the attached device. 297Alternatively, you may use ``pw watch`` to set up Pigweed to trigger 298builds/tests whenever changes to source files are detected. 299 300----------------------- 301Connect with pw_console 302----------------------- 303Once the board has been flashed, you can connect to it and send RPC commands 304via the Pigweed console: 305 306.. code-block:: console 307 308 $ pw-system-console -d /dev/{ttyX} -b 115200 \ 309 --proto-globs pw_rpc/echo.proto \ 310 --token-databases \ 311 out/rp2040.size_optimized/obj/pw_system/bin/system_example.elf 312 313Replace ``{ttyX}`` with the appropriate device on your machine. On Linux this 314may look like ``ttyACM0``, and on a Mac it may look like ``cu.usbmodem***``. 315 316When the console opens, try sending an Echo RPC request. You should get back 317the same message you sent to the device. 318 319.. code-block:: pycon 320 321 >>> device.rpcs.pw.rpc.EchoService.Echo(msg="Hello, Pigweed!") 322 (Status.OK, pw.rpc.EchoMessage(msg='Hello, Pigweed!')) 323 324You can also try out our thread snapshot RPC service, which should return a 325stack usage overview of all running threads on the device in Host Logs. 326 327.. code-block:: pycon 328 329 >>> device.snapshot_peak_stack_usage() 330 331Example output: 332 333.. code-block:: 334 335 20220826 09:47:22 INF PendingRpc(channel=1, method=pw.thread.ThreadSnapshotService.GetPeakStackUsage) completed: Status.OK 336 20220826 09:47:22 INF Thread State 337 20220826 09:47:22 INF 5 threads running. 338 20220826 09:47:22 INF 339 20220826 09:47:22 INF Thread (UNKNOWN): IDLE 340 20220826 09:47:22 INF Est CPU usage: unknown 341 20220826 09:47:22 INF Stack info 342 20220826 09:47:22 INF Current usage: 0x20002da0 - 0x???????? (size unknown) 343 20220826 09:47:22 INF Est peak usage: 390 bytes, 76.77% 344 20220826 09:47:22 INF Stack limits: 0x20002da0 - 0x20002ba4 (508 bytes) 345 20220826 09:47:22 INF 346 20220826 09:47:22 INF ... 347 348You are now up and running! 349 350.. seealso:: 351 352 The :ref:`module-pw_console` 353 :bdg-ref-primary-line:`module-pw_console-user_guide` for more info on using 354 the the pw_console UI. 355 356--------------------- 357Interactive debugging 358--------------------- 359To interactively debug a Pico, first ensure you are set up for 360:ref:`target-raspberry-pi-pico-flashing-using_openocd`\. 361 362In one terminal window, start an OpenOCD GDB server with the following command: 363 364.. code-block:: console 365 366 $ openocd -f interface/cmsis-dap.cfg \ 367 -f target/rp2040.cfg -c "adapter speed 5000" 368 369In a second terminal window, connect to the open GDB server, passing the binary 370you will be debugging: 371 372.. code-block:: console 373 374 $ arm-none-eabi-gdb -ex "target remote :3333" \ 375 out/rp2040.size_optimized/obj/pw_system/bin/system_example.elf 376 377Helpful GDB commands 378==================== 379+---------------------------------------------------------+--------------------+ 380| Action | shortcut / command | 381+=========================================================+====================+ 382| Reset the running device, stopping immediately | ``mon reset halt`` | 383+---------------------------------------------------------+--------------------+ 384| Continue execution until pause or breakpoint | ``c`` | 385+---------------------------------------------------------+--------------------+ 386| Pause execution | ``ctrl+c`` | 387+---------------------------------------------------------+--------------------+ 388| Show backtrace | ``bt`` | 389+---------------------------------------------------------+--------------------+ 390