Waveshare RP2040

The RP2040 SoC [1] by Raspberry Pi Ltd. is a small sized and low-cost 32-bit dual ARM Cortex-M0+ microcontroller and predestined for versatile board designs. The Waveshare RP2040 board series based on this microcontroller offers a wide range with different scaling factors, in size, features and interfaces for communication, input and output.

Supported Boards

Hardware

The RP2040-One [58] is a mini sized RP2040 development board. The on-board PCB USB-A connector makes it plug-and-play instantly. The castellated module allows soldering direct to carrier boards.

Features and Resources

Printed Circuit Board

5V/300㎃ 3.3V/500㎃ 3.3V(OUT)

133㎒ 4㎆ 264㎅ RST RGB USB-A UF2

20+9 16 4 2 2 2

  • Dual core Arm Cortex-M0+ processor running up to 133㎒

  • 264㎅ on-chip SRAM

  • 4㎆ on-board QSPI flash with XIP capabilities

  • USB 1.1 controller (host/device)

  • On-board PCB USB-A connector

  • On-board RGB LED

  • On-board 3.3V LDO regulator with 500㎃

  • On-board RESET button

  • On-board BOOT button

  • 20 GPIO pins via edge pinout

  • 9 GPIO pins via solder points

  • 2 UART peripherals

  • 2 I2C controllers

  • 2 SPI controllers

  • 16 PWM channels

  • 4 ADC analog inputs

  • 8 Programmable I/O (PIO) state machines for custom peripherals

  • 1 Watchdog timer peripheral

  • 1 Temperature sensor on-chip

Design Data

Waveshare RP2040-One

Positions

Waveshare RP2040-One details
  1. PCB USB-A port

  2. RT9013-33
    500㎃ low dropout, low noise, ultra-fast LDO
  3. WS2812B
    RGB LED
  4. BOOT button
    press it when resetting to enter download mode
  1. W25Q32JV
    4㎆ NOR-Flash
  2. RESET button

  3. RP2040

  4. RP2040 pins
    10 solder points, including 9 GPIO pins

Data Sheets

Pinouts

The peripherals of the RP2040 SoC [1] can be routed to various pins on the board. The configuration of these routes can be modified through DTS. Please refer to the datasheet to see the possible routings for each peripheral. The default assignments for the various Waveshare RP2040 boards are defined below separately in a single tab.

External pin mapping on the RP2040-One is not identical to the original Raspberry Pi Pico board. Almost all pins are rearranged in a more compact order. Likewise, the voltage sense and monitoring functions are not integrated. Thus all internal R2040 GPIO lines are available for free use, insofar there is sufficient space for them on the outer edge of the board or on the bottom side by additional solder points.

Only GPIO line 16 is exclusively routed to the on-board user RGB LED. The analog voltage reference is internally hard-wired to the digital 3.3V power supply and only decoupled by a simple resistor. There is no option to change this from outside the board.

Pin Mapping

Pinout

on-edge(1-23):

6 4 4 2 1 1

on-pads(A-J):

9 9

on-board:

1 RGB

Default Zephyr Peripheral Mapping

 

  • 1 UART0_TX : GP0 (PWM0)
  • 2 UART0_RX : GP1 (PWM1)
  • 3 PIO/PWM : GP2 PWM2
  • 4 PIO/PWM : GP3 PWM3
  • 5 SPI0_RX : GP4 (PWM4)
  • 6 SPI0_CSN : GP5 (PWM5)
  • 7 SPI0_SCK : GP6 (PWM6)
  • 8 SPI0_TX : GP7 (PWM7)
  • 9 I2C0_SDA : GP8 (PWM8)
  • 10 I2C0_SCL : GP9 (PWM9)
  • 11 PIO/PWM : GP10 PWM10
  • 12 PIO/PWM : GP11 PWM11
  • 13 PIO/PWM : GP12 PWM12
  • 14 PIO/PWM : GP13 PWM13
  • 15 I2C1_SDA : GP14 (PWM14)
  • 16 I2C1_SCL : GP15 (PWM15)
  • nc PIO0 : GP16 (PWM0)
    nc on-board user RGB_LED_DI
  • A PIO/PWM : GP17 PWM1
  • B PIO/PWM : GP18 PWM2
  • C PIO/PWM : GP19 PWM3
  • D PIO/PWM : GP20 PWM4
  • E PIO/PWM : GP21 PWM5
  • F PIO/PWM : GP22 PWM6
  • G PIO/PWM : GP23 PWM7
  • H PIO/PWM : GP24 PWM8
  • I PIO/PWM : GP25 PWM9
  • J GND
  • 17 ADC_CH0 : GP26 (PWM10)
  • 18 ADC_CH1 : GP27 (PWM11)
  • 19 ADC_CH2 : GP28 (PWM12)
  • 20 ADC_CH3 : GP29 (PWM13)
  • 21 3V3(OUT)
  • 22 GND
  • 23 VSYS

