Raspberry Pi RP2040 User manual


Colophon
Copyright © 2020 Raspberry Pi (Trading) Ltd.
The documentation of the RP2040 microcontroller is licensed under a Creative Commons Attribution-NoDerivatives 4.0
International (CC BY-ND).
build-date: 2021-04-07
build-version: 86fc793-clean
About the SDK
Throughout the text "the SDK" refers to our Raspberry Pi Pico SDK. More details about the SDK can be
found in the Raspberry Pi Pico C/C++ SDK book.
Legal Disclaimer Notice
TECHNICAL AND RELIABILITY DATA FOR RASPBERRY PI PRODUCTS (INCLUDING DATASHEETS) AS MODIFIED FROM
TIME TO TIME (“RESOURCES”) ARE PROVIDED BY RASPBERRY PI (TRADING) LTD (“RPTL) "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW IN NO EVENT SHALL RPTL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE RESOURCES, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
RPTL reserves the right to make any enhancements, improvements, corrections or any other modifications to the
RESOURCES or any products described in them at any time and without further notice.
The RESOURCES are intended for skilled users with suitable levels of design knowledge. Users are solely responsible for
their selection and use of the RESOURCES and any application of the products described in them. User agrees to
indemnify and hold RPTL harmless against all liabilities, costs, damages or other losses arising out of their use of the
RESOURCES.
RPTL grants users permission to use the RESOURCES solely in conjunction with the Raspberry Pi products. All other use
of the RESOURCES is prohibited. No licence is granted to any other RPTL or other third party intellectual property right.
HIGH RISK ACTIVITIES. Raspberry Pi products are not designed, manufactured or intended for use in hazardous
environments requiring fail safe performance, such as in the operation of nuclear facilities, aircraft navigation or
communication systems, air traffic control, weapons systems or safety-critical applications (including life support
systems and other medical devices), in which the failure of the products could lead directly to death, personal injury or
severe physical or environmental damage (“High Risk Activities”). RPTL specifically disclaims any express or implied
warranty of fitness for High Risk Activities and accepts no liability for use or inclusions of Raspberry Pi products in High
Risk Activities.
Raspberry Pi products are provided subject to RPTL’s Standard Terms. RPTL’s provision of the RESOURCES does not
expand or otherwise modify RPTL’s Standard Terms including but not limited to the disclaimers and warranties
expressed in them.
Getting started with Raspberry Pi Pico
Legal Disclaimer Notice 1

Table of Contents
Colophon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê1
Legal Disclaimer Notice. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê1
1. Quick Pico Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê4
2. The SDK. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê6
2.1. Get the SDK and examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê6
2.2. Install the Toolchain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê7
2.3. Updating the SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê7
3. Blinking an LED in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê8
3.1. Building "Blink". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê8
3.2. Load and run "Blink" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê9
3.2.1. From the desktop. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê10
3.2.2. Using the command line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê10
3.2.3. Aside: Other Boards. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê11
3.2.4. Aside: Hands-free Flash Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê11
4. Saying "Hello World" in C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê12
4.1. Serial input and output on Raspberry Pi Pico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê12
4.2. Build "Hello World" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê13
4.3. Flash and Run "Hello World" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê14
4.4. See "Hello World" USB output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê14
4.5. See "Hello World" UART output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê15
4.6. Powering the board. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê16
5. Flash Programming with SWD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê18
5.1. Installing OpenOCD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê18
5.2. SWD Port Wiring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê19
5.3. Loading a Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê20
6. Debugging with SWD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê22
6.1. Build "Hello World" debug version. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê22
6.2. Installing GDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê22
6.3. Use GDB and OpenOCD to debug Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê22
7. Using Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê25
7.1. Installing Visual Studio Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê25
7.2. Loading a Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê26
7.3. Debugging a Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê27
7.3.1. Running "Hello USB" on the Raspberry Pi Pico. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê28
8. Creating your own Project. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê30
8.1. Debugging your project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê32
8.2. Working in Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê33
8.3. Automating project creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê33
8.3.1. Project generation from the command line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê35
9. Building on other platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê36
9.1. Building on Apple macOS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê36
9.1.1. Installing the Toolchain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê36
9.1.2. Using Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê36
9.1.3. Building with CMake Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê36
9.1.4. Saying "Hello World" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê38
9.2. Building on MS Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê38
9.2.1. Installing the Toolchain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê39
9.2.2. Getting the SDK and examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê41
9.2.3. Building "Hello World" from the Command Line. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê42
9.2.4. Building "Hello World" from Visual Studio Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê42
9.2.5. Flashing and Running "Hello World" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê44
10. Using other Integrated Development Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê46
10.1. Using Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê46
10.1.1. Setting up Eclipse for Pico on a Linux machine. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê46
10.2. Using CLion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê51
Getting started with Raspberry Pi Pico
Table of Contents 2

