arduino-pico-readthedocs-io-en-latest
arduino-pico-readthedocs-io-en-latest
Release 4.4.3
1 Getting Help 3
3 Installation 9
3.1 Installing via Arduino Boards Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Installing via Arduino CLI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Installing via GIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.4 Installing both Arduino and CMake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.5 Uploading Sketches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.6 Uploading the First Sketch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.7 Windows 7 Driver Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.8 Windows 7 Installation Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.9 Uploading Filesystem Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.10 Uploading Sketches with Picotool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.11 Uploading Sketches with Picoprobe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.12 Uploading Sketches with OpenOCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.13 Debugging with Picoprobe/Debugprobe, OpenOCD, and GDB . . . . . . . . . . . . . . . . . . . . . 14
4 IDE Menus 15
4.1 Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2 Flash Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.3 CPU Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.4 Debug Port and Debug Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.5 Generic RP2040 Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.6 Boot Stage 2 Options for Generic RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
i
5.10 CPU Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.11 Debug Port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.12 Debug Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.13 C++ Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.14 Stack Protector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.15 RTTI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.16 USB Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.17 USB Customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.18 IP Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.19 Bluetooth Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.20 Selecting a different core version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.21 Selecting the CPU architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.22 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.23 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.24 Filesystem Uploading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6 Pin Assignments 29
6.1 I2S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6.2 Serial1 (UART0), Serial2 (UART1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6.3 SPI (SPI0), SPI1 (SPI1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6.4 Wire (I2C0), Wire1 (I2C1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
8 Analog I/O 35
8.1 Analog Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8.2 Analog Outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8.3 Analog Output Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
9 Digital I/O 37
9.1 Board-Specific Pins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9.2 Pin Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9.3 Input Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9.4 Output Modes (Pad Strength) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9.5 Tone/noTone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
10 BOOTSEL Button 39
11 EEPROM Library 41
11.1 EEPROM Class API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
11.2 EEPROM Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
ii
14 ADC Input Library 51
14.1 ADC Input API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
17 SoftwareSerial Emulation 57
18 Servo Library 59
18.1 Pulse Width Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
22 Asynchronous Operation 67
22.1 bool transferAsync(const void *send, void *recv, size_t bytes) . . . . . . . . . . . . . . . . . . . . . 67
22.2 bool finishedAsync() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
22.3 void abortAsync() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
23 Examples 69
25 File Systems 73
25.1 Flash Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
25.2 Compatible Filesystem APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
25.3 FatFS File System Caveats and Warnings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
25.4 LittleFS File System Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
25.5 Uploading Files to the LittleFS File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
25.6 Downloading Files from a LittleFS System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
25.7 SD Library Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
25.8 Using Second SPI port for SD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
25.9 Enabling SDIO operation for SD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
25.10 Using VFS (Virtual File System) for POSIX support . . . . . . . . . . . . . . . . . . . . . . . . . . 76
25.11 File system object (LittleFS/SD/SDFS/FatFS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
25.12 Filesystem information structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
25.13 Directory object (Dir) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
25.14 File object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
27 Multicore Processing 87
27.1 Stack Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
27.2 Pausing Cores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
iii
27.3 Communicating Between Cores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
28 Semihosting Support 89
28.1 Running Semihosting on the Development Host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
28.2 SerialSemi - Serial over Semihosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
28.3 SemiFS - Host filesystem access through Semihosting . . . . . . . . . . . . . . . . . . . . . . . . . 89
35 SingleFileDrive 105
35.1 Callbacks, Interrupt Safety, and File Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
35.2 Using SingleFileDrive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
36 FatFSUSB 107
36.1 Callbacks, Interrupt Safety, and File Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
iv
39.2 Enabling Wired Ethernet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
39.3 Adjusting LWIP Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
39.4 Using Interrupt-Driven Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
39.5 Adjusting SPI Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
39.6 Using the WIZnet W5100S-EVB-Pico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
39.7 Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
39.8 Caveats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
39.9 Special Thanks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
40 WiFiClient 117
40.1 flush and stop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
40.2 setNoDelay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
40.3 getNoDelay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
40.4 setSync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
40.5 getSync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
40.6 setDefaultNoDelay and setDefaultSync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
40.7 getDefaultNoDelay and getDefaultSync . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
40.8 Other Function Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
v
46.2 Setting Server Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
46.3 Client sessions (Resuming connections fast) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
46.4 Requiring Client Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
vi
Arduino-Pico Documentation, Release 4.4.3
This is the documentation for the Raspberry Pi Pico Arduino core, Arduino-Pico. Arduino-Pico is a community port of
Arduino to the RP2040 (Raspberry Pi Pico processor) and RP2350 (Raspberry Pi Pico 2 processor), intended to make
it easier and more fun to use and program the Raspberry Pi Pico / RP2040 / RP2350 based boards.
This Arduino core uses a custom toolset with GCC 14.2 and Newlib 4.3 and doesn’t require any system-installed
prerequisites.
For the latest version, always check https://github.com/earlephilhower/arduino-pico
CONTENTS: 1
Arduino-Pico Documentation, Release 4.4.3
2 CONTENTS:
CHAPTER
ONE
GETTING HELP
This is a community supported project and has multiple ways to get assistance. Posting complete details, in a polite
and organized way will get the best response.
For bugs in the Core, or to submit patches, please use the GitHub Issues or GitHub Pull Requests
For general questions/discussions use either GitHub Discussions or live-chat with gitter.im
3
Arduino-Pico Documentation, Release 4.4.3
TWO
First of all, thank you for contributing to the project. It’s a lot of work keeping up with all the different uses of the
RP2040, so the more people working on the code, the better. Your assistance can help the project succeed.
5
Arduino-Pico Documentation, Release 4.4.3
Create a folder called variants/BOARD_NAME and place in a pins_arduino.h file in it that contains your default pin
name mapping (i.e. SPI0/1 pins, UART pins, LED_DEFAULT, etc.). Copying one of the existing ones as a template
can make this task much simpler.
In your git commit be sure to add the newly generated tools/json/XXX.json file as well as the modified
makeboards script and boards.txt, the new pins_arduino.h header you generated, and the Arduino packaging
JSON package/package_pico_index.template.json. You should also add a note in the README.md file listing
your new board.
Submit the updated commit as a PR and, if all goes well, your board will be in on the next core release.
#if defined(PICO_RP2040)
...OG Pico code...
#endif
#if defined(PICO_RP2350)
...Pico 2 code...
#endif
For only RP2350A variants (using the compile options, not the onboard ID register):
For only RP2350B variants (again, at compile time as identified by the selected board and not the chip ID register):
#if defined(PICO_RP2350B)
...48-GPIO version code here
#endif
THREE
INSTALLATION
The Arduino-Pico core can be installed using the Arduino IDE Boards Manager or using git. If you want to simply
write programs for your RP2040 board, the Boards Manager installation will suffice, but if you want to try the latest
pre-release versions and submit improvements, you will need the git installation.
9
Arduino-Pico Documentation, Release 4.4.3
mkdir -p ~/Arduino/hardware/pico
git clone https://github.com/earlephilhower/arduino-pico.git ~/Arduino/hardware/pico/
˓→rp2040
cd ~/Arduino/hardware/pico/rp2040
git submodule update --init
cd pico-sdk
git submodule update --init
cd ../tools
python3 ./get.py
10 Chapter 3. Installation
Arduino-Pico Documentation, Release 4.4.3
12 Chapter 3. Installation
Arduino-Pico Documentation, Release 4.4.3
• https://arduino-pico.readthedocs.io/en/latest/fs.html
The first line creates a file with the USB vendor and ID of the Picoprobe and tells UDEV to give users full access to
it. The second causes udev to load this new rule. Note that you will need to unplug and re-plug in your device the first
time you create this file, to allow udev to make the device node properly.
Once Picoprobe permissions are set up properly, then select the board “Raspberry Pi Pico (Picoprobe)” in the Tools
menu and upload as normal.
The first line creates a file that recognizes all CMSIS-DAP adapters and tells UDEV to give users full access to it. The
second causes udev to load this new rule. Note that you will need to unplug and re-plug in your device the first time
you create this file, to allow udev to make the device node properly.
Once CMSIS-DAP permissions are set up properly, then select the Upload Method “Picoprobe/Debugprobe (CMSIS-
DAP)” in the Tools menu.
14 Chapter 3. Installation
CHAPTER
FOUR
IDE MENUS
4.1 Board
Use the boards menu to select your model of RP2040 board.
There is also a Generic RP2040 board which allows you to individually select things such as flash size or boot2 flash
type. Use this if your board isn’t yet fully supported and isn’t working with the normal Raspberry Pi Pico option.
15
Arduino-Pico Documentation, Release 4.4.3
If you can’t match a chip name in the menu to your flash chip, a simple test can be run to determine which is correct.
Simpily load the Blink example, select the first option in the Boot Stage 2 menu, and upload. If that works, note it and
continue. Iterate through the options and note which ones work. If an option doesn’t work, unplug the chip and hold
the BOOTSEL button down while re-inserting it to enter the ROM uploader mode. (The CPU and flash will not be
harmed if the test fails.)
If one of the custom bootloaders (not Generic SPI /2 or /4) worked, use that option to get best performance. If none
worked other than the Generic SPI /2 or /4 then use that. The /2 options of all models is preferred as it is faster, but
some boards do require /4 on the custom chip interfaces.
When in doubt, Generic SPI /4 should work with any flash chip but is slow.
FIVE
17
Arduino-Pico Documentation, Release 4.4.3
To work around this requires performing two steps and rebooting Windows once. These steps will enable longer file
paths at the Windows OS and the git level.
[env:pico]
platform = raspberrypi
board = pico
framework = arduino
Here, you need to change the platform to take advantage of the features described hereunder and switch to the new core.
[env:pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
board_build.core = earlephilhower
When the support for this core has been merged into mainline PlatformIO, this notice will be removed and a standard
platformio.ini as shown above will work as a base.
; note that download link for toolchain is specific for OS. see https://github.com/
˓→earlephilhower/pico-quick-toolchain/releases.
This is now deprecated and should not be done anymore. Users should delete these platform_packages lines and
update the platform integration by issuing the command
in the PlatformIO CLI. The same can be achieved by using the VSCode PIO Home -> Platforms -> Updates GUI.
The toolchain, which was also renamed to toolchain-rp2040-earlephilhower is downloaded automatically from
the registry. The same goes for the framework-arduinopico toolchain package, which points directly to the Arduino-
Pico Github repository. However, users can still select a custom fork or branch of the core if desired so, as detailed in
a chapter below.
board_build.core = earlephilhower
must be added to the platformio.ini. This controls the core switching logic.
When using Arduino-Pico-only boards like board = rpipico or board = adafruit_feather, this is not needed.
; PSRAM CS is at GP47
build_flags =
-DRP2350_PSRAM_CS=47
; 133MHz
board_build.f_cpu = 133000000L
; equivalent to above
build_flags =
-DDEBUG_RP2040_WIRE
-DDEBUG_RP2040_SPI
-DDEBUG_RP2040_CORE
-DDEBUG_RP2040_PORT=Serial2
; Enable Exceptions
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
5.15 RTTI
RTTI (run-time type information) is disabled by default. To enable it, use
; Enable RTTI
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
; Adafruit TinyUSB
build_flags = -DUSE_TINYUSB
; No USB stack
build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
Note that the special “No USB” setting is also supported, through the shortcut-define
PIO_FRAMEWORK_ARDUINO_NO_USB.
5.18 IP Stack
The lwIP stack can be configured to support only IPv4 (default) or additionally IPv6. To activate IPv6 support, add
; IPv6
build_flags = -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
to the platformio.ini.
to the platformio.ini.
platform_packages =
framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
Whereas the #master can also be replaced by a #branchname or a #commithash. If left out, it will pull the default
branch, which is master.
The file:// and symlink:// pseudo-protocols can also be used instead of https:// to point to a local copy of
the core (with e.g. some modifications) on disk (see documentation).
Note that this can only be done for versions that have the PlatformIO builder script it in, so versions before 1.9.2 are
not supported.
5.22 Examples
The following example platformio.ini can be used for a Raspberry Pi Pico and 0.5MByte filesystem.
[env:pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
; board can use both Arduino cores -- we select Arduino-Pico here
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
The initial project structure should be generated just creating a new project for the Pico and the Arduino framework,
after which the auto-generated platformio.ini can be adapted per above.
5.23 Debugging
With recent updates to the toolchain and OpenOCD, debugging firmwares is also possible.
To specify the debugging adapter, use debug_tool (documentation). Supported values are:
• picoprobe
• cmsis-dap
• jlink
• raspberrypi-swd
• blackmagic
These values can also be used in upload_protocol if you want PlatformIO to upload the regular firmware through
this method, which you likely want.
Especially the PicoProbe method is convenient when you have two Raspberry Pi Pico boards. One of them can be
flashed with the PicoProbe firmware (documentation) and is then connected to the target Raspberry Pi Pico board
(see documentation chapter “Picoprobe Wiring”). Remember that on Windows, you have to use Zadig to also load
“WinUSB” drivers for the “Picoprobe (Interface 2)” device so that OpenOCD can speak to it.
ò Note
Newer PicoProbe firmware versions have dropped the proprietary “PicoProbe” USB communication protocol and
emulate a CMSIS-DAP instead. Meaning, you have to use debug_tool = cmsis-dap for these newer firmwares,
such as those obtained from raspberrypi/picoprobe
With that set up, debugging can be started via the left debugging sidebar and works nicely: Setup breakpoints, inspect
the value of variables in the code, step through the code line by line. When a breakpoint is hit or execution is halted,
you can even see the execution state both Cortex-M0+ cores of the RP2040.
For further information on customizing debug options, like the initial breakpoint or debugging / SWD speed, consult
the documentation.
ò Note
For the BlackMagicProbe debugging probe (as can be e.g., created by simply flashing a STM32F103C8 “Bluepill”
board), you currently have to use the branch fix/rp2040-flash-reliability (or at least commit 1d001bc)
and use the official ARM provided toolchain.
You can obtain precompiled binaries from here. A flashing guide is available here. You then have to configure the
target serial port (“GDB port”) in your project per documentation.
The files you want to upload should be placed in a folder called data inside the project. This can be customized if
needed.
The task “Build Filesystem Image” will take all files in the data directory and create a littlefs.bin file from it using
the mklittlefs tool.
The task “Upload Filesystem Image” will upload the filesystem image to the Pico via the specified upload_protocol.
ò Note
Set the space available for the filesystem in the platformio.ini using e.g., board_build.filesystem_size
= 0.5m, or filesystem creation will fail!
SIX
PIN ASSIGNMENTS
The Raspberry Pi Pico has an incredibly flexible I/O configuration and most built-in peripherals (except for the ADC)
can be used on multiple sets of pins. Note, however, that not all peripherals can use all I/Os. Refer to the RP2040
datasheet or an online pinout diagram for more details.
Additional methods have been added to allow you to select a peripheral’s I/O pins before calling ::begin. This is
especially helpful when using third party libraries: the library doesn’t need to be modified, only your own code in
setup() is needed to adjust pinouts.
6.1 I2S
::setBCLK(pin)
::setDOUT(pin)
For example, because the SD library uses the SPI library, we can make it use a non-default pinout with a simple call
void setup() {
SPI.setRX(4);
(continues on next page)
29
Arduino-Pico Documentation, Release 4.4.3
SEVEN
Some of the core functionality of the RP2040 chip powering the Raspberry Pi Pico is exposed in the RP2040 class
variable rp2040.
31
Arduino-Pico Documentation, Release 4.4.3
The maximum delay_ms allowed in this call is 8300, corresponding to 8.3 seconds. Any higher values will be trun-
cated by the hardware.
7.5 Bootloader
7.5.1 void rp2040.enableDoubleResetBootloader() (Pico/RP2040 only)
Add a call anywhere in the sketch to rp2040.enableDoubleResetBootloader() and the core will check for a
double-tap on reset, and if found will start the USB bootloader.
EIGHT
ANALOG I/O
35
Arduino-Pico Documentation, Release 4.4.3
NINE
DIGITAL I/O
9.5 Tone/noTone
Simple square wave tone generation is possible for up to 8 channels using Arduino standard tone calls. Because these
use the PIO to generate the waveform, they must share resources with other calls such as I2S or Servo objects.
37
Arduino-Pico Documentation, Release 4.4.3
TEN
BOOTSEL BUTTON
The BOOTSEL button on the Pico is not connected to a standard GPIO, so it cannot be read using the usual
digitalRead function. It can, however, be read using a special (relatively slow) method.
The BOOTSEL object implements a simple way of reading the BOOTSEL button. Simply use the object BOOTSEL as a
boolean (as a conditional in an if or while, or assigning to a bool):
39
Arduino-Pico Documentation, Release 4.4.3
ELEVEN
EEPROM LIBRARY
While the Raspberry Pi Pico RP2040 does not come with an EEPROM onboard, we simulate one by using a single 4K
chunk of flash at the end of flash space.
Note that this is a simulated EEPROM and will only support the number of writes as the onboard flash chip,
not the 100,000 or so of a real EEPROM. Therefore, do not frequently update the EEPROM or you may prematurely
wear out the flash.
11.1.4 EEPROM.commit()
Writes the updated data to flash, so next reboot it will be readable.
11.1.5 EEPROM.end()
EEPROM.commit() and frees all memory used. Need to call EEPROM.begin() before the EEPROM can be used again.
41
Arduino-Pico Documentation, Release 4.4.3
11.1.8 EEPROM.length()
Returns the length of the EEPROM (i.e. the value specified in EEPROM.begin() ).
TWELVE
While the RP2040 chip on the Raspberry Pi Pico does not include a hardware I2S device, it is possible to use the PIO
(Programmable I/O) state machines to implement one dynamically.
Digital audio input and output are supported at 8, 16, 24, and 32 bits per sample.
Theoretically up to 6 I2S ports may be created, but in practice there may not be enough resources (DMA, PIO SM) to
actually create and use so many.
Create an I2S port by instantiating a variable of the I2S class specifying the direction. Configure it using API calls
below before using it.
12.1.2 I2S(INPUT)
Creates an I2S input port. Needs to be connected up to the desired pins (see below) and started before any input can
happen.
12.1.3 I2S(INPUT_PULLUP)
Creates a bi-directional I2S input and output port. Needs to be connected up to the desired pins (see below) and started
before any input or output can happen.
43
Arduino-Pico Documentation, Release 4.4.3
THIRTEEN
Relatively good quality analog audio out can be generated by using the RP2040 onboard PWM hardware. It can drive
an amplifier for speaker output, or be decoupled using a capacitor to drive a headphone-level signal. Mono and stereo
signals can be generated.
All samples are sent to the PWMAudio library as signed 16 bits per sample. Due to frequency limitations of the PWM
hardware, at higher bit rates these 16-bits will automatically be reduced to the maximum the hardware can handle.
Multiple PWMAudio devices are supported, depending on availability of DMA channels.
The interface for the PWMAudio device is very similar to the I2S device, and most code can be ported simply by
instantiating a PWMAudio object in lieu of an I2S object.
49
Arduino-Pico Documentation, Release 4.4.3
FOURTEEN
The ADC pins can be sampled and recorded by an application using the same interface as the I2S or PWM Audio
libraries. This allows analog devices which need to be periodically sampled to be read by applications, easily, such as:
• Analog electret microphones
• Potentiometers
• Light dependent resistors (LDR), etc.
Up to 4 analog samples can be recorded by the hardware (A0 . . . A3), and all recording is done at 16-bit levels (but be
aware that the ADC in the Pico will only ever return values between 0. . . 4095).
The interface for the ADCInput device is very similar to the I2S input device, and most code can be ported simply by
instantiating a ADCInput object in lieu of an I2S input object and choosing the pins to record.
Since this uses the ADC hardware, no analogRead or analogReadTemp calls are allowed while in use.
51
Arduino-Pico Documentation, Release 4.4.3
A0 will be sampled at 0ms, 1ms, 2ms, etc. and A1 will be sampled at 0.5ms 1.5ms, 2.5ms, etc. Each input is sampled
at the proper frequency but offset in time since there is only one active ADC at a time.
FIFTEEN
The Arduino-Pico core implements a software-based Serial-over-USB port using the USB ACM-CDC model to support
a wide variety of operating systems.
Serial is the USB serial port, and while Serial.begin() does allow specifying a baud rate, this rate is ignored since
it is USB-based. (Also be aware that this USB Serial port is responsible for resetting the RP2040 during the upload
process, following the Arduino standard of 1200bps = reset to bootloader).
The RP2040 provides two hardware-based UARTS with configurable pin selection.
Serial1 is UART0, and Serial2 is UART1.
Configure their pins using the setXXX calls prior to calling begin()
Serial1.setRX(pin);
Serial1.setTX(pin);
Serial1.begin(baud);
The size of the receive FIFO may also be adjusted from the default 32 bytes by using the setFIFOSize call prior to
calling begin()
Serial1.setFIFOSize(128);
Serial1.begin(baud);
The FIFO is normally handled via an interrupt, which reduced CPU load and makes it less likely to lose characters.
For applications where an IRQ driven serial port is not appropriate, use setPollingMode(true) before calling
begin()
Serial1.setPollingMode(true);
Serial1.begin(300)
For detailed information about the Serial ports, see the Arduino Serial Reference .
15.1 Inversion
Serial1 and Serial2 can both support inverted input and/or outputs via the methods Serial1/
2::setInvertRX(bool invert) and Serial1/2::setInvertTX(bool invert) and Serial1/
2::serInvertControl(bool invert).
53
Arduino-Pico Documentation, Release 4.4.3
SIXTEEN
Equivalent to the Arduino SoftwareSerial library, an emulated UART using one or two PIO state machines is included
in the Arduino-Pico core. This allows for up to 4 bidirectional or up to 8 unidirectional serial ports to be run from the
RP2040 without requiring additional CPU resources.
Instantiate a SerialPIO(txpin, rxpin, fifosize) object in your sketch and then use it the same as any other
serial port. Even, odd, and no parity modes are supported, as well as data sizes from 5- to 8-bits. Fifosize, if not
specified, defaults to 32 bytes.
To instantiate only a serial transmit or receive unit, pass in SerialPIO::NOPIN as the txpin or rxpin.
For example, to make a transmit-only port on GP16
For detailed information about the Serial ports, see the Arduino Serial Reference .
16.1 Inversion
SoftwareSerial and SerialPIO can both support inverted input and/or outputs via the methods setInvertRX(bool
invert) and setInvertTX(bool invert).
55
Arduino-Pico Documentation, Release 4.4.3
SEVENTEEN
SOFTWARESERIAL EMULATION
A SoftwareSerial wrapper is included to provide plug-and-play compatibility with the Arduino Software Serial
library. Use the normal #include <SoftwareSerial.h> to include it. The following differences from the Arduino
standard are present:
• All ports are always listening
• listen call is a no-op
• isListening() always returns true
57
Arduino-Pico Documentation, Release 4.4.3
EIGHTEEN
SERVO LIBRARY
A hardware-based servo controller is provided using the Servo library. It utilizes the PIO state machines and generates
the appropriate servo control pulses, glitch-free and jitter-free (within crystal limits).
Up to 8 Servos can be controlled in parallel assuming no other tasks require the use of a PIO machine.
See the Arduino standard Servo documentation for detailed usage instructions. There is also an included sweep exam-
ple.
59
Arduino-Pico Documentation, Release 4.4.3
NINETEEN
The RP2040 has two hardware SPI interfaces, spi0 (SPI) and spi1 (SPI1). These interfaces are supported by the
SPI library in master mode.
SPI pinouts can be set before SPI.begin() using the following calls:
Note that the CS pin can be hardware or software controlled by the sketch. When software controlled, the setCS() call
is ignored.
The Arduino SPI documentation gives a detailed overview of the library, except for the following RP2040-specific
changes:
• SPI.begin(bool hwCS) can take an options hwCS parameter.
By passing in true for hwCS the sketch does not need to worry about asserting and deasserting the CS pin between
transactions. The default is false and requires the sketch to handle the CS pin itself, as is the standard way in Arduino.
• The interrupt calls (attachInterrupt, and detachInterrpt) are not implemented.
61
Arduino-Pico Documentation, Release 4.4.3
TWENTY
Similar to SoftwareSerial, SoftwareSPI creates a PIO based SPI interface that can be used in the same manner
as the hardware SPI devices. The constructor takes the pins desired, which can be any GPIO pins with the rule that if
hardware CS is used then it must be on pin SCK + 1. Construct a SoftwareSPI object in your code as follows and
use it as needed (i.e. pass it into SD.begin(_CS, softwareSPI);
#include <SoftwareSPI.h>
SoftwareSPI softSPI(_sck, _miso, _mosi); // no HW CS support, any selection of pins can␣
˓→be used
63
Arduino-Pico Documentation, Release 4.4.3
TWENTYONE
Slave mode operation is also supported on either SPI interface. Two callbacks are needed in your app, set through
SPISlave.onDataRecv and SPISlave.onDataSent, in order to consunme the received data and provide data to
transmit.
• The callbacks operate at IRQ time and may be called very frequently at high SPI frequencies. So, make then
small, fast, and with no memory allocations or locking.
65
Arduino-Pico Documentation, Release 4.4.3
TWENTYTWO
ASYNCHRONOUS OPERATION
Applications can use asynchronous SPI calls to allow for processing while long-running SPI transfers are being per-
formed. For example, a game could send a full screen update out over SPI and immediately start processing the next
frame without waiting for the first one to be sent. DMA is used to handle the transfer to/from the hardware freeing the
CPU from bit-banging or busy waiting.
Note that asynchronous operations can not be intersped with normal, synchronous ones. transferAsync should still
occur after a beginTransaction() and when finishedAsync() returns true then endTransaction() should
also be called.
All buffers need to be valid throughout the entire operation. Read data cannot be accessed until the transaction is
completed and can’t be “peeked” at while the operation is ongoing.
67
Arduino-Pico Documentation, Release 4.4.3
TWENTYTHREE
EXAMPLES
See the SPItoMyself and SPItoMyselfAsync examples for a complete Master and Slave application.
69
Arduino-Pico Documentation, Release 4.4.3
TWENTYFOUR
The RP2040 has two I2C devices, i2c0 (Wire) and i2c1 (Wire1).
The default pins for Wire and Wire1 vary depending on which board you’re using. (Here are the pinout diagrams for
Pico and Adafruit Feather.)
You may change these pins before calling Wire.begin() or Wire1.begin() using:
Be sure to use pins labeled I2C0 for Wire and I2C1 for Wire1 on the pinout diagram for your board, or it won’t work.
Other than that, the API is compatible with the Arduino standard. Both master and slave operation are supported.
Master transmissions are buffered (up to 256 bytes) and only performed on endTransmission, as is standard with
modern Arduino Wire implementations.
For more detailed information, check the Arduino Wire documentation .
71
Arduino-Pico Documentation, Release 4.4.3
The first call to an asynchronous write/read operation allocates the required DMA channels and internal buffer. If
desired, call end() to free these resources.
TWENTYFIVE
FILE SYSTEMS
The Arduino-Pico core supports using some of the onboard flash as a file system, useful for storing configuration data,
output strings, logging, and more. It also supports using SD cards as another (FAT32) filesystem, with an API that’s
compatible with the onboard flash file system.
|----|---------------------|-------------|----|
^ ^ ^ ^
OTA Sketch File system EEPROM
The file system size is configurable via the IDE menus, from 64k up to 15MB (assuming you have an RP2040 board
with that much flash)
Note: to use any of file system functions in the sketch, add the following include to the sketch:
73
Arduino-Pico Documentation, Release 4.4.3
^C (break)
(gdb) dump binary memory littlefs.bin &_FS_start &_FS_end
It may take a few seconds as GDB reads out the flash to the file. Once the raw file is downloaded it can be extracted
using the mklittlefs tool from the BASH/Powershell/command line
The defaults built into mklittlefs should be appropriate for normal LittleFS filesystems built on the device or using
the upload tool.
SD.begin(cspin, SPI1);
..code:: cpp
SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
No other changes are required in the application to take advantage of this high performance mode.
#include <VFS.h>
#include <LittleFS.h>
void setup() {
LittleFS.begin();
VFS.root(LittleFS);
FILE *fp = fopen("/thisfilelivesonflash.txt", "w");
fprintf(fp, "Hello!\n");
fclose(fp);
}
Multiple filesystems can be VFS.map() into the VFS namespace under different directory names. For example, the
following will make files on /sd reside on an externalSD card and files on /lfs live in internal flash.
#include <VFS.h>
#include <LittleFS.h>
#include <SDFS.h>
void setup() {
LittleFS.begin();
SDFS.begin();
VFS.map("/lfs", LittleFS);
VFS.map("/sd", SDFS);
FILE *onSD = fopen("/sd/thislivesonsd.txt", "wb");
....
}
SDFSConfig c2;
c2.setCSPin(12);
SDFS.setConfig(c2);
FatFSConfig c3;
(continues on next page)
This method allows you to configure the parameters of a filesystem before mounting. All filesystems have their own
*Config (i.e. SDFSConfig or LittleFSConfig with their custom set of options. All filesystems allow explicitly
enabling/disabling formatting when mounts fail. If you do not call this setConfig method before perforing begin(),
you will get the filesystem’s default behavior and configuration. By default, LittleFS and FatFS will autoformat the
filesystem if it cannot mount it, while SDFS will not. FatFS will also use the built-in FTL to support 512 byte sectors
and higher write lifetime.
25.11.2 begin
SDFS.begin()
or LittleFS.begin()
This method mounts file system. It must be called before any other FS APIs are used. Returns true if file system was
mounted successfully, false otherwise.
Note that LittleFS will automatically format the filesystem if one is not detected. This is configurable via setConfig.
25.11.3 end
SDFS.end()
or LittleFS.end()
25.11.4 format
SDFS.format()
or LittleFS.format()
Formats the file system. May be called either before or after calling begin. Returns true if formatting was successful.
25.11.5 open
SDFS.open(path, mode)
or LittleFS.open(path, mode)
Opens a file. path should be an absolute path starting with a slash (e.g. /dir/filename.txt). mode is a string
specifying access mode. It can be one of “r”, “w”, “a”, “r+”, “w+”, “a+”. The meaning of these modes is the same as
for the fopen C function.
Returns File object. To check whether the file was opened successfully, use the boolean operator.
25.11.6 exists
SDFS.exists(path)
or LittleFS.exists(path)
25.11.7 mkdir
SDFS.mkdir(path)
or LittleFS.mkdir(path)
25.11.8 rmdir
SDFS.rmdir(path)
or LittleFS.rmdir(path)
25.11.9 openDir
SDFS.openDir(path)
or LittleFS.openDir(path)
25.11.10 remove
SDFS.remove(path)
or LittleFS.remove(path)
Deletes the file given its absolute path. Returns true if file was deleted successfully.
25.11.11 rename
SDFS.rename(pathFrom, pathTo)
or LittleFS.rename(pathFrom, pathTo)
Renames file from pathFrom to pathTo. Paths must be absolute. Returns true if file was renamed successfully.
25.11.12 info
FSInfo fs_info;
or LittleFS.info(fs_info);
Fills FSInfo structure with information about the file system. Returns true if successful, false otherwise. ìnfo()
has been updated to support filesystems greater than 4GB and FSInfo64 and info64() have been discarded.
This is the structure which may be filled using FS::info method. - totalBytes — total size of useful data on the file
system - usedBytes — number of bytes used by files - blockSize — filesystem block size - pageSize — filesystem
logical page size - maxOpenFiles — max number of files which may be open simultaneously - maxPathLength —
max file name length (including one byte for zero termination)
The SD, SDFS, and LittleFS filesystems support a file timestamp, updated when the file is opened for writing. By de-
fault, the Pico will use the internal time returned from time(NULL) (i.e. local time, not UTC, to conform to the existing
FAT filesystem), but this can be overridden to GMT or any other standard you’d like by using setTimeCallback(). If
your app sets the system time using NTP before file operations, then you should not need to use this function. However,
if you need to set a specific time for a file, or the system clock isn’t correct and you need to read the time from an
external RTC or use a fixed time, this call allows you do to so.
In general use, with a functioning time() call, user applications should not need to use this function.
25.13.1 next
Returns true while there are files in the directory to iterate over. It must be called before calling fileName(),
fileSize(), and openFile() functions.
25.13.2 fileName
Returns the name of the current file pointed to by the internal iterator.
25.13.3 fileSize
Returns the size of the current file pointed to by the internal iterator.
25.13.4 fileTime
Returns the time_t write time of the current file pointed to by the internal iterator.
25.13.5 fileCreationTime
Returns the time_t creation time of the current file pointed to by the internal iterator.
25.13.6 isFile
Returns true if the current file pointed to by the internal iterator is a File.
25.13.7 isDirectory
Returns true if the current file pointed to by the internal iterator is a Directory.
25.13.8 openFile
This method takes mode argument which has the same meaning as for SDFS/LittleFS.open() function.
25.13.9 rewind
Resets the internal pointer to the start of the directory.
25.14.1 seek
file.seek(offset, mode)
This function behaves like fseek C function. Depending on the value of mode, it moves current position in a file as
follows:
• if mode is SeekSet, position is set to offset bytes from the beginning.
• if mode is SeekCur, current position is moved by offset bytes.
• if mode is SeekEnd, position is set to offset bytes from the end of the file.
Returns true if position was set successfully.
25.14.2 position
file.position()
25.14.3 size
file.size()
25.14.4 name
String name = file.name();
Returns short (no-path) file name, as const char*. Convert it to String for storage.
25.14.5 fullName
// Filesystem:
// testdir/
// file1
Dir d = LittleFS.openDir("testdir/");
(continues on next page)
25.14.6 getLastWrite
Returns the file last write time, and only valid for files opened in read-only mode. If a file is opened for writing, the
returned time may be indeterminate.
25.14.7 getCreationTime
Returns the file creation time, if available.
25.14.8 isFile
bool amIAFile = file.isFile();
25.14.9 isDirectory
bool amIADir = file.isDir();
Returns true if this File points to a directory (used for emulation of the SD.* interfaces with the openNextFile method).
25.14.10 close
file.close()
Close the file. No other operations should be performed on File object after close function was called.
Opens the next file in the directory pointed to by the File. Only valid when File.isDirectory() == true.
Resets the openNextFile pointer to the top of the directory. Only valid when File.isDirectory() == true.
TWENTYSIX
Two USB stacks are present in the core. Users can choose the simpler Pico-SDK version or the more powerful Adafruit
TinyUSB library. Use the Tools->USB Stack menu to select between the two.
#include <Adafruit_TinyUSB.h>
If you need to be compatible with the other USB stack, you can use an ifdef:
#ifdef USE_TINYUSB
#include <Adafruit_TinyUSB.h>
#endif
85
Arduino-Pico Documentation, Release 4.4.3
Also, this stack requires sketches to manually call Serial.begin(115200) to enable the USB serial port and auto-
matic sketch upload from the IDE. If a sketch is run without this command in setup(), the user will need to use the
standard “hold BOOTSEL and plug in USB” method to enter program upload mode.
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID 1
#define CFG_TUD_MIDI 1
#define CFG_TUD_VENDOR 1
this configuration file defines the maximum number of USB CDC (serial) devices as 1. Hence, the example sketch
cdc_multi.ino that is delivered with the library will not work, it will only create one USB CDC device instead of two.
It will however work when the above CFG_TUD_CDC macro is defined to 2 instead of 1.
To do such a modification when using the Arduino IDE, the file can be locally modified in the Arduino core’s package
files. The base path can be found per this article, then navigate further to the packages/rp2040/hardware/rp2040/
<core version>/libraries/Adafruit_TinyUSB_Arduino folder to find the Adafruit TinyUSB library.
When using PlatformIO, one can also make use of the feature that TinyUSB allows redirecting the configuration file to
another one if a certain macro is set.
#ifdef CFG_TUSB_CONFIG_FILE
#include CFG_TUSB_CONFIG_FILE
#else
#include "tusb_config.h"
#endif
build_flags =
-DUSE_TINYUSB
-DCFG_TUSB_CONFIG_FILE=\"custom_tusb_config.h\"
-Iinclude/
and further add create the file include/custom_tusb_config.h as a copy of the original tusb_config_rp2040.h
but with the needed modifications.
Note: Some configuration file changes have no effect because upper levels of the library don’t properly support them.
In particular, even though the maximum number of HID devices can be set to 2, and two Adafruit_USBD_HID can be
created, it will not cause two HID devices to actually show up, because of code limitations.
TWENTYSEVEN
MULTICORE PROCESSING
The RP2040 chip has 2 cores that can run independently of each other, sharing peripherals and memory with each
other. Arduino code will normally execute only on core 0, with the 2nd core sitting idle in a low power state.
By adding a setup1() and loop1() function to your sketch you can make use of the second core. Anything called
from within the setup1() or loop1() routines will execute on the second core.
setup() and setup1() will be called at the same time, and the loop() or loop1() will be started as soon as the
core’s setup() completes (i.e. not necessarily simultaneously!).
See the Multicore.ino example in the rp2040 example directory for a quick introduction.
87
Arduino-Pico Documentation, Release 4.4.3
TWENTYEIGHT
SEMIHOSTING SUPPORT
Using special debugger breakpoints and commands, the Pico can read and write to the debugging console as well as
read and write files on a development PC. The Semihosting library allows applications to use the semihosting support
as a normal filesystem or serial port.
NOTE Semihosting only works when connected to an OpenOCD + GDB debug session. Running an application
compiled for Semihosting without the debugger will cause a panic and hang the chip.
As of now, only ARM has support for Semihosting.
At this point load and run your ELF application as normal. Again, all SerialSemi output will go to the OpenOCD
window, not GDB.
See the hellosemi example in the Semihosting library.
89
Arduino-Pico Documentation, Release 4.4.3
SemiFS.begin();
File f = SemiFS.open("debug.dmp", "w");
f.write(buffer, size);
f.close();
SerialSemi.printf("Debug dump now available on host.\n");
TWENTYNINE
Applications running on the Pico can be profiled using GNU GPROF to show where the CPU is using its time on
the device and how often certain functions are called. It does this by recompiling the application and adding a small
preamble to each function built to identify what functions call what others (and how frequently). It also uses the
SYSTICK exception timer to sample and record the PC 10,000 times per second. When an application is complete, the
recorded date can be dumped to the host PC as a gmon.,out file which can be processed by arm-none-eabi-gprof
into useful date.
s histogram of PCs and tally of function caller/callees can take a significant amount of RAM, from 100KB to 10000KB
depending on the size of the application. As such, while the RP2040 may be able to profile small applications, this
is only really recommended on the RP2350 with external PSRAM. The profiler will automatically use PSRAM when
available. Call rp2040.getProfileMemoryUsage() to get the memory allocated at runtime.
Profiling also adds processing overhead in terms of the periodic sampling and the function preambles. In most cases
there is no reason to enable (and many reasons to disable) profiling when an application is deployed to the field.
To transfer the GMON.OUT data from the Pico to the host HP can be done by having the application write it out to an SD
card or a LittleFS filesystem which is then manually dumped, but for ease of use semihosting can be used to allow the
Pico (under the control of OpenOCD and GDB) to write the gmon.out file directly on the host PC, ready for use.
NOTE Semihosting only works when connected to an OpenOCD + GDB debug session. Running an application
compiled for Semihosting without the debugger will cause a panic and hang the chip.
As of now, only ARM has support for Semihosting or GPROF.
#include <SemiFS.h>
void setup() {
SerialSemi.printf("BEGIN\n");
do_some_work_that_takes_a_long_time_with_many_function_calls();
// Do lots of other work...
// Now all done...
(continues on next page)
91
Arduino-Pico Documentation, Release 4.4.3
THIRTY
The RP2350 chip (present on the Raspberry Pi Pico 2 board and many others) is supported by the core with some minor
caveats:
• PSRAM is supported via a new pmalloc call and PSRAM variable decorator.
• Both RP2350A and RP2350B (48 GPIOs) are supported.
93
Arduino-Pico Documentation, Release 4.4.3
THIRTYONE
The RP2350 chip in the Raspberry Pi Pico 2, and other RP2350 boards, supports an external interface to PSRAM.
When a PSRAM chip is attached to the processor (please note that there is none on the Pico 2 board, but iLabs and
SparkFun boards, among others, do have it), up to 16 megabytes of additional memory can be used by the chip.
While this external RAM is slower than the built-in SRAM, it is still able to be used in any place where normal RAM
would be used (other than for memory-mapped functions and statically initialized variables).
When present, PSRAM can be used in two ways: for specific instantiated variables, or through a malloc-like access
method. Both can be used in any single application.
...
float weights[4000] PSRAM; // Place an array of 4000 floats in PSRAM
char samplefile[1'000'000] PSRAM; // Allocate 1M for WAV samples in PSRAM
...
These variables can be used just like normal ones, no special handling is required. For example:
void initBuff() {
bzero(buff, sizeof(buff));
for (int i = 0; i < 4 *1024 * 1024; i += 4096) {
buff[i] = rand();
}
}
The only restriction is that these variables may not be initialized statically. The following example will NOT work:
95
Arduino-Pico Documentation, Release 4.4.3
Simply replace a malloc or calloc with pmalloc or pcalloc to use the PSRAM heap. Other calls, such as free
and realloc “just work” and do not need to be modified (they check where the passed-in pointer resides and do the
right thing automatically).
For example, to create and modify large buffer in PSRAM:
void ex() {
int *buff;
// Ignoring OOM error conditions in example for brevity
buff = (int *)pmalloc(10000 * sizeof(*buff));
// Something happened and we need more space, so...
buff = (int *)realloc(buff, 20000 * sizeof(*buff)); // buff now has 20K elements
for (int i = 0; i < 20000; i++) {
buff[i] = i;
}
// Do some work, now we're done
free(buff);
}
C++ objects can be allocated in PSRAM using “placement new” constructors. Note that this will only place immediate
object data in PSRAM: if the object creates any other objects via new those objects will be placed in normal RAM
unless the object also uses placement new constructors.
THIRTYTWO
As of the Pico-SDK version 1.5.0, the PicoW has BETA Bluetooth support.
97
Arduino-Pico Documentation, Release 4.4.3
THIRTYTHREE
The PicoW can connect to a Bluetooth Classic or Bluetooth BLE keyboard, mouse, or joystick and receive input events
from it. As opposed to the Keyboard, Mouse, and Joystick libraries, which make the PicoW into a peripheral others
can use, this lets the PicoW use the same kinds of peripherals in a master rols.
99
Arduino-Pico Documentation, Release 4.4.3
HIDKeyStream keystream;
void joystickCB(void *cbdata, int x, int y, int z, int rz, uint8_t hat, uint32_t␣
˓→buttons) {
THIRTYFOUR
The PicoW can be used as a Bluetooth Audio sink or source with the BluetoothAudio class. Operation is generally
handled “automatically” in the background so while the audio is playing or streaming the main application can perform
other operations (like displaying playback info, polling buttons for controls, etc.)
#include <BluetoothAudio.h>
...
Note about CPU usage: Bluetooth SBC audio is a compressed format. That means that it takes non-trivial amounts
of CPU to compress on send, or decompress on receive. Transmitting precompressed audio from, say, MP3 or AAC,
requires first decompressing the source file into raw PCM and then re-compressing them in the SBC format. You may
want to consider overclocking in this case to avoid underflow.
34.1 A2DPSink
This class implements slave sink-mode operation with player control (play, pause, etc.) and can play the received and
decoded SBC audio to PWMAudio, I2S, or a user-created BluetoothAudioConsumer` class.
The A2DPSink.ino example demonstrates turning a PicoW into a Bluetooth headset with PWMAudio.
34.2 A2DPSource
This class implements a master source-mode SBC Bluetooth A2DP audio connection which transmits audio using the
standard Stream interface (like I2S or PWMAudio. The main application connects to a Bluetooth speaker and then
writes samples into a buffer that’s automatically transmitted behind the scenes.
The A2DPSource.ino example shows how to connect to a Bluetooth speaker, transmit data, and respond to commands
from the speaker.
103
Arduino-Pico Documentation, Release 4.4.3
THIRTYFIVE
SINGLEFILEDRIVE
USB drive mode is supported through the SingleFileDrive class which allows the Pico to emulate a FAT-formatted
USB stick while preserving the onboard LittleFS filesystem. A single file can be exported this way without needing to
use FAT as the onboard filesystem (FAT is not appropriate for flash-based devices without complicated wear leveling
because of the update frequency of the FAT tables).
This emulation is very simple and only allows for the reading of the single file, and deleting it.
#include <LittleFS.h>
#include <SingleFileDrive.h>
105
Arduino-Pico Documentation, Release 4.4.3
void setup() {
LittleFS.begin();
singleFileDrive.onPlug(myPlugCB);
singleFileDrive.onUnplug(myUnplugCB);
singleFileDrive.onDelete(myDeleteCB);
singleFileDrive.begin("littlefsfile.csv", "Data Recorder.csv");
// ... rest of setup ...
}
void loop() {
// Take some measurements, delay, etc.
if (okay-to-write) {
noInterrupts();
File f = LittleFS.open("littlefsfile.csv", "a");
f.printf("%d,%d,%d\n", data1, data2, data3);
f.close();
interrupts();
}
}
THIRTYSIX
FATFSUSB
When the onboard flash memory is used as a FatFS filesystem, the FatFSUSB can be used to allow exporting it to a
PC as a standard memory stick. The PC can then access, add, and remove files as if the Pico was a USB memory stick,
and upon ejection the Pico can access any new files just as if it made them itself.
(Note, if you are using LittleFS then you need to use SingleFileDrive to export a single file, not this class, because
the PC does not understand the LittleFS disk format.)
107
Arduino-Pico Documentation, Release 4.4.3
THIRTYSEVEN
FREERTOS SMP
The SMP (multicore) port of FreeRTOS is included with the core. This allows complex task operations and real
preemptive multithreading in your sketches. While the setup1 and loop1 way of multitasking is simplest for most
folks, FreeRTOS is much more powerful.
#include <FreeRTOS.h>
37.3 Caveats
While the core now supports FreeRTOS, most (probably all) Arduino libraries were not written to support preemptive
multithreading. This means that all calls to a particular library should be made from a single task.
In particular, the LittleFS and SDFS libraries can not be called from different threads. Do all File operations from
a single thread or else undefined behavior (aka strange crashes or data corruption) can occur.
109
Arduino-Pico Documentation, Release 4.4.3
THIRTYEIGHT
WiFi is supported on the Raspberry Pi Pico W by selecting the “Raspberry Pi Pico W” board in the Boards Manager.
It is generally compatible with the Arduino WiFi library and the ESP8266 Arduino WiFi library.
Enable WiFi support by selecting the Raspberry Pi Pico W board in the IDE and adding #include <WiFi.h> in your
sketch.
111
Arduino-Pico Documentation, Release 4.4.3
The WiFi library borrows much work from the ESP8266 Arduino Core , especially the WiFiClient and WiFiServer
classes.
THIRTYNINE
Wired Ethernet interfaces are supported for all the internal networking libraries (WiFiClient, WiFiClientSecure,
WiFiServer, WiFiServerSecure, WiFiUDP, WebServer, Updater, HTTPClient, etc.).
Using these wired interfaces is very similar to using the Pico-W WiFi so most examples in the core only require minor
modifications to use a wired interface.
In your setup() you may adjust the SPI pins you’re using to match your hardware (be sure they are legal for the
RP2040!), or skip this if you’re using the default ones:
void setup() {
SPI.setRX(0);
SPI.setCS(1);
SPI.setSCK(2);
SPI.setTX(3);
....
}
And finally replace the WiFi.begin() and WiFi.connected() calls with eth.begin() and eth.connected():
void setup() {
....
// WiFi.begin(SSID, PASS)
eth.begin();
(continues on next page)
113
Arduino-Pico Documentation, Release 4.4.3
//while (!WiFi.connected()) {
while (!eth.connected()) {
Serial.print(".");
}
....
}
#include <W5100lwIP.h>
Wiznet5100lwIP eth(SS /* Chip Select*/, SPI /* SPI interface */, 17 /* Interrupt GPIO */␣
˓→);
#include <W5500lwIP.h>
Wiznet5500lwIP eth(1);
void setup() {
eth.setSPISpeed(30000000);
lwipPollingPeriod(3);
...
(continues on next page)
#include <W5100lwIP.h>
Wiznet5100lwIP eth(17, SPI, 21); // Note chip select is **17**
void setup() {
// Set SPI to the onboard Wiznet chip
SPI.setRX(16);
SPI.setCS(17);
SPI.setSCK(18);
SPI.setTX(19);
...
eth.begin();
...
}
39.8 Caveats
The same restrictions for WiFi apply to these Ethernet classes, namely:
• Only core 0 may run any networking related code.
• In FreeRTOS, only the setup and loop task can call networking libraries, not any tasks.
FORTY
WIFICLIENT
40.2 setNoDelay
setNoDelay(nodelay)
With nodelay set to true, this function will to disable Nagle algorithm.
This algorithm is intended to reduce TCP/IP traffic of small packets sent over the network by combining a number
of small outgoing messages, and sending them all at once. The downside of such approach is effectively delaying
individual messages until a big enough packet is assembled.
Example:
117
Arduino-Pico Documentation, Release 4.4.3
client.setNoDelay(true);
40.3 getNoDelay
Returns whether NoDelay is enabled or not for the current connection.
40.4 setSync
This is an experimental API that will set the client in synchronized mode. In this mode, every write() is flushed. It
means that after a call to write(), data are ensured to be received where they went sent to (that is flush semantic).
When set to true in WiFiClient implementation,
• It slows down transfers, and implicitly disable the Nagle algorithm.
• It also allows to avoid a temporary copy of data that otherwise consumes at most TCP_SND_BUF = (2 * MSS) bytes
per connection,
40.5 getSync
Returns whether Sync is enabled or not for the current connection.
FORTYONE
SERVER CLASS
41.1 accept
Method accept() returns a waiting client connection. accept() is documented for the Arduino Ethernet library.
41.2 available
see accept
available in the ESP8266WiFi library’s WiFiServer class doesn’t work as documented for the Arduino WiFi library.
It works the same way as accept.
121
Arduino-Pico Documentation, Release 4.4.3
41.4 setNoDelay
setNoDelay(nodelay)
With nodelay set to true, this function will to disable Nagle algorithm.
This algorithm is intended to reduce TCP/IP traffic of small packets sent over the network by combining a number
of small outgoing messages, and sending them all at once. The downside of such approach is effectively delaying
individual messages until a big enough packet is assembled.
Example:
server.begin();
server.setNoDelay(true);
By default, nodelay value will depends on global WiFiClient::getDefaultNoDelay() (currently false by default).
However, a call to wiFiServer.setNoDelay() will override NoDelay for all new WiFiClient provided by the
calling instance (wiFiServer).
FORTYTWO
UDP CLASS
123
Arduino-Pico Documentation, Release 4.4.3
FORTYTHREE
NTP allows the Pico to set its internal clock using the internet, and is required for secure connections because the
certificates used have valid date stamps.
After WiFi.begin() use NTP.begin(s1) or NTP.begin(s1, s2) to use one or two NTP servers (common ones are
pool.ntp.org and time.nist.gov) .
WiFi.begin("ssid", "pass");
NTP.begin("pool.ntp.org", "time.nist.gov");
Either names or IPAddress may be used to identify the NTP server to use.
It may take seconds to minutes for the system time to be updated by NTP, depending on the server. It is often useful to
check that time(NULL) returns a sane value before continuing a sketch:
void setClock() {
NTP.begin("pool.ntp.org", "time.nist.gov");
void setClock() {
NTP.begin("pool.ntp.org", "time.nist.gov");
NTP.waitSet();
time_t now = time(nullptr);
struct tm timeinfo;
(continues on next page)
125
Arduino-Pico Documentation, Release 4.4.3
void setClock() {
NTP.begin("pool.ntp.org", "time.nist.gov");
NTP.waitSet([]() { Serial.print("."); });
time_t now = time(nullptr);
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
FORTYFOUR
Methods and properties described in this section are specific to the Raspberry Pi Pico W and the ESP8266. They are not
covered in Arduino WiFi library documentation. Before they are fully documented please refer to information below.
The BearSSL library (with modifications for ESP8266 compatibility and to use ROM tables whenever possible) is used
to perform all cryptography and TLS operations. The main ported repo is available on GitHub.
BearSSL::WiFiClientSecure client;
const char x509CA PROGMEM = ".......";
void setup() {
BearSSL::X509List x509(x509CA);
client.setTrustAnchor(&x509);
}
(continues on next page)
127
Arduino-Pico Documentation, Release 4.4.3
Because the pointer to the local object x509 no longer is valid after setup(), expect to crash in the main loop() where it
is accessed by the client object.
As a rule, either keep your objects global, use new to create them, or ensure that all objects needed live inside the same
scope as the client.
Note that PROGMEM strings and arrays are natively supported by these constructors and no special *_P modes are
required. There are additional functions to identify the key type and access the underlying BearSSL proprietary types,
but they are not needed by user applications.
If you need to add additional certificates (unlikely in normal operation), the ::append() operation can be used.
FORTYFIVE
WIFICLIENTSECURE CLASS
BearSSL::WiFiClientSecure is the object which actually handles TLS encrypted WiFi connections to a remote server
or client. It extends WiFiClient and so can be used with minimal changes to code that does unsecured communications.
45.1 Validating X509 Certificates (Am I talking to the server I think I’m
talking to?)
Prior to connecting to a server, the BearSSL::WiFiClientSecure needs to be told how to verify the identity of the other
machine. By default BearSSL will not validate any connections and will refuse to connect to any server.
There are multiple modes to tell BearSSL how to verify the identity of the remote server. See the BearSSL_Validation
example for real uses of the following methods:
45.1.1 setInsecure()
Don’t verify any X509 certificates. There is no guarantee that the server connected to is the one you think it is in this
case.
131
Arduino-Pico Documentation, Release 4.4.3
45.5 Errors
BearSSL can fail in many more unique and interesting ways. Use these calls to get more information when something
fails.
45.6.1 setCiphers()
Takes an array (in PROGMEM is valid) or a std::vector of 16-bit BearSSL cipher identifiers and restricts BearSSL to
only use them. If the server requires a different cipher, then connection will fail. Generally this is not useful except in
cases where you want to connect to servers using a specific cipher. See the BearSSL headers for more information on
the supported ciphers.
45.6.2 setCiphersLessSecure()
Helper function which essentially limits BearSSL to less secure ciphers than it would natively choose, but they may be
helpful and faster if your server depended on specific crypto options.
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_
˓→cert, const char *cli_key);
Note that the SSL backend is very different between Arduino-Pico and ESP32-Arduino (BearSSL vs. mbedTLS). This
means that, for instance, the SSL connection will check valid dates of certificates (and hence require system time to be
set on the Pico, which is automatically done in this case).
TLS-Pre Shared Keys (PSK) is not supported by BearSSL, and hence not implemented here. Neither is ALPN.
For more advanced control, it is recommended to port to the native Pico calls which allows much more flexibility and
control.
FORTYSIX
WIFISERVERSECURE CLASS
Implements a TLS encrypted server with optional client certificate validation. See Server Class for general information
and BearSSL Secure Client Class for basic server and BearSSL concepts.
openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days 4096
Again, it is up to the application author to generate this certificate and key and keep the private key safe and private.
135
Arduino-Pico Documentation, Release 4.4.3
Here are the kind of performance improvements that you’ll be able to see for TLS handshakes with an ESP8266 with
it’s clock set at 160MHz on a network with fairly low latency:
• With an EC key of 256 bits, a request taking ~360ms without caching takes ~60ms with caching.
• With an RSA key of 2048 bits, a request taking ~1850ms without caching takes ~70ms with caching.
FORTYSEVEN
HTTPCLIENT LIBRARY
A simple HTTP requester that can handle both HTTP and HTTPS requests is included as the HTTPClient library.
Check the examples for use under HTTP and HTTPS configurations. In general, for HTTP connections (unsecured and
very uncommon on the internet today) simply passing in a URL and performiung a GET is sufficient to transfer data.
For HTTPS connections, simply add the appropriate WiFiClientSecure calls as needed (i.e. setInsecure(),
setTrustAnchor, etc.). See the WiFiClientSecure documentation for more details.
Unlike the ESP8266 and ESP32 HTTPClient implementations it is not necessary to create a WiFiClient or
WiFiClientSecure to pass in to the HTTPClient object.
137
Arduino-Pico Documentation, Release 4.4.3
FORTYEIGHT
OTA UPDATES
48.1 Introduction
OTA (Over the Air) update is the process of uploading firmware to a Pico using a Wi-Fi, Ethernet, or other connection
rather than a serial port. This is especially useful for WiFi enabled Picos, like the Pico W, because it lets systems be
updated remotely, without needing physical access.
OTA may be done using:
• Arduino IDE
• Web Browser
• HTTP Server
• Any other method (ZModem receive over a UART port, etc.) by using the Updater object in your sketch
The Arduino IDE option is intended primarily for the software development phase. The other two options would be
more useful after deployment, to provide the module with application updates either manually with a web browser, or
automatically using an HTTP server.
In any case, the first firmware upload has to be done over a serial port. If the OTA routines are correctly implemented
in the sketch, then all subsequent uploads may be done over the air.
By default, there is no imposed security for the OTA process. It is up to the developer to ensure that updates are allowed
only from legitimate / trusted sources. Once the update is complete, the module restarts, and the new code is executed.
The developer should ensure that the application running on the module is shut down and restarted in a safe manner.
Chapters below provide additional information regarding security and safety of OTA updates.
139
Arduino-Pico Documentation, Release 4.4.3
Certain basic protection is already built in and does not require any additional coding by the developer. ArduinoOTA
and espota.py use Digest-MD5 to authenticate uploads. Integrity of transferred data is verified on the Pico side using
MD5 checksum.
Make your own risk analysis and, depending on the application, decide what library functions to implement. If required,
consider implementation of other means of protection from being hacked, like exposing modules for uploads only
according to a specific schedule, triggering OTA only when the user presses a dedicated “Update” button wired to the
Pico, etc.
Automatic Signing
The simplest way of implementing signing is to use the automatic mode, which presently is only possible on Linux and
Mac due to some of the tools not being available for Windows. This mode uses the IDE to configure the source code
to enable signing verification with a given public key, and signs binaries as part of the standard build process using a
given public key.
To enable this mode, just include private.key and public.key in the sketch .ino directory. The IDE will call a helper script
(tools/signing.py) before the build begins to create a header to enable key validation using the given public key, and to
actually do the signing after the build process, generating a sketch.bin.signed file. When OTA is enabled (ArduinoOTA,
Web, or HTTP), the binary will automatically only accept signed updates.
When the signing process starts, the message:
will appear in the IDE window before a compile is launched. At the completion of the build, the signed binary file well
be displayed in the IDE build window as:
If you receive either of the following messages in the IDE window, the signing was not completed and you will need
to verify the public.key and private.key:
<in globals>
BearSSL::PublicKey signPubKey( ... key contents ... );
BearSSL::HashSHA256 hash;
BearSSL::SigningVerifier sign( &signPubKey );
...
<in setup()>
Update.installSignature( &hash, &sign );
The above snippet creates a BearSSL public key and a SHA256 hash verifier, and tells the Update object to use them
to validate any updates it receives from any method.
Compile the sketch normally and, once a .bin file is available, sign it using the signer script:
48.2 Compression
The bootloader incorporates a GZIP decompressor, built for very low code requirements. For applications, this optional
decompression is completely transparent.
No changes to the application are required. The Updater class and bootloader (which performs actual application
overwriting on update) automatically search for the gzip header in the uploaded binary, and if found, handle it.
Compress an application .bin file or filesystem package using any gzip available, at any desired compression level (gzip
-9 is recommended because it provides the maximum compression and uncompresses as fast as any other compression
level). For example:
gzip -9 sketch.bin
<PicoPath>/tools/signing.py --mode sign --privatekey <path-to-private.key> --bin sketch.
˓→bin.gz --out sketch.bin.gz.signed
48.2.1 Safety
The OTA process consumes some of the Pico’s resources and bandwidth during upload. Then, the module is restarted
and a new sketch executed. Analyse and test how this affects the functionality of the existing and new sketches.
If the Pico is in a remote location and controlling some equipment, you should devote additional attention to what
happens if operation of this equipment is suddenly interrupted by the update process. Therefore, decide how to put this
equipment into a safe state before starting the update. For instance, your module may be controlling a garden watering
system in a sequence. If this sequence is not properly shut down and a water valve is left open, the garden may be
flooded.
The following functions are provided with the ArduinoOTA library and intended to handle functionality of your appli-
cation during specific stages of OTA, or on an OTA error:
void onStart(OTA_CALLBACK(fn));
void onEnd(OTA_CALLBACK(fn));
void onProgress(OTA_CALLBACK_PROGRESS(fn));
void onError(OTA_CALLBACK_ERROR (fn));
Where 123 is a sample password that you should replace with your own.
Before implementing it in your sketch, it is a good idea to check how it works using BasicOTA.ino sketch available
under File > Examples > ArduinoOTA. Go ahead, open BasicOTA.ino, uncomment the above statement that is already
there, and upload the sketch. To make troubleshooting easier, do not modify example sketch besides what is absolutely
required. This includes the original simple 123 OTA password. Then attempt to upload a sketch again (using OTA).
After compilation is complete, once upload is about to begin, you should see a prompt for password.
Enter the password and upload should be initiated as usual with the only difference being Authenticating...OK
message visible in the upload log.
You will not be prompted for a reentering the same password next time. Arduino IDE will remember it for you. You
will see a prompt for password only after reopening the IDE, or if you change it in your sketch, upload the sketch and
then try to upload it again.
Please note, it is possible to reveal password entered previously in Arduino IDE, if the IDE has not been closed since
last upload. This can be done by enabling Show verbose output during: upload in File > Preferences and attempting
to upload the module.
48.5.1 Requirements
• The Pico and the computer must be connected to the same network, or the IP of the Pico should be known if on
a different network.
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
loop()
httpServer.handleClient();
In case OTA update fails dead after entering modifications in your sketch, you can always recover module by loading
it over a serial port. Then diagnose the issue with sketch using Serial Monitor. Once the issue is fixed try OTA again.
48.6.1 Requirements
• web server
WiFiClient client;
HTTPUpdate.update(client, "192.168.0.2", 80, "/arduino.bin");
Advanced updater
It’s possible to point the update function to a script on the server. If a version string argument is given, it will be sent
to the server. The server side script can use this string to check whether an update should be performed.
The server-side script can respond as follows: - response code 200, and send the firmware image, - or response code
304 to notify Pico that no update is required.
WiFiClient client;
t_httpUpdate_return ret = HTTPUpdate.update(client, "192.168.0.2", 80, "/pico/update/
˓→arduino.php", "optional current version string here");
switch(ret) {
case HTTP_UPDATE_FAILED:
Serial.println("[update] Update failed.");
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println("[update] Update no Update.");
break;
case HTTP_UPDATE_OK:
Serial.println("[update] Update ok.");
break;
}
TLS updater
Please read and try the examples provided with the library.
Advanced updater
For advanced update management a script (such as a PHP script) can run on the server side. It will receive the following
headers which it may use to choose a specific firmware file to serve:
::
[User-Agent] => Pico-HTTP-Update [x-Pico-STA-MAC] => 18:FE:AA:AA:AA:AA [x-Pico-AP-MAC] =>
1A:FE:AA:AA:AA:AA [x-Pico-Version] => DOOR-7-g14f53a19 [x-Pico-Mode] => sketch
Update.begin(firmwareLengthInBytes);
Update.writeStream(streamVar);
Update.end();
[boot2.S] [OTA Bootloader] [0-pad] [OTA partition table] [Main sketch] [LittleFS␣
˓→filesystem] [EEPROM]
FORTYNINE
Most Arduino libraries that work on modern 32-bit CPU based Arduino boards will run fine using Arduino-Pico.
The following libraries have undergone additional porting and optimizations specifically for the RP2040 and you should
consider using them instead of the generic versions available in the Library Manager
• Adafruit GFX Library by @Bodmer, 2-20x faster than the standard version on the Pico
• Adafruit ILI9341 Library again by @Bodmer
• ESP8266Audio ported to use the included I2S library
147
Arduino-Pico Documentation, Release 4.4.3
FIFTY
#include "pico/stdlib.h"
void setup() {
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 1);
sleep_ms(250);
gpio_put(LED_PIN, 0);
sleep_ms(250);
}
}
void loop() {}
Note: When you call SDK functions in your own app, the core and libraries are not aware of any changes to the Pico
you perform. So, you may break the functionality of certain libraries in doing so.
149
Arduino-Pico Documentation, Release 4.4.3
FIFTYONE
Arduino-Pico is licensed under the LGPL license as detailed in the included README.
In addition, it contains code from additional open source projects:
• The Arduino IDE and ArduinoCore-API are developed and maintained by the Arduino team. The IDE is licensed
under GPL.
• The RP2040 GCC-based toolchain is licensed under under the GPL.
• The Pico-SDK and Pico-Extras are by Raspberry Pi (Trading) Ltd. and licensed under the BSD 3-Clause license.
• Arduino-Pico core files are licenses under the LGPL.
• LittleFS library written by ARM Limited and released under the BSD 3-clause license .
• UF2CONV.PY is by Microsoft Corporation and licensed under the MIT license.
• Some filesystem code taken from the ESP8266 Arduino Core and licensed under the LGPL.
151