Devicetree compatible

Waveshare RP2040-One edge pinout

Supported Features

Similar to the Raspberry Pi Pico the Waveshare RP2040 board configuration supports the following hardware features:

Peripheral

Kconfig option

Devicetree compatible

Zephyr API

PINCTRL

CONFIG_PINCTRL

raspberrypi,pico-pinctrl

Pin Control API

UART

CONFIG_SERIAL

raspberrypi,pico-uart

Universal Asynchronous Receiver-Transmitter (UART)

GPIO

CONFIG_GPIO

raspberrypi,pico-gpio

General-Purpose Input/Output (GPIO)

USB Device

CONFIG_USB_DEVICE_STACK

raspberrypi,pico-usbd

USB device support APIs

I2C

CONFIG_I2C

Inter-Integrated Circuit (I2C) Bus

SPI

CONFIG_SPI

raspberrypi,pico-spi

Serial Peripheral Interface (SPI) Bus

PWM

CONFIG_PWM

raspberrypi,pico-pwm

Pulse Width Modulation (PWM)

ADC

CONFIG_ADC

raspberrypi,pico-adc

Analog-to-Digital Converter (ADC)

Temperature (Sensor)

CONFIG_SENSOR

raspberrypi,pico-temp (!!)

Sensors

Timer (Counter)

CONFIG_COUNTER

raspberrypi,pico-timer

Counter

Watchdog Timer (WDT)

CONFIG_WATCHDOG

raspberrypi,pico-watchdog

Watchdog

Flash

CONFIG_FLASH

raspberrypi,pico-flash-controller

Flash and Flash map

PIO

CONFIG_PIO_RPI_PICO

raspberrypi,pico-pio

N/A

UART (PIO)

CONFIG_SERIAL

raspberrypi,pico-uart-pio

Universal Asynchronous Receiver-Transmitter (UART)

SPI (PIO)

CONFIG_SPI

raspberrypi,pico-spi-pio

Serial Peripheral Interface (SPI) Bus

DMA

CONFIG_DMA

raspberrypi,pico-dma

Direct Memory Access (DMA)

RESET

CONFIG_RESET

raspberrypi,pico-reset

Reset Controller

VREG

CONFIG_REGULATOR

raspberrypi,core-supply-regulator

Regulators

NVIC

N/A

arm,v6m-nvic

Nested Vector Interrupts Controller

HWINFO

CONFIG_HWINFO

N/A

Hardware Information

(!) Designware I2C driver has issues:

The Raspberry Pi Pico I2C driver is using the Designware I2C driver automatically. According to our observation, this driver has some shortcomings in interrupt handling and leads to a dead-lock of the entire runtime system. Also known is the lack of support for 0 byte transfers, which prevents a proper I2C device scan. Thus, all Waveshare RP2040 boards will be configured to use the simple GPIO-I2C bit-bang driver as long as this driver is not applicable as expected.

See also: https://github.com/zephyrproject-rtos/zephyr/pull/60427

(!!) Die-Temperature Sensor driver has issues:

It seems the RP2040 Die-Temperature sensor driver has also race conditions and leads to a dead-lock of the entire runtime system. Thus, all Waveshare RP2040 boards will be configured to disable this sensor node in DTS explicitly. As a workaround the ADC channel 4 can be used, but that result have to convert manually to the corresponding chip temperature following the formula that can be found in the RP2040 Datasheet [2], section with title “Temperature Sensor”.

Other hardware features are not currently supported by Zephyr. The default configuration can be found in the different Kconfig files:

Board Configurations

The Waveshare RP2040 boards can be configured for the following different use cases. The RP2040-Plus board offers an assembly option with 16㎆ Flash, which is mapped as a hardware revision.

west build -b waveshare_rp2040_one

Use the serial port UART0 on edge header as Zephyr console and for the shell.

west build -b waveshare_rp2040_one -S usb-console

Use the native USB device port with CDC-ACM as Zephyr console and for the shell.

Connections and IOs

The Waveshare wiki [57] has detailed information about board connections. Download the different schematics or datasheets as linked above per board for more details. The pinout diagrams can also be found there.

System Clock

The RP2040 [1] MCU is configured to use the 12㎒ external crystal with the on-chip PLL generating the 125㎒ system clock. The internal AHB and APB units are set up in the same way as the upstream Raspberry Pi Pico C/C++ SDK [4] libraries.

GPIO (PWM) Ports

The RP2040 [1] MCU has 1 GPIO cell which covers all I/O pads and 8 PWM function unit each with 2 channels beside a dedicated Timer unit. On the two boards RP2040-Plus and RP2040-LCD-0.96, PWM4 channel B is available on the on-board user or backlight LED. But the PWM operation is not enable by default. Only if CONFIG_PWM_RPI_PICO is enabled then the first user or backlight LED is driven by PWM4CHB instead of by GPIO. All channels of PWM0 until PWM7 are available on the Raspberry Pi Pico or Waveshare RP2040 Mini header and Waveshare RP2040 Mini PCB Pads.

The RP2040-Geek board has no such LED and no standard header and therefore does not provide any PWM to the outside on any pad by default.

ADC/TS Ports

The RP2040 [1] MCU has 1 ADC with 4 channels and an additional fifth channel for the on-chip temperature sensor (TS). The ADC channels 0-2 are available on the Raspberry Pi Pico or Waveshare RP2040 Mini header, channel 3 only on the Waveshare RP2040 Mini header. On the RP2040-Plus, the RP2040-LCD-0.96 and RP2040-ETH, ADC channel 3 will be used for internal on-board voltage monitoring.

The external voltage reference ADC_VREF can be used optional for the ADC and is only available on the Raspberry Pi Pico header.

The RP2040-Geek board provides ADC channel 2 and 3 over GP28 (ADC2) and GP29 (ADC3) on one of the three edge connectors but these are disabled by default. Both ADC channels will share the same lines with the I2C0 signals.

SPI Port

The RP2040 [1] MCU has 2 SPIs. To the edge connectors SPI0 is connect to external devices over GP19 (MOSI), GP16 (MISO), GP18 (SCK), and GP17 (CSn) on the Raspberry Pi Pico header or over GP7 (MOSI), GP4 (MISO), GP6 (SCK), and GP5 (CSn) on the Waveshare RP2040 Mini header. A special case is the RP2040-ETH board where SPI0 is routed on the Raspberry Pi Pico header with the same GP4-7 layout as on the Waveshare RP2040 Mini header.

The RP2040-Geek does not provide any SPI to the outside on any pad. These are connected internally to the LCD and the TF/microSD card interfaces.

I2C Port

The RP2040 [1] MCU has 2 I2Cs. To the edge connectors I2C0 and I2C1 is connect to external devices over GP4 (I2C0_SDA), GP5 (I2C0_SCL), GP14 (I2C1_SDA), and GP15 (I2C1_SCL) on the Raspberry Pi Pico header or over GP8 (I2C0_SDA), GP9 (I2C0_SCL), GP14 (I2C1_SDA), and GP15 (I2C1_SCL) on the Waveshare RP2040 Mini header. A special case is the RP2040-ETH board where I2C1 is omitted and I2C0 is routed on the Raspberry Pi Pico header with the same GP8-9 layout as on the Waveshare RP2040 Mini header.

