Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions boards/waveshare/rp2040_plus/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2025 David Schneider
# SPDX-License-Identifier: Apache-2.0

config BOARD_RP2040_PLUS
select RP2_FLASH_W25Q080
13 changes: 13 additions & 0 deletions boards/waveshare/rp2040_plus/Kconfig.defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2025 David Schneider
# SPDX-License-Identifier: Apache-2.0

if BOARD_RP2040_PLUS

if I2C_DW

config I2C_DW_CLOCK_SPEED
default 125
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this clock speed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not have a answer for your question. I was using the RPI Pico board as a blueprint which contains the same define:

config I2C_DW_CLOCK_SPEED
default 125

All of the other RP2040 based boards I checked have the same definition.


endif # I2C_DW

endif # BOARD_RP2040_PLUS
5 changes: 5 additions & 0 deletions boards/waveshare/rp2040_plus/Kconfig.rp2040_plus
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2025 David Schneider
# SPDX-License-Identifier: Apache-2.0

config BOARD_RP2040_PLUS
select SOC_RP2040
5 changes: 5 additions & 0 deletions boards/waveshare/rp2040_plus/board.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0

board_runner_args(uf2 "--board-id=RPI-RP2")

include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake)
6 changes: 6 additions & 0 deletions boards/waveshare/rp2040_plus/board.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
board:
name: rp2040_plus
full_name: RP2040-Plus
vendor: waveshare
socs:
- name: rp2040
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 94 additions & 0 deletions boards/waveshare/rp2040_plus/doc/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
.. zephyr:board:: rp2040_plus

Overview
********

RP2040-Plus, a low-cost, high-performance Pico-like MCU board based on Raspberry Pi microcontroller RP2040
including a battery charger.

Hardware
********
- Dual core Arm Cortex-M0+ processor running up to 133MHz
- 264KB on-chip SRAM
- 4MB/16MB on-board QSPI flash with XIP capabilities
- 26 GPIO pins
- 3 Analog inputs
- 2 UART peripherals
- 2 SPI controllers
- 2 I2C controllers
- 16 PWM channels
- USB 1.1 controller (host/device)
- 8 Programmable I/O (PIO) for custom peripherals
- On-board LED
- 1 Watchdog timer peripheral
- on-board battery charger


Supported Features
==================

.. zephyr:board-supported-hw::

Pin Mapping
===========

The peripherals of the RP2040 SoC 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.

.. figure:: img/rp2040_plus-details.webp
:align: center
:alt: Waveshare RP2040-Plus pinout overview

Default Zephyr Peripheral Mapping:
----------------------------------

.. rst-class:: rst-columns

- UART0_TX : P0
- UART0_RX : P1
- I2C0_SDA : P4
- I2C0_SCL : P5
- I2C1_SDA : P6
- I2C1_SCL : P7
- SPI0_RX : P16
- SPI0_CSN : P17
- SPI0_SCK : P18
- SPI0_TX : P19
- ADC_CH0 : P26
- ADC_CH1 : P27
- ADC_CH2 : P28

Programming and Debugging
*************************

.. zephyr:board-supported-runners::

Flashing
========

Using UF2
---------

Here is an example of building the sample for driving the built-in led.

.. zephyr-app-commands::
:zephyr-app: samples/basic/blinky
:board: rp2040_plus
:goals: build
:compact:

You must flash the RP2040-Plus with an UF2 file. One option is to use West (Zephyr’s meta-tool). To enter the UF2 flashing mode just keep the ``BOOT`` button pressed while you connect the USB port, it will appear on the host as a mass storage device. In alternative with the board already connected via USB you can keep the ``RESET`` button pressed, press and release ``BOOT``, release ``RESET``. At this point you can flash the image file by running:

.. code-block:: bash

west flash

Alternatively, you can locate the generated :file:`build/zephyr/zephyr.uf2` file and simply drag-and-drop to the device after entering the UF2 flashing mode.

