The overview, with examples running, is on the board page and The Raspberry Pi Pico model (every register).
What it is
The Raspberry Pi Pico, an RP2040 running on our own Cortex-M core in its ARMv6-M profile. Firmware is a Thumb ELF talking to the real RP2040 addresses, so the same image runs on real hardware.
The system clock is 125 MHz from reset, because the clock tree is not modeled and there is nothing to bring up.
The pins
The 40-pin header, in the order the board has it.
Left column, pins 1 to 20: GP0, GP1, GND, GP2 to GP5, GNDb, GP6 to
GP9, GNDc, GP10 to GP13, GNDd, GP14, GP15.
Right column, pins 40 down to 21: VBUS, VSYS, GNDe, 3V3_EN, 3V3,
ADC_VREF, GP28, AGND, GP27, GP26, RUN, GP22, GNDf, GP21,
GP20, GP19, GP18, GNDg, GP17, GP16.
The board silkscreens GND on all seven grounds; here they carry letters so
each name is unique. The test points and the SWD header are not pins.
This is a 3.3 volt board and its pins are not 5 V tolerant. 3V3 supplies
3.3 V, VBUS supplies 5 V and VSYS supplies 4.7 V, which is 5 V through the
board's own Schottky diode.
GP23, GP24 and GP25 exist in the model but are not on the header, as on
the real board. GP25 is the on-board LED, which is why LED_BUILTIN is 25.
What is modeled
SIO GPIO, the 64 bit TIMER, UART0, UART1, PWM and the ADC. Every PWM slice drives channel A on an even pin and channel B on an odd one, which is how the on-board LED on GP25 can be faded.
Serial (and Serial1, the same port) is UART0, which is the serial monitor.
Serial2 is UART1, as in arduino-pico, and its bytes are on its pins rather
than the monitor: TX on GP4 and RX on GP5, or another UART1 pair (GP8 and GP9,
GP20 and GP21) chosen with Serial2.setTX() and Serial2.setRX() before
begin(). A GPS module, an HC-05 or a second board wired there hears it bit by
bit, at the baud rate the divider really gives.
The ADC is the RP2040's twelve-bit converter. GP26, GP27 and GP28 are
A0 to A2, and analogRead() on one of them reads the voltage on the net
against 3.3 V: ten bits by default, as in arduino-pico, or twelve after
analogReadResolution(12). analogReadTemp() reads the on-chip temperature
sensor, which sits at 27 C here. The converter has no noise and no error in it,
and its FIFO, DMA and interrupt are not modeled.
That is the set pinMode, digitalWrite, digitalRead, analogRead,
analogWrite, millis, micros, delay, Serial, Serial2 and
attachInterrupt need, at their real addresses.
What is not
A long list, and it is worth reading before you plan a project around one of
them: PIO, DMA, SPI, I2C, USB, the RTC, the clock tree,
the QSPI flash interface, the second core, the on-chip ROM and the
interpolators. The watchdog is modeled: watchdog_enable() and
rp2040.wdt_begin() reboot a sketch that stops feeding them.
Their address blocks are unmapped, so touching one is a bus fault rather than a silent zero. That is deliberate: a program that quietly reads nothing is harder to debug than one that stops.
A Pico SDK program is not built in the editor, but its prebuilt .uf2 or
.elf runs: the Pico boots it through its boot ROM, with the clocks, I2C, SPI,
DMA and USB blocks there as for MicroPython (see
Run a prebuilt firmware), and so does PIO
there. The second core stops such a program with a sentence saying so.
SPI.h and Wire.h still work, in software on ordinary pins (below), so the
missing SPI and I2C blocks matter only to code that writes their registers.
A Pico running MicroPython or a prebuilt firmware is the exception: it boots
the way silicon does, and the I2C, SPI, DMA and PIO blocks are there for
machine.I2C, machine.SPI and rp2.StateMachine (see MicroPython on the Pico).
Two approximations are worth knowing as well. The core runs in 1.024 us chunks rather than one instruction at a time, because a Cortex-M interpreter has no headroom at 125 MHz: timer alarms, PWM edges and UART bytes land on their exact cycle, but a pin change made by software can be up to a microsecond late. And the system clock is always 125 MHz, whatever a sketch programs, because the clock tree is not there.
The full list, and section 8's sorting of what is a data sheet number and what is an approximation, is in the Raspberry Pi Pico model.
Stock Arduino libraries
A tutorial that includes Servo.h, Wire.h, SPI.h, EEPROM.h,
LiquidCrystal_I2C.h, Adafruit_GFX.h with Adafruit_SSD1306.h and DHT.h
compiles here as it stands. Each is Mokxi's own header under the upstream name,
written on the drivers for the parts in the bin, and none of it is the upstream
library's code.
Wire.begin()puts the I2C bus onGP4(SDA) andGP5(SCL).EEPROM.hworks, but this board's model has no EEPROM or writable flash, so the bytes live in 4 KB of RAM: they read back within a Run and are gone at a reset.Adafruit_NeoPixel.hdrives a WS2812 strip. A real Pico sends the bits from PIO, which is not modeled, so here the core times each one on SysTick, inside the data sheet's windows, with interrupts off for the frame.
The code editor and compiling lists what each one covers and how it differs from the upstream library.
MicroPython
A Pico can run Python instead of a sketch. In the board's Firmware panel, pick
MicroPython (main.py): the board's files become a main.py, and Run starts
it. What runs is MicroPython v1.29.0, the official Pico firmware from
micropython.org, on the simulated RP2040. Run copies your .py files onto the
board the way Thonny does, and then the board runs main.py itself. print()
goes to the Serial Monitor, and the REPL answers there once main.py ends or
you stop it with Ctrl-C.
machine.Pin, machine.PWM, machine.ADC, machine.UART(1), machine.I2C,
machine.SPI, SoftI2C and SoftSPI work, so drivers such as
micropython-lib's ssd1306.py talk to the parts on the canvas. A traceback
marks the line in your file, as a compile error does.
PIO works too: rp2.PIO and rp2.StateMachine run their programs on the
simulated PIO blocks, so the WS2812 example from MicroPython's documentation
lights a NeoPixel strip. Not simulated: the second core (_thread stops the
board with a message), the I2C target mode and the SPI slave mode.
The CPU stays at 125 MHz whatever machine.freq() says.
The Pico W runs MicroPython too, with its own build: its CYW43439 radio chip
is modeled, so Pin("LED") lights and network.WLAN joins Mokxi's simulated
network (see the Pico W). To get started, see
MicroPython on the Pico.
CircuitPython
Pick CircuitPython (code.py) in the board's Firmware panel instead and Run
boots the official CircuitPython 10.3.1 firmware for the Pico. Your code.py
is saved onto the board's CIRCUITPY drive over USB and runs, and the Adafruit
libraries it imports go into the drive's lib/ folder by themselves. See
CircuitPython on the Pico.
A Pico SDK program
A program built with the Raspberry Pi Pico SDK runs from its build: in the
board's Firmware panel choose Upload firmware (.uf2, .elf) and pick the
.uf2 or .elf from your build/ folder. The Pico boots it through its boot
ROM, as after copying it onto the board's drive, and the Serial Monitor shows
UART0 and USB serial both. PIO works; the second core is not simulated. The
steps are in Run a prebuilt firmware.
Assembly
The Firmware panel also offers Assembly (no Arduino): a Blink, a Button to
LED, a UART hello and a Timer interrupt in ARM Thumb assembly for the
Cortex-M0+. The board's files become one main.S, and nothing but that file is
linked, so it carries its own vector table: .word _stack_top, then
Reset_Handler, then its handlers. The starters take IO_BANK0 and
PADS_BANK0 out of RESETS, drive GPIO25 through SIO and time themselves on
TIMERAWL. A .S tab beside an ordinary sketch works too. The Pico W has no
starters, because its LED is on the radio chip. See
Writing assembly.
The examples
Blink, Button, Serial, Fade and Chaser, and the game controller examples: the four Fight stick steps, Fight stick, Leverless controller, Mixbox-style controller and Stop the light.
Elsewhere
- The board page: /boards/pico
- The contract document: the Raspberry Pi Pico model
- The learning path: Embedded on the Raspberry Pi Pico, at /learn
- The same chip with WiFi: the Pico W
- The same chip on smaller boards: the XIAO RP2040, the RP2040-Zero and the Nano RP2040 Connect