The RP2040-Geek board provides I2C0 over GP28 (SDA) and GP29 (SCL) on one of the three edge connectors and it is enabled by default. Both I2C0 signals will share the same lines with ADC channels 2 and 3.

Serial Port

The RP2040 [1] MCU has 2 UARTs. One of the UARTs (UART0) is connected to external devices over GP0 (TX) and GP1 (RX) on both the Raspberry Pi Pico and the Waveshare RP2040 Mini header in same manner and is the Zephyr console.

The RP2040-Geek board provides UART1 over GP4 (TX) and GP5 (RX) on one of the three edge connectors and it is enabled by default.

USB Device Port

The RP2040 [1] MCU has a (native) USB device port that can be used to communicate with a host PC. See the USB device support samples sample applications for more, such as the USB CDC-ACM sample which sets up a virtual serial port that echos characters back to the host PC. As an alternative to the default Zephyr console on serial port the Bridle USB Console Snippet (usb-console) can be used to enable CDC ACM and switch the console to USB:

USB device idVendor=2e8a, idProduct=000a, bcdDevice= 3.05
USB device strings: Mfr=1, Product=2, SerialNumber=3
Product: RP2040-Plus (CDC ACM)
Manufacturer: Waveshare (Raspberry Pi)
SerialNumber: B69F8448A6E91514

To integrate specific USB device functions that do not follow a USB standard class, the following alternate identifier numbers are available for the various Waveshare RP2040 boards according to the Raspberry Pi USB product ID list [6]:

0x101F:

RP2040-Zero

0x1020:

RP2040-Plus

0x1021:

RP2040-LCD-0.96

0x1039:

RP2040-LCD-1.28

0x103A:

RP2040-One

0x1044:

Power Management HAT (B)

0x1055:

RP2040-ETH

0x1056:

RP2040-HACK

0x1057:

RP2040-Touch-LCD-1.28

Programmable I/O (PIO)

The RP2040 SoC [1] comes with two PIO periherals. These are two simple co-processors that are designed for I/O operations. The PIOs run a custom instruction set, generated from a custom assembly language. PIO programs are assembled using pioasm, a tool provided by Raspberry Pi. Further informations can be found in the Raspberry Pi Pico C/C++ SDK [4] document, section with title “Using PIOASM, the PIO Assembler”.

Zephyr does not (currently) assemble PIO programs. Rather, they should be manually assembled and embedded in source code. An example of how this is done can be found at drivers/serial/uart_rpi_pico_pio.c or drivers/spi/spi_rpi_pico_pio.c.

Programming and Debugging

Flashing

Using UF2

If you don’t have an SWD adapter, you can flash the Waveshare RP2040 boards with a UF2 file. By default, building an app for this board will generate a build/zephyr/zephyr.uf2 file. If the board is powered on with the BOOTSEL button pressed, it will appear on the host as a mass storage device:

USB device idVendor=2e8a, idProduct=0003, bcdDevice= 1.00
USB device strings: Mfr=1, Product=2, SerialNumber=3
Product: RP2 Boot
Manufacturer: Raspberry Pi
SerialNumber: E0C9125B0D9B

The UF2 file should be drag-and-dropped or copied on command line to the device, which will then flash the Waveshare RP2040 board.

Each RP2040 SoC [1] ships the UF2 compatible [11] bootloader pico-bootrom [7], a native support in silicon. The full source for the RP2040 bootrom at pico-bootrom [7] includes versions 1, 2 and 3 of the bootrom, which correspond to the B0, B1 and B2 silicon revisions, respectively.

Note that every time you build a program for the RP2040, the Pico SDK selects an appropriate second stage bootloader based on what kind of external QSPI Flash type the board configuration you are building for was giving. There are several versions of boot2 [8] for different flash chips, and each one is exactly 256 bytes of code which is put right at the start of the eventual program binary. On Zephyr the boot2 versions are part of the Raspberry Pi Pico HAL [9] module. Possible selections:

CONFIG_RP2_FLASH_AT25SF128A:

boot2_at25sf128a.S

CONFIG_RP2_FLASH_GENERIC_03H:

boot2_generic_03h.S

CONFIG_RP2_FLASH_IS25LP080:

boot2_is25lp080.S

CONFIG_RP2_FLASH_W25Q080:

boot2_w25q080.S

CONFIG_RP2_FLASH_W25X10CL:

boot2_w25x10cl.S

All Waveshare RP2040 boards set this option to CONFIG_RP2_FLASH_W25Q080. Further informations can be found in the RP2040 Datasheet [2], sections with title “Bootrom” and “Processor Controlled Boot Sequence” or Brian Starkey’s Blog article Pico serial bootloader [10]

Using OpenOCD

To use PicoProbe [12] or Raspberry Pi Debug Probe [13], you must configure udev. Create a file in /etc/udev.rules.d with any name, and write the line below.

ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE="660", GROUP="plugdev", TAG+="uaccess"

This example is valid for the case that the user joins to plugdev groups.

The RP2040-LCD-0.96 and RP2040-Plus has an SWD interface that can be used to program and debug the on board RP2040. This interface can be utilized by OpenOCD. To use it with the RP2040, OpenOCD version 0.12.0 or later is needed. If you are using a Debian based system (including RaspberryPi OS, Ubuntu, and more), using the pico_setup.sh [17] script is a convenient way to set up the forked version of OpenOCD. Depending on the interface used (such as JLink), you might need to checkout to a branch that supports this interface, before proceeding. Build and install OpenOCD as described in the README.

Here is an example of building and flashing the Blinky application.

# From the root of the zephyr repository
west build -b waveshare_rp2040_plus -p -d build/waveshare_rp2040 zephyr/samples/basic/blinky -- \
-DOPENOCD=/usr/local/bin/openocd \
-DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts \
-DWAVESHARE_RP2040_DEBUG_ADAPTER=picoprobe
west flash -r openocd -d build/waveshare_rp2040

Set the environment variables OPENOCD to /usr/local/bin/openocd and OPENOCD_DEFAULT_PATH to /usr/local/share/openocd/scripts. This should work with the OpenOCD that was installed with the default configuration. This configuration also works with an environment that is set up by the pico_setup.sh [17] script.

WAVESHARE_RP2040_DEBUG_ADAPTER specifies what debug adapter is used for debugging. If WAVESHARE_RP2040_DEBUG_ADAPTER was not assigned, cmsis-dap is used by default. The other supported adapters are picoprobe, raspberrypi-swd, jlink and blackmagicprobe. How to connect picoprobe and raspberrypi-swd is described in Getting Started Guide with Raspberry Pi Pico [5]. Any other SWD debug adapter maybe also work with this configuration. The value of WAVESHARE_RP2040_DEBUG_ADAPTER is cached, so it can be omitted from west flash and west debug if it was previously set while running west build. WAVESHARE_RP2040_DEBUG_ADAPTER is used in an argument to OpenOCD as "source [find interface/${WAVESHARE_RP2040_DEBUG_ADAPTER}.cfg]". Thus, WAVESHARE_RP2040_DEBUG_ADAPTER needs to be assigned the file name of the debug adapter.

You can also flash the board with the following command that directly calls OpenOCD (assuming a SEGGER JLink adapter is used):

$ openocd -f interface/jlink.cfg    \
          -c 'transport select swd' \
          -f target/rp2040.cfg      \
          -c "adapter speed 2000"   \
          -c 'targets rp2040.core0' \
          -c 'program path/to/zephyr.elf verify reset exit'

Debugging

The SWD interface can also be used to debug the board. To achieve this, you can either use SEGGER JLink or OpenOCD.

Using SEGGER JLink

Use a SEGGER JLink debug probe and follow the instruction in Building, Flashing and Debugging.

Using OpenOCD

Install OpenOCD as described for flashing the board.

Here is an example for debugging the Blinky application.