References
**********

- `Official Documentation`_

.. _Official Documentation: https://www.waveshare.com/wiki/RP2040-Plus
57 changes: 57 additions & 0 deletions boards/waveshare/rp2040_plus/rp2040_plus-pinctrl.dtsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/

#include <dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h>
#include <dt-bindings/i2c/i2c.h>

&pinctrl {
uart0_default: uart0_default {
group1 {
pinmux = <UART0_TX_P0>;
};
group2 {
pinmux = <UART0_RX_P1>;
input-enable;
};
};

i2c0_default: i2c0_default {
group1 {
pinmux = <I2C0_SDA_P4>, <I2C0_SCL_P5>;
input-enable;
input-schmitt-enable;
};
};

i2c1_default: i2c1_default {
group1 {
pinmux = <I2C1_SDA_P6>, <I2C1_SCL_P7>;
input-enable;
input-schmitt-enable;
};
};

spi0_default: spi0_default {
group1 {
pinmux = <SPI0_CSN_P17>, <SPI0_SCK_P18>, <SPI0_TX_P19>;
};
group2 {
pinmux = <SPI0_RX_P16>;
input-enable;
};
};

pwm_ch4b_default: pwm_ch4b_default {
group1 {
pinmux = <PWM_4B_P25>;
};
};

adc_default: adc_default {
group1 {
pinmux = <ADC_CH0_P26>, <ADC_CH1_P27>, <ADC_CH2_P28>, <ADC_CH3_P29>;
input-enable;
};
};
};
200 changes: 200 additions & 0 deletions boards/waveshare/rp2040_plus/rp2040_plus.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/

/dts-v1/;

#include <freq.h>
#include <zephyr/dt-bindings/pwm/pwm.h>
#include <raspberrypi/rpi_pico/rp2040.dtsi>

#include "rp2040_plus-pinctrl.dtsi"

/ {
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,flash-controller = &ssi;
zephyr,console = &uart0;
zephyr,shell-uart = &uart0;
zephyr,code-partition = &code_partition;
};

aliases {
rtc = &rtc;
watchdog0 = &wdt0;
led0 = &led0;
pwm-led0 = &pwm_led0;
};

pico_header: connector {
compatible = "raspberrypi,pico-header";
#gpio-cells = <2>;
gpio-map-mask = <0xffffffff 0xffffffc0>;
gpio-map-pass-thru = <0 0x3f>;
gpio-map = <0 0 &gpio0 0 0>, /* GP0 */
<1 0 &gpio0 1 0>, /* GP1 */
<2 0 &gpio0 2 0>, /* GP2 */
<3 0 &gpio0 3 0>, /* GP3 */
<4 0 &gpio0 4 0>, /* GP4 */
<5 0 &gpio0 5 0>, /* GP5 */
<6 0 &gpio0 6 0>, /* GP6 */
<7 0 &gpio0 7 0>, /* GP7 */
<8 0 &gpio0 8 0>, /* GP8 */
<9 0 &gpio0 9 0>, /* GP9 */
<10 0 &gpio0 10 0>, /* GP10 */
<11 0 &gpio0 11 0>, /* GP11 */
<12 0 &gpio0 12 0>, /* GP12 */
<13 0 &gpio0 13 0>, /* GP13 */
<14 0 &gpio0 14 0>, /* GP14 */
<15 0 &gpio0 15 0>, /* GP15 */
<16 0 &gpio0 16 0>, /* GP16 */
<17 0 &gpio0 17 0>, /* GP17 */
<18 0 &gpio0 18 0>, /* GP18 */
<19 0 &gpio0 19 0>, /* GP19 */
<20 0 &gpio0 20 0>, /* GP20 */
<21 0 &gpio0 21 0>, /* GP21 */
<22 0 &gpio0 22 0>, /* GP22 */
<26 0 &gpio0 26 0>, /* GP26 */
<27 0 &gpio0 27 0>, /* GP27 */
<28 0 &gpio0 28 0>; /* GP28 */
};