10.2.1. Setting up CLion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê51
10.3. Other Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê54
10.3.1. Using openocd-svd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê54
Appendix A: Using Picoprobe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê57
Build OpenOCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê57
Linux. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê57
Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê57
Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê59
Build and flash picoprobe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê60
Picoprobe Wiring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê61
Install Picoprobe driver (only needed on Windows). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê62
Using Picoprobe’s UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê62
Linux. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê62
Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê63
Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê64
Using Picoprobe with OpenOCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê64
Appendix B: Using Picotool. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê65
Getting picotool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê65
Building picotool. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê65
Using picotool. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê66
Display information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê67
Save the program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê69
Binary Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê69
Basic information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê70
Pins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê70
Including Binary information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê70
Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê71
Setting common fields from CMake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê73
Appendix C: Documentation Release History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ê74
Getting started with Raspberry Pi Pico
Table of Contents 3

Chapter 1. Quick Pico Setup
If you are developing for Raspberry Pi Pico on the Raspberry Pi 4B, or the Raspberry Pi 400, most of the installation
steps in this Getting Started guide can be skipped by running the setup script.
NOTE
This setup script requires approximately 2.5GB of disk space on your SD card, so make sure you have enough free
space before running it. You can check how much free disk space you have with the df -h command.
You can get this script by running the following command in a terminal:
$ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh ①
1. You should first sudo apt install wget if you don’t have wget already installed.
Then make the script executable with,
$ chmod +x pico_setup.sh
and run it with,
$ ./pico_setup.sh
The script will:
•Create a directory called pico
•Install required dependencies
•Download the pico-sdk, pico-examples, pico-extras, and pico-playground repositories
•Define PICO_SDK_PATH, PICO_EXAMPLES_PATH, PICO_EXTRAS_PATH, and PICO_PLAYGROUND_PATH in your ~/.bashrc
•Build the blink and hello_world examples in pico-examples/build/blink and pico-examples/build/hello_world
•Download and build picotool (see Appendix B), and copy it to /usr/local/bin.
•Download and build picoprobe (see Appendix A).
•Download and compile OpenOCD (for debug support)
•Download and install Visual Studio Code
•Install the required Visual Studio Code extensions (see Chapter 7 for more details)
•Configure the Raspberry Pi UART for use with Raspberry Pi Pico
Getting started with Raspberry Pi Pico
Chapter 1. Quick Pico Setup 4

NOTE
The pico directory will be created in the folder where you run the pico_setup.sh script.
Once it has run, you will need to reboot your Raspberry Pi,
$ sudo reboot
for the UART reconfiguration to take effect. Once your Raspberry Pi has rebooted you can open Visual Studio Code in
the "Programming" menu and follow the instructions from Section 7.2.
Getting started with Raspberry Pi Pico
Chapter 1. Quick Pico Setup 5