# From the root of the zephyr repository
west build -b waveshare_rp2040_plus -p -d build/waveshare_rp2040 zephyr/samples/basic/blinky -- \
-DOPENOCD=/usr/local/bin/openocd \
-DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts \
-DWAVESHARE_RP2040_DEBUG_ADAPTER=raspberrypi-swd
west debug -r openocd -d build/waveshare_rp2040

As with flashing, you can specify the debug adapter by specifying WAVESHARE_RP2040_DEBUG_ADAPTER at west build time. No needs to specify it at west debug time.

You can also debug with OpenOCD and gdb launching from command-line. Run the following command:

$ openocd -f interface/jlink.cfg    \
          -c 'transport select swd' \
          -f target/rp2040.cfg      \
          -c "adapter speed 2000"   \
          -c 'targets rp2040.core0'

On another terminal, run:

$ gdb-multiarch

Inside gdb, run:

(gdb) tar ext :3333
(gdb) file path/to/zephyr.elf

You can then start debugging the board.

More Samples

LED Blinky and Fade

WS2812 LED Test Pattern by PIO

See also Zephyr sample: WS2812 LED strip

Waveshare RP2040-One WS2812 LED Test Pattern
west build -b waveshare_rp2040_one -p -d build/waveshare_rp2040 zephyr/samples/drivers/led_ws2812
west flash -r uf2 -d build/waveshare_rp2040

Hint

Neither LED Blinky nor LED Fade can be built and executed on RP2040-One, because this system has only one digital RGB LED. A simple GPIO or PWM control is not possible!

Hello Shell with USB-CDC/ACM Console

Hello Shell

west build -b waveshare_rp2040_one -p -S usb-console -d build/waveshare_rp2040 bridle/samples/helloshell
west flash -r uf2 -d build/waveshare_rp2040

Simple test execution on target

uart:~$ hello -h
hello - say hello
uart:~$ hello
Hello from shell.

uart:~$ hwinfo devid
Length: 8
ID: 0x8be83cbec052feae

uart:~$ kernel version
Zephyr version 3.5.0

uart:~$ bridle version
Bridle version 3.5.1

uart:~$ bridle version long
Bridle version 3.5.1.0

uart:~$ bridle info
Zephyr: 3.5.0
Bridle: 3.5.1

uart:~$ device list
devices:
- reset-controller@4000c000 (READY)
- snippet_cdc_acm_console_uart (READY)
- uart@40034000 (READY)
- timer@40054000 (READY)
- pio@50200000 (READY)
- gpio@40014000 (READY)
- adc@4004c000 (READY)
- flash-controller@18000000 (READY)
- i2c@40044000 (READY)
- vreg@40064000 (READY)

uart:~$ history
[  0] history
[  1] device list
[  2] bridle info
[  3] bridle version long
[  4] bridle version
[  5] kernel version
[  6] hwinfo devid
[  7] hello
[  8] hello -h

Display Test and Demonstration

This samples and test applications are only applicable on the RP2040-LCD-0.96 and RP2040-Geek board. They will be built with activated USB-CDC/ACM console.

The following samples work with the chosen display. That is:

LCD : chosen { zephyr,display = &lcd_panel; };
ST7735S : lcd_panel: &st7735s_160x80 {};

LCD Orientation and Bit Order Test

Using the Display driver API with chosen display. See also Zephyr sample: Display.

west build -b waveshare_rp2040_lcd_0_96 -p -S usb-console -d build/waveshare_rp2040 zephyr/samples/drivers/display
west flash -r uf2 -d build/waveshare_rp2040
Waveshare RP2040-LCD-0.96 Display Sample Animation

TOP LEFT, TOP RIGHT, BOTTOM RIGHT

LVGL Basic Sample

Using the LVGL module on top of the Display driver API with chosen display. See also Zephyr sample: LVGL basic sample.

west build -b waveshare_rp2040_lcd_0_96 -p -S usb-console -d build/waveshare_rp2040 zephyr/samples/subsys/display/lvgl
west flash -r uf2 -d build/waveshare_rp2040

References