mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
boards/arm/rp23xx: Add support for the Pimoroni Pico Plus 2 W.
The Pimoroni Pico Plus 2 W is a Pico form-factor board built around the
RP2350B, the 80-pin part with 48 GPIOs, carrying 16MB of flash, 8MB of PSRAM
and a Raspberry Pi RM2 module for 2.4GHz WiFi. The RM2 houses an Infineon
CYW43439, wired to the same pins the Raspberry Pi Pico W uses: GPIO 23 for
power enable, 24 for the shared gSPI data and interrupt line, 25 for chip
select and 29 for the clock.
Three configurations are provided: nsh and usbnsh without the wireless chip,
and wifi, which brings up wlan0 in station mode with WAPI, a DHCP client and
ping. The CYW43439 firmware and CLM blob are linked in from the pico-sdk at
build time, as on the Pico W; CONFIG_CYW43439_FIRMWARE_BIN_PATH selects the
file and the board documentation covers converting it out of the C header that
pico-sdk 2.x ships in place of the binary. rp23xx_firmware.c is placed in the
common source directory so that a future board with the same chip can reuse
it, and unlike rp2040 the blob is staged for the CMake build as well.
Two board details are worth calling out:
- The only LED is wired to GPIO 0 of the CYW43439 rather than to a pin of
the RP2350, so driving it means an iovar request over the gSPI bus. That
works for CONFIG_USERLED but not for CONFIG_ARCH_LEDS, whose
board_autoled_on() is called from interrupt handlers and from assertion
handling, so a build selecting CONFIG_ARCH_LEDS is rejected with an
explicit message. The LED also only responds once wlan0 has been brought
up, because that is when the chip's firmware is downloaded.
- The BOOT button is also wired to GPIO 45, so it can be read as an ordinary
user button once NuttX is running. Its internal pull-up is enabled
deliberately: erratum RP2350-E9 means a floating Bank 0 input on RP2350 A2
leaks enough current to settle around 2.2V, which the internal pull-down
cannot overcome.
Tested on the board with a Raspberry Pi Debug Probe: nsh and wifi boot on
UART0, wlan0 reports the MAC read from the chip, wapi scan lists access
points, and association to a WPA2 network followed by DHCP gives a working
route with ping succeeding to both a literal address and a resolved name.
The LED and the BOOT button were confirmed by hand.
Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
parent
4cb00df87a
commit
eea880f1ac
29 changed files with 3558 additions and 0 deletions
|
|
@ -0,0 +1,276 @@
|
|||
======================
|
||||
Pimoroni Pico Plus 2 W
|
||||
======================
|
||||
|
||||
.. tags:: chip:rp2350, chip:rp2350b, wifi
|
||||
|
||||
The `Pimoroni Pico Plus 2 W <https://shop.pimoroni.com/products/pimoroni-pico-plus-2-w>`_
|
||||
is a Raspberry Pi Pico form-factor board built around the RP2350B -- the 80-pin
|
||||
variant of the RP2350 with 48 GPIOs. It adds 16MB of flash, 8MB of PSRAM, a
|
||||
USB-C connector, a Qw/ST (Qwiic/STEMMA QT) connector, and an Infineon CYW43439
|
||||
for 2.4GHz WiFi and Bluetooth. The radio is carried on a Raspberry Pi RM2
|
||||
module, which is where the CYW43439 lives.
|
||||
|
||||
.. figure:: pimoroni-pico-plus-2-w.jpg
|
||||
:align: center
|
||||
|
||||
Pimoroni Pico Plus 2 W, front and back (photo: Pimoroni)
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
* RP2350B microcontroller chip (QFN-80 package)
|
||||
* Dual-core ARM Cortex-M33 processor at up to 150MHz, with FPU and DSP
|
||||
* Also contains two Hazard3 RISC-V cores, selectable instead of the M33 pair
|
||||
* 520kB of on-chip SRAM
|
||||
* 16MB of on-board QSPI flash
|
||||
* 8MB of on-board QSPI PSRAM (chip select on GPIO 47)
|
||||
* 48 multi-function GPIO pins, 30 of them on the castellated headers
|
||||
* 4x UART, 2x SPI, 2x I2C, 8x 12-bit ADC, 24x PWM channels
|
||||
* 12x Programmable IO (PIO) state machines across 3 PIO blocks
|
||||
* USB-C, supporting device and host
|
||||
* Infineon CYW43439 for 2.4GHz WiFi 4 (802.11n) and Bluetooth 5.2
|
||||
* Qw/ST connector on I2C0
|
||||
* BOOT and RESET buttons; BOOT is also readable at runtime on GPIO 45
|
||||
* Battery connector with charging, and VSYS monitoring on GPIO 43
|
||||
|
||||
Serial Console
|
||||
==============
|
||||
|
||||
By default the serial console is UART0 on GPIO 0 (TX, pin 1) and GPIO 1
|
||||
(RX, pin 2), at 115200-8N1.
|
||||
|
||||
The board can instead be configured to put the console on the USB-C connector
|
||||
(the ``usbnsh`` configuration). Note that the RP2350 USB device support is
|
||||
still marked experimental in NuttX and the CDC/ACM console is known to corrupt
|
||||
data and stop responding after a handful of commands. Prefer the UART console
|
||||
for anything that matters.
|
||||
|
||||
Wireless Communication
|
||||
======================
|
||||
|
||||
The on-board Infineon CYW43439 is reached over a half-duplex gSPI bus driven by
|
||||
a PIO state machine, implemented in ``arch/arm/src/rp23xx/rp23xx_cyw43439.c``.
|
||||
It presents itself as the ``wlan0`` network device and supports 2.4GHz WiFi 4
|
||||
(802.11n) in station mode. Bluetooth is not supported.
|
||||
|
||||
The chip's firmware is not downloaded until ``wlan0`` is brought up, so nothing
|
||||
on the wireless chip -- including the LED, see below -- responds before that.
|
||||
|
||||
CYW43439 firmware
|
||||
-----------------
|
||||
|
||||
The driver links the wireless chip's firmware and CLM blob into the NuttX
|
||||
binary, so a copy has to be available at build time. ``CONFIG_CYW43439_FIRMWARE_BIN_PATH``
|
||||
points at it and defaults to::
|
||||
|
||||
${PICO_SDK_PATH}/lib/cyw43-driver/firmware/43439A0-7.95.49.00.combined
|
||||
|
||||
This is the WiFi firmware padded up to a 256-byte boundary with the CLM blob
|
||||
appended, and ``CONFIG_CYW43439_FIRMWARE_LEN`` is the *unpadded* length of just
|
||||
the firmware part (224190 bytes for this release).
|
||||
|
||||
pico-sdk 2.x no longer ships that file as a binary -- it only carries the same
|
||||
bytes as a C array in ``lib/cyw43-driver/firmware/w43439A0_7_95_49_00_combined.h``.
|
||||
If that is all you have, convert the array back to a binary, for example::
|
||||
|
||||
$ python3 -c '
|
||||
import re, sys
|
||||
text = open(sys.argv[1]).read()
|
||||
body = text.split("{", 1)[1].split("};", 1)[0]
|
||||
data = bytes(int(b, 16) for b in re.findall(r"0x([0-9a-fA-F]{2})", body))
|
||||
open(sys.argv[2], "wb").write(data)
|
||||
' ${PICO_SDK_PATH}/lib/cyw43-driver/firmware/w43439A0_7_95_49_00_combined.h \
|
||||
${PICO_SDK_PATH}/lib/cyw43-driver/firmware/43439A0-7.95.49.00.combined
|
||||
|
||||
The header's own ``CYW43_WIFI_FW_LEN`` and ``CYW43_CLM_LEN`` macros tell you the
|
||||
lengths to expect: 224190 + 984, in a 225240-byte file.
|
||||
|
||||
If the file is missing the build still succeeds, but a placeholder is linked in
|
||||
and the wireless chip will not come up.
|
||||
|
||||
User LED
|
||||
========
|
||||
|
||||
**The board's only LED is wired to GPIO 0 of the CYW43439, not to a pin of the
|
||||
RP2350.** Setting it therefore means an iovar request over the gSPI bus, which
|
||||
has two consequences:
|
||||
|
||||
* The LED does not respond until ``wlan0`` has been brought up, because that is
|
||||
when the wireless chip's firmware is downloaded. Before that, every write
|
||||
fails with ``-EIO``.
|
||||
* Driving the LED blocks, so it cannot be done from interrupt context. That
|
||||
rules out ``CONFIG_ARCH_LEDS``, whose ``board_autoled_on()`` is called from
|
||||
interrupt handlers and from assertion handling. This board therefore
|
||||
supports ``CONFIG_USERLED`` only, and a build with ``CONFIG_ARCH_LEDS``
|
||||
enabled is rejected with an explicit error.
|
||||
|
||||
With ``CONFIG_USERLED`` the LED appears as ``/dev/userleds`` and can be driven
|
||||
with the ``leds`` example. Board code can also reach it, and the CYW43439's
|
||||
other two GPIOs, through ``include/rp23xx_extra_gpio.h``:
|
||||
|
||||
===== ========= ==============================================================
|
||||
GPIO Direction Function
|
||||
===== ========= ==============================================================
|
||||
0 output On-board LED
|
||||
1 output Voltage regulator mode: 1 selects PWM (less ripple) over PFM
|
||||
2 input Non-zero if power is coming from USB or the VBUS pin
|
||||
===== ========= ==============================================================
|
||||
|
||||
Buttons
|
||||
-------
|
||||
|
||||
The board has two physical buttons, BOOT and RESET.
|
||||
|
||||
BOOT is also wired to GPIO 45, active low, so once NuttX is running it can be
|
||||
read as an ordinary user button -- this is the pin pico-sdk calls
|
||||
``PIMORONI_PICO_PLUS2_W_USER_SW_PIN``. It appears as ``/dev/buttons`` with
|
||||
``CONFIG_INPUT_BUTTONS``, and is the single button reported by
|
||||
``board_buttons()``. RESET is not readable as a GPIO.
|
||||
|
||||
The internal pull-up is enabled on GPIO 45, and must be: erratum RP2350-E9
|
||||
means a floating Bank 0 input on RP2350 A2 leaks around 120uA and settles at
|
||||
roughly 2.2V, which the internal pull-down is far too weak to overcome. The
|
||||
pull-up is unaffected by the erratum.
|
||||
|
||||
Held down while power is applied or while RESET is released, BOOT instead makes
|
||||
the RP2350 come up in bootloader mode, where it appears as a storage device over
|
||||
USB; copying a .UF2 file to it replaces the flash contents.
|
||||
|
||||
Pin Mapping
|
||||
===========
|
||||
|
||||
The castellated headers follow the Raspberry Pi Pico pinout, with the RP2350B's
|
||||
extra GPIOs brought out on the two rows of pads inside the headers.
|
||||
|
||||
===== ========== =============================================================
|
||||
Pin Signal Notes
|
||||
===== ========== =============================================================
|
||||
1 GPIO0 Default TX for UART0 serial console
|
||||
2 GPIO1 Default RX for UART0 serial console
|
||||
3 Ground
|
||||
4 GPIO2
|
||||
5 GPIO3
|
||||
6 GPIO4 Default SDA for I2C0, also on the Qw/ST connector
|
||||
7 GPIO5 Default SCL for I2C0, also on the Qw/ST connector
|
||||
8 Ground
|
||||
9 GPIO6
|
||||
10 GPIO7
|
||||
11 GPIO8
|
||||
12 GPIO9
|
||||
13 Ground
|
||||
14 GPIO10
|
||||
15 GPIO11
|
||||
16 GPIO12
|
||||
17 GPIO13
|
||||
18 Ground
|
||||
19 GPIO14
|
||||
20 GPIO15
|
||||
21 GPIO16 Default RX for SPI0
|
||||
22 GPIO17 Default CSn for SPI0
|
||||
23 Ground
|
||||
24 GPIO18 Default SCK for SPI0
|
||||
25 GPIO19 Default TX for SPI0
|
||||
26 GPIO20
|
||||
27 GPIO21
|
||||
28 Ground
|
||||
29 GPIO22
|
||||
30 Run
|
||||
31 GPIO26 ADC0
|
||||
32 GPIO27 ADC1
|
||||
33 AGND Analog ground
|
||||
34 GPIO28 ADC2
|
||||
35 ADC_VREF Analog reference voltage
|
||||
36 3V3 Power output to peripherals
|
||||
37 3V3_EN Pull to ground to turn off
|
||||
38 Ground
|
||||
39 VSYS +5V supply to the board
|
||||
40 VBUS Connected to USB +5V
|
||||
===== ========== =============================================================
|
||||
|
||||
Other RP2350B Pins
|
||||
==================
|
||||
|
||||
===== ================================================================
|
||||
GPIO Function
|
||||
===== ================================================================
|
||||
23 Output - CYW43439 power enable (WL_REG_ON)
|
||||
24 I/O - CYW43439 gSPI data line, doubles as its interrupt request
|
||||
25 Output - CYW43439 chip select
|
||||
29 Output - CYW43439 gSPI clock
|
||||
43 Input - VSYS monitoring, via ADC
|
||||
45 Input - BOOT button, active low, readable as a user button
|
||||
47 Output - PSRAM chip select
|
||||
===== ================================================================
|
||||
|
||||
Note that GPIO 23, 24, 25 and 29 are the same pins the Raspberry Pi Pico W uses
|
||||
for its CYW43439, so the wireless wiring is identical despite the larger
|
||||
package. Do not use them for anything else.
|
||||
|
||||
Installation & Build
|
||||
====================
|
||||
|
||||
For instructions on how to install the build dependencies and create a NuttX
|
||||
image for this board, consult the main :doc:`RP23XX documentation <../../index>`.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
|
||||
All configurations listed below can be configured using the following command
|
||||
in the ``nuttx`` directory (again, consult the main
|
||||
:doc:`RP23XX documentation <../../index>`):
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ ./tools/configure.sh pimoroni-pico-plus-2-w:<configname>
|
||||
|
||||
nsh
|
||||
---
|
||||
|
||||
Basic NuttShell configuration, console on UART0 at 115200 bps. The wireless
|
||||
chip is not enabled, so this configuration has no network and no LED.
|
||||
|
||||
usbnsh
|
||||
------
|
||||
|
||||
Basic NuttShell configuration with the console on USB CDC/ACM at 115200 bps.
|
||||
See the caveat under `Serial Console`_.
|
||||
|
||||
wifi
|
||||
----
|
||||
|
||||
NuttShell configuration with the console on UART0 at 115200 bps and the
|
||||
CYW43439 enabled: ``wlan0`` in station mode, WAPI, DHCP client, DNS client and
|
||||
``ping``. ``/dev/userleds`` and ``/dev/buttons`` are registered too.
|
||||
|
||||
After loading this configuration, set the country code to match your region in
|
||||
:menuselection:`Device Drivers --> Wireless Device Support --> IEEE 802.11 Device Support`,
|
||||
and set your network's credentials in
|
||||
:menuselection:`Application Configuration --> Network Utilities --> Network initialization --> WAPI Configuration`.
|
||||
|
||||
Alternatively, leave the built-in credentials alone and associate at runtime:
|
||||
|
||||
.. code:: console
|
||||
|
||||
nsh> wapi mode wlan0 2
|
||||
nsh> wapi psk wlan0 "my-passphrase" 3 2
|
||||
nsh> wapi essid wlan0 my-ssid 1
|
||||
nsh> renew wlan0
|
||||
nsh> ifconfig
|
||||
lo Link encap:Local Loopback at RUNNING mtu 1518
|
||||
inet addr:127.0.0.1 DRaddr:127.0.0.1 Mask:255.0.0.0
|
||||
|
||||
wlan0 Link encap:Ethernet HWaddr 28:cd:c1:ff:d3:be at RUNNING mtu 576
|
||||
inet addr:192.168.0.118 DRaddr:192.168.0.1 Mask:255.255.255.0
|
||||
|
||||
nsh> ping -c 3 8.8.8.8
|
||||
PING 8.8.8.8 56 bytes of data
|
||||
56 bytes from 8.8.8.8: icmp_seq=0 time=20.0 ms
|
||||
56 bytes from 8.8.8.8: icmp_seq=1 time=10.0 ms
|
||||
56 bytes from 8.8.8.8: icmp_seq=2 time=10.0 ms
|
||||
3 packets transmitted, 3 received, 0% packet loss, time 3030 ms
|
||||
rtt min/avg/max/mdev = 10.000/13.333/20.000/4.714 ms
|
||||
|
||||
The ``3`` and ``2`` arguments to ``wapi psk`` select WPA_ALG_CCMP and WPA_VER_2;
|
||||
run ``wapi help`` for the other values. ``wapi scan wlan0`` lists the visible
|
||||
access points.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 441 KiB |
Loading…
Add table
Add a link
Reference in a new issue