• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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