Chapter 2. The SDK
IMPORTANT
The following instructions assume that you are using a Raspberry Pi Pico and some details may differ if you are
using a different RP2040-based board. They also assume you are using Raspberry Pi OS running on a Raspberry Pi 4,
or an equivalent Debian-based Linux distribution running on another platform. Alternative instructions for those
using Microsoft Windows (see Section 9.2) or Apple macOS (see Section 9.1) are also provided.
The Raspberry Pi Pico is built around the RP2040 microcontroller designed by Raspberry Pi. Development on the board
is fully supported with both a C/C++ SDK, and an official MicroPython port. This book talks about how to get started
with the SDK, and walks you through how to build, install, and work with the SDK toolchain.
TIP
For more information on the official MicroPython port see the Raspberry Pi Pico Python SDK book which documents
the port, and Get started with MicroPython on Raspberry Pi Pico by Gareth Halfacree and Ben Everard, published by
Raspberry Pi Press.
TIP
For more information on the C/C++ SDK, along with API-level documentation, see the Raspberry Pi Pico C/C++ SDK
book.
2.1. Get the SDK and examples
The pico-examples repository (https://github.com/raspberrypi/pico-examples) provides a set of example applications
that are written using the pico-sdk (https://github.com/raspberrypi/pico-sdk). To clone these repositories start by
creating a pico directory to keep all pico related checkouts in. These instructions create a pico directory at /home/pi/pico.
$ cd ~/
$ mkdir pico
$ cd pico
Then clone the pico-sdk and pico-examples git repositories.
$ git clone -b master https://github.com/raspberrypi/pico-sdk.git
$ cd pico-sdk
$ git submodule update --init
$ cd ..
$ git clone -b master https://github.com/raspberrypi/pico-examples.git
Getting started with Raspberry Pi Pico
2.1. Get the SDK and examples 6

WARNING
If you have not initialised the tinyusb submodule in your pico-sdk checkout then USB CDC serial, and other USB
functions and example code, will not work as the SDK will contain no USB functionality.
NOTE
There are additional repositories: pico-extras, and pico-playground that you may also be interested in.
2.2. Install the Toolchain
To build the applications in pico-examples, you’ll need to install some extra tools. To build projects you’ll need CMake, a
cross-platform tool used to build the software, and the GNU Embedded Toolchain for Arm. You can install both these via
apt from the command line. Anything you already have installed will be ignored by apt.
$ sudo apt update
$ sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential ①
1. Native gcc and g++ are needed to compile pioasm and elf2uf2.
NOTE
Ubuntu and Debian users might additionally need to also install libstdc++-arm-none-eabi-newlib.
2.3. Updating the SDK
When a new version of the SDK is released you will need to update your copy of the SDK. To do this go into the pico-sdk
directory which contains your copy of the SDK, and do the following;
$ cd pico-sdk
$ git pull
$ git submodule update
NOTE
If you wish to be informed of new releases you can get notified by setting up a custom watch on the pico-sdk
repository. Navigate to https://github.com/raspberrypi/pico-sdk and then select Watch →Custom →Releases. You
will recieve an email notification every time there is a new SDK release.
Getting started with Raspberry Pi Pico
2.2. Install the Toolchain 7

Chapter 3. Blinking an LED in C
When you’re writing software for hardware, turning an LED on, off, and then on again, is typically the first program that
gets run in a new programming environment. Learning how to blink an LED gets you half way to anywhere. We’re going
to go ahead and blink the on-board LED on the Raspberry Pi Pico which is connected to pin 25 of the RP2040.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/blink/blink.c Lines 9 - 23
Ê9 int main() {
10 #ifndef PICO_DEFAULT_LED_PIN
11 #warning blink example requires a board with a regular LED
12 #else
13 const uint LED_PIN = PICO_DEFAULT_LED_PIN;
14 gpio_init(LED_PIN);
15 gpio_set_dir(LED_PIN, GPIO_OUT);
16 while (true) {
17 gpio_put(LED_PIN, 1);
18 sleep_ms(250);
19 gpio_put(LED_PIN, 0);
20 sleep_ms(250);
21 }
22 #endif
23 }
3.1. Building "Blink"
From the pico directory we created earlier, cd into pico-examples and create a build directory.
$ cd pico-examples
$ mkdir build
$ cd build
Then, assuming you cloned the pico-sdk and pico-examples repositories into the same directory side-by-side, set the
PICO_SDK_PATH:
$ export PICO_SDK_PATH=../../pico-sdk
TIP
Throughout this book we use the relative path ../../pico-sdk to the checkout of the SDK for the PICO_SDK_PATH.
However depending on the location of your checkout it might make sense to replace this with the absolute path, e.g.
/home/pi/pico/pico-sdk.
Prepare your cmake build directory by running cmake ..
$ cmake ..
Using PICO_SDK_PATH from environment ('../../pico-sdk')
PICO_SDK_PATH is /home/pi/pico/pico-sdk
Ê .
Getting started with Raspberry Pi Pico
3.1. Building "Blink" 8

Ê .
Ê .
-- Build files have been written to: /home/pi/pico/pico-examples/build
NOTE
cmake will default to a Release build with compiler optimisations enabled and debugging information removed. To
build a debug version, run cmake -DCMAKE_BUILD_TYPE=Debug ... We will explore this later in Section 6.1.
CMake has now prepared a build area for the pico-examples tree. From here, it is possible to type make to build all example
applications. However, as we are building blink we will only build that application for now by changing directory into the
blink directory before typing make.
TIP
Invoking make with -j4 will run four make jobs in parallel to speed it up. A Raspberry Pi 4 has 4 cores so -j4 is a
reasonable number.
$ cd blink
$ make -j4
Scanning dependencies of target ELF2UF2Build
Scanning dependencies of target boot_stage2_original
[ 0%] Creating directories for 'ELF2UF2Build'
Ê .
Ê .
Ê .
[100%] Linking CXX executable blink.elf
[100%] Built target blink
Amongst other targets, we have now built:
•blink.elf, which is used by the debugger
•blink.uf2, which can be dragged onto the RP2040 USB Mass Storage Device
This binary will blink the on-board LED of the Raspberry Pi Pico which is connected to GPIO25 of RP2040.
More detail on the example code?
This document shows how to build software and load it onto your Raspberry Pi Pico. A lot goes on
behind the scenes to turn our blink application into a binary program, and the Raspberry Pi Pico C/C++
SDK book pulls back the curtain and shows some of the machinery involved. If you aren’t worried about
this kind of thing yet, read on!
3.2. Load and run "Blink"
The fastest method to load software onto a RP2040-based board for the first time is by mounting it as a USB Mass
Storage Device. Doing this allows you to drag a file onto the board to program the flash. Go ahead and connect the
Raspberry Pi Pico to your Raspberry Pi using a micro-USB cable, making sure that you hold down the BOOTSEL button
(Figure 1) as you do so, to force it into USB Mass Storage Mode.
Getting started with Raspberry Pi Pico
3.2. Load and run "Blink" 9

3.2.1. From the desktop
If you are running the Raspberry Pi Desktop the Raspberry Pi Pico should automatically mount as a USB Mass Storage
Device. From here, you can Drag-and-drop blink.uf2 onto the Mass Storage Device.
RP2040 will reboot, unmounting itself as a Mass Storage Device, and start to run the flashed code, see Figure 1.
Figure 1. Blinking the
on-board LED on the
Raspberry Pi Pico.
Arrows point to the on-
board LED, and the
BOOTSEL button.
3.2.2. Using the command line
TIP
You can use picotool to load a UF2 binary onto your Raspberry Pi Pico, see Appendix B.
If you are logged in via ssh for example, you may have to mount the mass storage device manually:
$ dmesg | tail
[ 371.973555] sd 0:0:0:0: [sda] Attached SCSI removable disk
$ sudo mkdir -p /mnt/pico
$ sudo mount /dev/sda1 /mnt/pico
If you can see files in /mnt/pico then the USB Mass Storage Device has been mounted correctly:
$ ls /mnt/pico/
INDEX.HTM INFO_UF2.TXT
Copy your blink.uf2 onto RP2040:
sudo cp blink.uf2 /mnt/pico
sudo sync
RP2040 has already disconnected as a USB Mass Storage Device and is running your code, but for tidiness unmount
/mnt/pico
Getting started with Raspberry Pi Pico
3.2. Load and run "Blink" 10

sudo umount /mnt/pico
NOTE
Removing power from the board does not remove the code. When the board is reattached to power, the code you
have just loaded will begin running again. If you want to upload new code to the board (and overwrite whatever was
already on there), press and hold the BOOTSEL button when applying power to put the board into Mass Storage
mode.
3.2.3. Aside: Other Boards
If you are not following these instructions on a Raspberry Pi Pico, you may not have a BOOTSEL button (as labelled in
Figure 1). Your board may have some other way of loading code, which the board supplier should have documented:
•Most boards expose the SWD interface (Chapter 5) which can reset the board and load code without any button
presses
•There may be some other way of pulling down the flash CS pin (which is how the BOOTSEL button works on
Raspberry Pi Pico), such as a pair of jumper pins which should be shorted together
•Some boards will have a reset button but no BOOTSEL, and may include some code in flash to detect a double-
press of the reset button and enter the bootloader in this way.
In all cases you should consult the documentation for the specific board you are using, which should describe the best
way to load firmware onto that board.
3.2.4. Aside: Hands-free Flash Programming
To enter BOOTSEL mode on your Raspberry Pi Pico, and load code over USB, you need to hold the BOOTSEL button
down, and then reset the board in some way. You can do this by unplugging and plugging the USB connector, or adding
an external button to pull the RUN pin to ground.
You can also use the SWD port (Chapter 5) to reset the board, load code and set the processors running, and this works
even if your code has crashed, so there is no need to manually reset the board or press any buttons. Once you are all set
up with building programs, and you have tried the Hello World example in the next chapter (Chapter 4), setting up SWD
is a good next step.
If you are on a Raspberry Pi, you can set up SWD by running the pico-setup script (Chapter 1), and connecting 3 wires
from your Pi to the Pico as shown in Chapter 5. A USB to SWD debug probe can also be used, for example Appendix A
shows how one Pico can be used to access the SWD port of a second Pico via the first Pico’s USB port.
Getting started with Raspberry Pi Pico
3.2. Load and run "Blink" 11

Chapter 4. Saying "Hello World" in C
After blinking an LED on and off, the next thing that most developers will want to do is create and use a serial port, and
say "Hello World."
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/hello_world/serial/hello_serial.c Lines 10 - 17
10 int main() {
11 stdio_init_all();
12 while (true) {
13 printf("Hello, world!\n");
14 sleep_ms(1000);
15 }
16 return 0;
17 }
4.1. Serial input and output on Raspberry Pi Pico
Serial input (stdin) and output (stdout) can be directed to either serial UART or to USB CDC (USB serial). However by
default stdio and printf will target the default Raspberry Pi Pico UART0.
Default UART0 Physical Pin GPIO Pin
GND 3 N/A
UART0_TX 1 GP0
UART0_RX 2 GP1
IMPORTANT
The default Raspberry Pi Pico UART TX pin (out from Raspberry Pi Pico) is pin GP0, and the UART RX pin (in to
Raspberry Pi Pico) is pin GP1. The default UART pins are configured on a per-board basis using board configuration
files. The Raspberry Pi Pico configuration can be found in https://github.com/raspberrypi/pico-sdk/tree/master/src/
boards/include/boards/pico.h. The SDK defaults to a board name of Raspberry Pi Pico if no other board is specified.
The SDK makes use of CMake to control its build system, see Chapter 8, making use of the pico_stdlib interface library
to aggregate necessary source files to provide capabilities.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/hello_world/serial/CMakeLists.txt Lines 1 - 12
Ê1 add_executable(hello_serial
Ê2 hello_serial.c
Ê3 )
Ê4
Ê5 # Pull in our pico_stdlib which aggregates commonly used features
Ê6 target_link_libraries(hello_serial pico_stdlib)
Ê7
Ê8 # create map/bin/hex/uf2 file etc.
Ê9 pico_add_extra_outputs(hello_serial)
10
11 # add url via pico_set_program_url
12 example_auto_set_url(hello_serial)
Getting started with Raspberry Pi Pico
4.1. Serial input and output on Raspberry Pi Pico 12

The destination for stdout can be changed using CMake directives, with output directed to UART or USB CDC, or to both,
pico_enable_stdio_usb(hello_world 1) ①
pico_enable_stdio_uart(hello_world 0) ②
1. Enable printf output via USB CDC (USB serial)
2. Disable printf output via UART
This means that without changing the C source code, you can change the destination for stdio from UART to USB.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/hello_world/usb/CMakeLists.txt Lines 1 - 20
Ê1 if (TARGET tinyusb_device)
Ê2 add_executable(hello_usb
Ê3 hello_usb.c
Ê4 )
Ê5
Ê6 # Pull in our pico_stdlib which aggregates commonly used features
Ê7 target_link_libraries(hello_usb pico_stdlib)
Ê8
Ê9 # enable usb output, disable uart output
10 pico_enable_stdio_usb(hello_usb 1)
11 pico_enable_stdio_uart(hello_usb 0)
12
13 # create map/bin/hex/uf2 file etc.
14 pico_add_extra_outputs(hello_usb)
15
16 # add url via pico_set_program_url
17 example_auto_set_url(hello_usb)
18 elseif(PICO_ON_DEVICE)
19 message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in
Ê the SDK")
20 endif()
4.2. Build "Hello World"
As we did for the previous "Blink" example, change directory into the hello_world directory inside the pico-examples/build
tree, and run make.
$ cd hello_world
$ make -j4
Scanning dependencies of target ELF2UF2Build
[ 0%] Creating directories for 'ELF2UF2Build'
Ê .
Ê .
[ 33%] Linking CXX executable hello_usb.elf
[ 33%] Built target hello_usb
Ê .
Ê .
[100%] Linking CXX executable hello_serial.elf
[100%] Built target hello_serial
This will build two separate examples programs in the hello_world/serial/ and hello_world/usb/ directories.
Getting started with Raspberry Pi Pico
4.2. Build "Hello World" 13

Amongst other targets, we have now built:
•serial/hello_serial.elf, which is used by the debugger
•serial/hello_serial.uf2, which can be dragged onto the RP2040 USB Mass Storage Device (UART serial binary)
•usb/hello_usb.elf, which is used by the debugger
•usb/hello_usb.uf2, which can be dragged onto the RP2040 USB Mass Storage Device (USB serial binary)
Where hello_serial directs stdio to UART0 on pins GP0 and GP1, and hello_usb directs stdio to USB CDC serial.
WARNING
If you have not initialised the tinyusb submodule in your pico-sdk checkout then the USB CDC serial example will not
work as the SDK will contain no USB functionality.
4.3. Flash and Run "Hello World"
Connect the Raspberry Pi Pico to your Raspberry Pi using a micro-USB cable, making sure that you hold down the
BOOTSEL button to force it into USB Mass Storage Mode. Once it is connected release the BOOTSEL button and if you are
running the Raspberry Pi Desktop it should automatically mount as a USB Mass Storage Device. From here, you can
Drag-and-drop either the hello_serial.uf2 or hello_usb.uf2 onto the Mass Storage Device.
RP2040 will reboot, unmounting itself as a Mass Storage Device, and start to run the flashed code.
However, although the "Hello World" example is now running, we cannot yet see the text. We need to connect our host
computer to the appropriate stdio interface on the Raspberry Pi Pico to see the output.
4.4. See "Hello World" USB output
If you have dragged and dropped the hello_usb.uf2 binary, then the "Hello World" text will be directed to USB serial.
Figure 2. Connecting
the Raspberry Pi to
Raspberry Pi Pico via
USB.
With your Raspberry Pi Pico connected directly to your Raspberry Pi via USB, see Figure 2, you can see the text by
installing minicom:
Getting started with Raspberry Pi Pico
4.3. Flash and Run "Hello World" 14

$ sudo apt install minicom
and open the serial port:
$ minicom -b 115200 -o -D /dev/ttyACM0
You should see Hello, world! printed to the console.
TIP
To exit minicom, use CTRL-A followed by X.
NOTE
If you are intending to using SWD for debugging (see Chapter 6) you need to use a UART based serial connection as
the USB stack will be paused when the RP2040 cores are stopped during debugging, which will cause any attached
USB devices to disconnect.
4.5. See "Hello World" UART output
Alternatively if you dragged and dropped the hello_serial.uf2 binary, then the "Hello World" text will be directed to
UART0 on pins GP0 and GP1. The first thing you’ll need to do to see the text is enable UART serial communications on
the Raspberry Pi host. To do so, run raspi-config,
$ sudo raspi-config
and go to Interfacing Options →Serial and select "No" when asked "Would you like a login shell to be accessible over
serial?" and "Yes" when asked "Would you like the serial port hardware to be enabled?" You should see something like
Figure 3.
Figure 3. Enabling a
serial UART using
raspi-config on
the Raspberry Pi.
Leaving raspi-config you should choose "Yes" and reboot your Raspberry Pi to enable the serial port.
Getting started with Raspberry Pi Pico
4.5. See "Hello World" UART output 15

You should then wire the Raspberry Pi and the Raspberry Pi Pico together with the following mapping:
Raspberry Pi Raspberry Pi Pico
GND (Pin 14) GND (Pin 3)
GPIO15 (UART_RX0, Pin 10) GP0 (UART0_TX, Pin 1)
GPIO14 (UART_TX0, Pin 8) GP1 (UART0_RX, Pin 2)
See Figure 4.
Figure 4. A Raspberry
Pi 4 and the Raspberry
Pi Pico with UART0
connected together.
Once the two boards are wired together if you have not already done so you should install minicom:
$ sudo apt install minicom
and open the serial port:
$ minicom -b 115200 -o -D /dev/serial0
You should see Hello, world! printed to the console.
TIP
To exit minicom, use CTRL-A followed by X.
4.6. Powering the board
You can unplug the Raspberry Pi Pico from USB, and power the board by additionally connecting the Raspberry Pi’s 5V
pin to the Raspberry Pi Pico VSYS pin via a diode, see Figure 5, where in the ideal case the diode would be a Schottky
diode.
Getting started with Raspberry Pi Pico
4.6. Powering the board 16

Figure 5. Raspberry Pi
and Raspberry Pi Pico
connected only using
the GPIO pins.
Whilst it is possible to connect the Raspberry Pi’s 5V pin to the Raspberry Pi Pico VBUS pin, this is not recommended.
Shorting the 5V rails together will mean that the Micro USB cannot be used. An exception is when using the Raspberry
Pi Pico in USB host mode, in this case 5V must be connected to the VBUS pin.
The 3.3V pin is an OUTPUT pin on the Raspberry Pi Pico, you cannot power the Raspberry Pi Pico via this pin, and it
should NOT be connected to a power source.
See the Power section in Hardware design with RP2040 for more information about powering the Raspberry Pi Pico.
Getting started with Raspberry Pi Pico
4.6. Powering the board 17

Chapter 5. Flash Programming with
SWD
Serial Wire Debug (SWD) is a standard interface on Cortex-M-based microcontrollers, which the machine you are using
to develop your code (commonly called the host) can use to reset the board, load code into flash, and set the code
running. Raspberry Pi Pico exposes the RP2040 SWD interface on three pins at the bottom edge of the board. The host
can use the SWD port to access RP2040 internals at any time, so there is no need to manually reset the board or hold
the BOOTSEL button.
Figure 6. The SWD
port is labelled at the
bottom of this Pico
pinout diagram. The
ground (GND)
connection is required
to maintain good
signal integrity
between the host and
the Pico. The SWDIO
pin carries debug
traffic in both
directions, between
RP2040 and the host.
The SWCLK pin keeps
the connection well-
synchronised. These
pins connect to a
dedicated SWD
interface on RP2040,
so you don’t need to
sacrifice any GPIOs to
use the SWD port.
On a Raspberry Pi, you can connect the Pi GPIOs directly to Pico’s SWD port, and load code from there. On other
machines you will need an extra piece of hardware — a debug probe — to bridge a connection on your host machine (like
a USB port) to the SWD pins on the Pico. One of the cheapest ways to do this is to use another Pico as the debug probe,
and this is covered in Appendix A.
This chapter covers how you can connect your machine to Raspberry Pi Pico’s SWD port, and use this to write programs
into flash and run them.
TIP
If you use an IDE like Visual Studio Code (Chapter 7), this can be configured to use SWD automatically behind the
scenes, so you click the play button and the code runs, as though you were running native code on your own
machine.
NOTE
You can also use SWD for interactive debugging techniques like setting breakpoints, stepping through code
execution line-by-line, or even peeking and poking IO registers directly from your machine without writing any
RP2040 software. This is covered in Chapter 6.
5.1. Installing OpenOCD
To access the SWD port on a microcontroller, you need a program on your host machine called a debug translator,
which understands the SWD protocol, and knows how to control the processor (two Cortex-M0+s in the case of
Getting started with Raspberry Pi Pico
5.1. Installing OpenOCD 18

RP2040) inside the microcontroller. The debug translator also knows how to talk to the specific debug probe that you
have connected to the SWD port, and how to program the flash on your device.
This section walks through installing a debug translator called OpenOCD.
TIP
If you have run the pico-setup script on your Raspberry Pi (Chapter 1), OpenOCD is already installed and you can skip
to the next section.
NOTE
These instructions assume you want to build openocd in /home/pi/pico/openocd
$ 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 --recursive --branch rp2040 --depth=1
$ cd openocd
$ ./bootstrap
$ ./configure --enable-ftdi --enable-sysfsgpio --enable-bcm2835gpio
$ make -j4
$ sudo make install
OpenOCD should now be installed, and you can run it as openocd from your terminal.
5.2. SWD Port Wiring
You need to connect wires to the SWD port in order to program and run code on RP2040 via SWD.
Figure 7. A Raspberry
Pi 4 and the Raspberry
Pi Pico with UART and
SWD port connected
together. Both are
jumpered directly back
to the Raspberry Pi 4
without using a
breadboard. Only the
lower three wires in
this diagram are
needed for SWD
access; optionally you
can also connect the
Pi UART, as shown by
the upper 3 wires, to
directly access the
Pico’s serial port.
The default configuration is to have SWDIO on Pi GPIO 24, and SWCLK on GPIO 25 — and can be wired to a Raspberry Pi
Pico with the following mapping,
Getting started with Raspberry Pi Pico
5.2. SWD Port Wiring 19
This manual suits for next models
1
Table of contents
Other Raspberry Pi Microcontroller manuals