leds {
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
label = "LED";
};
};

pwm_leds {
compatible = "pwm-leds";
status = "disabled";
pwm_led0: pwm_led_0 {
pwms = <&pwm 9 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
label = "PWM_LED";
};
};

vbatt: vbatt {
compatible = "voltage-divider";
io-channels = <&adc 3>;
output-ohms = <100000>;
full-ohms = <(200000 + 100000)>;
};
};

&flash0 {
reg = <0x10000000 DT_SIZE_M(4)>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be two variants: a 4MB and a 16MB. It would be good to reflect this in the codebase.

Not a blocker.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What solution do you propose to support both variants?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think within Zephyr's parlance they'd be different board variants. Not a blocker, and defaulting to the smaller 4MB is the safer thing to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

followup PR: #92384


partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

/* Reserved memory for the second stage bootloader */
second_stage_bootloader: partition@0 {
label = "second_stage_bootloader";
reg = <0x00000000 0x100>;
read-only;
};

/*
* Usable flash. Starts at 0x100, after the bootloader. The partition
* size is 4MB minus the 0x100 bytes taken by the bootloader.
*/
code_partition: partition@100 {
label = "code-partition";
reg = <0x100 (DT_SIZE_M(4) - 0x100)>;
read-only;
};
};
};

&uart0 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};

&i2c0 {
status = "okay";
pinctrl-0 = <&i2c0_default>;
pinctrl-names = "default";
clock-frequency = <I2C_BITRATE_STANDARD>;
};

&i2c1 {
pinctrl-0 = <&i2c1_default>;
pinctrl-names = "default";
clock-frequency = <I2C_BITRATE_FAST>;
};

&spi0 {
clock-frequency = <DT_FREQ_M(8)>;
status = "okay";
pinctrl-0 = <&spi0_default>;
pinctrl-names = "default";
};

&timer {
status = "okay";
};

&wdt0 {
status = "okay";
};

&gpio0 {
status = "okay";
};

&rtc {
clocks = <&clocks RPI_PICO_CLKID_CLK_RTC>;
status = "okay";
};

&adc {
status = "okay";
pinctrl-0 = <&adc_default>;
pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;

channel@3 {
reg = <3>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <12>;
};

channel@4 {
reg = <4>;
zephyr,gain = "ADC_GAIN_1";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <12>;
Comment on lines +166 to +179
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's going on with these ADC channels? I've looked at the circuit diagram at https://files.waveshare.com/wiki/RP2040-Plus/RP2040_Plus.pdf but I can't see the ADCs being used.

Can you offer a bit more information?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ADC channel 3 (GPIO29) is connected to VSYS via voltage divider R2/R8.
To keep it compatible with samples/boards/nordic/battery I choose "vbatt" as node name although technically not 100% correct as it will be ~0.4V lower than the actual battery voltage.
https://github.com/dsch/zephyr/blob/9aad3493350f8d0d86f5a1442fe5bbff8b4d8667/boards/waveshare/rp2040_plus/rp2040_plus.dts#L80-L85

ADC channel 4 is connected to on-chip temperature sensor. This channel is used in "dietemp" node:

die_temp: dietemp {
compatible = "raspberrypi,pico-temp";
io-channels = <&adc 4>;
status = "disabled";
};

Refer to RP2040 Datasheet, section 4.9. ADC and Temperature Sensor

};
};

zephyr_udc0: &usbd {
status = "okay";
};

&pwm {
pinctrl-0 = <&pwm_ch4b_default>;
pinctrl-names = "default";
};

&vreg {
regulator-always-on;
regulator-allowed-modes = <REGULATOR_RPI_PICO_MODE_NORMAL>;
};

pico_spi: &spi0 {};
pico_i2c0: &i2c0 {};
pico_i2c1: &i2c1 {};
pico_serial: &uart0 {};
Loading