diff --git a/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst new file mode 100644 index 00000000000..486c4f2c844 --- /dev/null +++ b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/index.rst @@ -0,0 +1,172 @@ +=============================== +Pimoroni Pico Plus 2 +=============================== + +.. tags:: chip:rp2350 + +The `Pimoroni Pico Plus 2 `_ +is an RP2350B based board in the Raspberry Pi Pico form factor, with a +USB-C connector, a large 16 MiB of flash and 8 MiB of external QSPI PSRAM. + +.. figure:: pico-plus-2.jpg + :align: center + +Features +======== + +* RP2350B microcontroller chip (QFN-80 variant) +* Dual-core Arm Cortex-M33 processor running up to 150 MHz +* 520 KiB of internal SRAM +* 16 MiB of on-board QSPI flash memory +* 8 MiB of on-board QSPI PSRAM (APS6404) on chip select 1 +* USB-C connector, USB 1.1 host and device support +* Qwiic / STEMMA QT (I2C) connector +* SP/CE debug and expansion connectors +* Reset and BOOTSEL buttons +* 48 multi-function GPIO pins broken out on castellated and through-hole pads +* Drag & drop programming using mass storage over USB +* 12 Programmable IO (PIO) state machines for custom peripheral support + +Serial Console +============== + +By default a serial console appears on GPIO0 (TX) and GPIO1 (RX). This +console runs at 115200-8N1. + +The board can be configured to use the USB connection as the serial console. +See the ``usbnsh`` configuration. + +Buttons and LEDs +================ + +The user LED is controlled by GPIO25 and is configured as autoled by default. + +A BOOTSEL button, which if held down when power is first applied to the board, +will cause the RP2350 to boot into programming mode and appear as a storage +device to the computer connected via USB. Saving a ``.uf2`` file to this +device will replace the flash contents. A separate RESET button is also +provided. + +PSRAM +===== + +The distinguishing feature of the Pimoroni Pico Plus 2 is the 8 MiB of +external QSPI PSRAM (an APS6404 part) hanging off the QMI on chip select 1 +(GPIO47). NuttX detects the PSRAM at boot, switches it to quad mode and +maps it read/write at ``0x11000000``. + +PSRAM support is enabled by default in the ``nsh`` configuration +(``CONFIG_RP23XX_PSRAM``), which adds the 8 MiB to the main heap. The +chip select pin is configured with ``CONFIG_RP23XX_PSRAM_CS1_GPIO`` (47 on +this board) and the way the PSRAM is exposed to the memory manager (single +heap, separate heap, or user heap) is selectable. See the +:doc:`RP23xx PSRAM section <../../index>` for the details of each mode. + +.. note:: + + The PSRAM is considerably slower than the internal SRAM. The QMI is + shared with the flash: writing to the flash goes through the bootrom, + which reconfigures the QMI for chip select 0 and disturbs the PSRAM + configuration on chip select 1. ``rp23xx_psram_restore()`` re-applies it + and is intended to be called from the flash write path after each erase or + program. + +Supported Capabilities +====================== + +NuttX supports the following Pico Plus 2 capabilities: + +* UART (console port) + + * GPIO 0 (UART0 TX) and GPIO 1 (UART0 RX) are used for the console. + +* External QSPI PSRAM (8 MiB) +* I2C +* SPI (master only) +* DMAC +* PWM +* ADC +* Watchdog +* USB device + + * MSC, CDC/ACM serial and composite devices are supported. + * CDC/ACM serial device can be used for the console. + +* PIO (RP2350 Programmable I/O) +* Flash ROM Boot +* SRAM Boot + + * If the Pico SDK is available, a ``nuttx.uf2`` file which can be used in + BOOTSEL mode will be created. + +* Persistent flash filesystem in unused flash ROM + +Installation +============ + +1. Download and install the toolchain and, optionally, the Raspberry Pi + Pico SDK (needed to generate the ``nuttx.uf2`` image). + +.. code-block:: console + + $ git clone -b 2.2.0 --recurse-submodules https://github.com/raspberrypi/pico-sdk.git + $ export PICO_SDK_PATH= + +2. Configure and build NuttX + +.. code-block:: console + + $ git clone https://github.com/apache/nuttx.git nuttx + $ git clone https://github.com/apache/nuttx-apps.git apps + $ cd nuttx + $ make distclean + $ ./tools/configure.sh pimoroni-pico-2-plus:nsh + $ make V=1 + +3. Connect the board to the USB port while pressing BOOTSEL. The board will + be detected as a USB Mass Storage Device. Then copy ``nuttx.uf2`` into + the device (the same way as standard Pico SDK applications). + +4. To access the console, connect GPIO 0 and 1 to a device such as a + USB-serial converter, or use the ``usbnsh`` configuration for a console + over USB CDC/ACM. + +Configurations +============== + +nsh +--- + +Basic NuttShell configuration (console enabled on UART0, at 115200 bps) with +the external PSRAM added to the main heap. + +usbnsh +------ + +Basic NuttShell configuration (console enabled via USB CDC/ACM). + +smp +--- + +Basic NuttShell configuration (console enabled on UART0, at 115200 bps) with +both Arm cores enabled. + +audiopack +--------- + +Configuration for the Pimoroni Pico Audio Pack. + +composite +--------- + +USB composite device configuration. + +usbmsc +------ + +USB mass storage device configuration. + +userled +------- + +Configuration demonstrating user-controlled LED access. diff --git a/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/pico-plus-2.jpg b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/pico-plus-2.jpg new file mode 100644 index 00000000000..d12129fd105 Binary files /dev/null and b/Documentation/platforms/arm/rp23xx/boards/pimoroni-pico-2-plus/pico-plus-2.jpg differ diff --git a/arch/arm/src/rp23xx/CMakeLists.txt b/arch/arm/src/rp23xx/CMakeLists.txt index 6036cb04ebf..814a1007859 100644 --- a/arch/arm/src/rp23xx/CMakeLists.txt +++ b/arch/arm/src/rp23xx/CMakeLists.txt @@ -105,4 +105,8 @@ if(CONFIG_RP23XX_FLASH_MTD) list(APPEND SRCS rp23xx_flash_mtd.c) endif() +if(CONFIG_RP23XX_PSRAM) + list(APPEND SRCS rp23xx_psram.c rp23xx_heaps.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rp23xx/Kconfig b/arch/arm/src/rp23xx/Kconfig index cb71ef9f529..0713e4f8721 100644 --- a/arch/arm/src/rp23xx/Kconfig +++ b/arch/arm/src/rp23xx/Kconfig @@ -9,6 +9,51 @@ config RP23XX_RP2350B bool "Use RP2350B variant (QFN-80)" default n +config RP23XX_PSRAM + bool "External QSPI PSRAM" + default n + ---help--- + Enable support for external QSPI PSRAM connected to QMI chip + select 1, such as the 8 MiB APS6404 fitted on the Pimoroni Pico + Plus 2. The chip is detected and switched to quad mode at boot, + after which it is directly addressable and writable at + 0x11000000. Configure the chip-select pin under the Board + Selection menu (RP23XX_PSRAM_CS1_GPIO). + +if RP23XX_PSRAM + +choice + prompt "PSRAM heap usage" + default RP23XX_PSRAM_HEAP_SINGLE + ---help--- + How the detected PSRAM is exposed to the memory manager. + +config RP23XX_PSRAM_HEAP_SINGLE + bool "Add PSRAM to the main heap" + depends on !MM_KERNEL_HEAP + ---help--- + Add the PSRAM region to the main heap. Requires + CONFIG_MM_REGIONS greater than 1 so the extra region can be + registered. + +config RP23XX_PSRAM_HEAP_USER + bool "PSRAM as the user heap" + depends on MM_KERNEL_HEAP + ---help--- + Use the PSRAM as the (user) heap and the internal SRAM as the + kernel heap. + +config RP23XX_PSRAM_HEAP_SEPARATE + bool "Separate PSRAM heap" + select ARCH_HAVE_EXTRA_HEAPS + ---help--- + Expose the PSRAM as a separate named heap ("psram") rather than + adding it to the main heap. + +endchoice + +endif # RP23XX_PSRAM + config RP23XX_DMAC bool "DMAC support" default y diff --git a/arch/arm/src/rp23xx/Make.defs b/arch/arm/src/rp23xx/Make.defs index 8f59e6aac6d..040f23ff868 100644 --- a/arch/arm/src/rp23xx/Make.defs +++ b/arch/arm/src/rp23xx/Make.defs @@ -108,3 +108,8 @@ endif ifeq ($(CONFIG_RP23XX_FLASH_MTD),y) CHIP_CSRCS += rp23xx_flash_mtd.c endif + +ifeq ($(CONFIG_RP23XX_PSRAM),y) +CHIP_CSRCS += rp23xx_psram.c +CHIP_CSRCS += rp23xx_heaps.c +endif diff --git a/arch/arm/src/rp23xx/hardware/rp23xx_qmi.h b/arch/arm/src/rp23xx/hardware/rp23xx_qmi.h index 0030d723a13..2be63cccbae 100644 --- a/arch/arm/src/rp23xx/hardware/rp23xx_qmi.h +++ b/arch/arm/src/rp23xx/hardware/rp23xx_qmi.h @@ -33,6 +33,10 @@ * Pre-processor Definitions ****************************************************************************/ +/* The QMI registers share the XIP-QMI peripheral base. */ + +#define RP23XX_QMI_BASE RP23XX_XIP_QMI_BASE + /* Register offsets *********************************************************/ #define RP23XX_QMI_DIRECT_CSR_OFFSET 0x00000000 diff --git a/arch/arm/src/rp23xx/rp23xx_heaps.c b/arch/arm/src/rp23xx/rp23xx_heaps.c index 725aeac6ad2..a2b57df4f10 100644 --- a/arch/arm/src/rp23xx/rp23xx_heaps.c +++ b/arch/arm/src/rp23xx/rp23xx_heaps.c @@ -30,15 +30,21 @@ #include #include "arm_internal.h" +#include "rp23xx_psram.h" #if defined(CONFIG_RP23XX_PSRAM) /**************************************************************************** - * Private Data + * Pre-processor Definitions ****************************************************************************/ -static void * const psram_start = (void *)0x11000000ul; -static const size_t psram_size = 8 * 1024 * 1024; +/* The PSRAM base address is fixed; the size is whatever rp23xx_psramconfig() + * detected at boot (0 if no PSRAM is fitted). psramconfig() runs from + * rp23xx_boardinitialize(), before any of the heap hooks below, so the + * detected size is always available here. + */ + +#define PSRAM_START ((void *)RP23XX_PSRAM_BASE) /**************************************************************************** * Public Functions @@ -56,9 +62,14 @@ static struct mm_heap_s *g_psramheap; #if CONFIG_MM_REGIONS > 1 void arm_addregion(void) { - /* Add the PSRAM region to main heap */ + size_t psram_size = rp23xx_psram_size(); - kumm_addregion(psram_start, psram_size); + /* Add the detected PSRAM region to the main heap */ + + if (psram_size > 0) + { + kumm_addregion(PSRAM_START, psram_size); + } } #endif @@ -85,8 +96,8 @@ void up_allocate_kheap(void **heap_start, size_t *heap_size) void up_allocate_heap(void **heap_start, size_t *heap_size) { - *heap_start = psram_start; - *heap_size = psram_size; + *heap_start = PSRAM_START; + *heap_size = rp23xx_psram_size(); } #elif defined (CONFIG_RP23XX_PSRAM_HEAP_SEPARATE) @@ -97,7 +108,12 @@ void up_allocate_heap(void **heap_start, size_t *heap_size) void up_extraheaps_init(void) { - g_psramheap = mm_initialize("psram", psram_start, psram_size); + size_t psram_size = rp23xx_psram_size(); + + if (psram_size > 0) + { + g_psramheap = mm_initialize("psram", PSRAM_START, psram_size); + } } #endif diff --git a/arch/arm/src/rp23xx/rp23xx_psram.c b/arch/arm/src/rp23xx/rp23xx_psram.c new file mode 100644 index 00000000000..1aa155c1fd3 --- /dev/null +++ b/arch/arm/src/rp23xx/rp23xx_psram.c @@ -0,0 +1,346 @@ +/**************************************************************************** + * arch/arm/src/rp23xx/rp23xx_psram.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + * + * Driver for the external QSPI PSRAM (an APS6404-family part) fitted on + * boards such as the Pimoroni Pico Plus 2. It hangs off QMI chip select 1 + * and, once configured, is directly addressable and writable at + * RP23XX_PSRAM_BASE (0x11000000). + * + * The QMI is the same serial interface that serves execute-in-place from the + * flash on chip select 0. Reprogramming it uses direct (non-XIP) mode, + * which stalls all XIP fetches, so the detection and configuration code must + * run from RAM with interrupts disabled -- hence the .time_critical section, + * which the board linker scripts copy to RAM. The sequence follows the + * Raspberry Pi Pico SDK's setup_psram(). + * + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "arm_internal.h" +#include "rp23xx_gpio.h" +#include "rp23xx_psram.h" +#include "hardware/rp23xx_qmi.h" +#include "hardware/rp23xx_xip.h" +#include "hardware/rp23xx_memorymap.h" + +#ifdef CONFIG_RP23XX_PSRAM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Detection and (re)configuration touch the QMI in direct mode, which stalls + * execute-in-place from the flash. The code that does so must therefore run + * from RAM: the board linker scripts copy the .time_critical section there. + */ + +#define RP23XX_PSRAM_RAMFUNC \ + __attribute__((section(".time_critical.rp23xx_psram"), noinline)) + +/* GPIO function select for the XIP chip-select-1 line (PSRAM). */ + +#define RP23XX_GPIO_FUNC_XIP_CS1 9 + +/* PSRAM interface width for direct-mode transfers (quad). */ + +#define QMI_DIRECT_TX_IWIDTH_Q (2 << RP23XX_QMI_DIRECT_TX_IWIDTH_SHIFT) + +/* Final QMI M1 register values for the APS6404 in quad mode. Computed from + * the field layout in the RP2350 datasheet to match the Pico SDK: + * + * TIMING: COOLDOWN=1, PAGEBREAK=1024, SELECT_HOLD=3, MAX_SELECT=16, + * MIN_DESELECT=7, RXDELAY=1, CLKDIV=2. + * RFMT: quad prefix/addr/suffix/dummy/data, 8-bit prefix, 24 dummy bits. + * RCMD: read prefix 0xeb. + * WFMT: quad prefix/addr/suffix/dummy/data, 8-bit prefix, no dummy. + * WCMD: write prefix 0x38. + */ + +#define RP23XX_PSRAM_M1_TIMING 0x61a07102 +#define RP23XX_PSRAM_M1_RFMT 0x000612aa +#define RP23XX_PSRAM_M1_RCMD 0x000000eb +#define RP23XX_PSRAM_M1_WFMT 0x000012aa +#define RP23XX_PSRAM_M1_WCMD 0x00000038 + +/* APS6404 SPI opcodes used during detection and mode switching. */ + +#define PSRAM_CMD_READ_ID 0x9f +#define PSRAM_CMD_RSTEN 0x66 +#define PSRAM_CMD_RST 0x99 +#define PSRAM_CMD_QUAD_ENABLE 0x35 + +#define PSRAM_KGD_PASS 0x5d + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static size_t g_psram_size; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_psram_apply_format + * + * Description: + * Program the QMI M1 timing/format/command registers and mark the region + * writable. Shared by the initial configuration and the post-flash + * restore. Runs from RAM. + * + ****************************************************************************/ + +static void RP23XX_PSRAM_RAMFUNC +rp23xx_psram_apply_format(void) +{ + putreg32(RP23XX_PSRAM_M1_TIMING, RP23XX_QMI_M1_TIMING); + putreg32(RP23XX_PSRAM_M1_RFMT, RP23XX_QMI_M1_RFMT); + putreg32(RP23XX_PSRAM_M1_RCMD, RP23XX_QMI_M1_RCMD); + putreg32(RP23XX_PSRAM_M1_WFMT, RP23XX_QMI_M1_WFMT); + putreg32(RP23XX_PSRAM_M1_WCMD, RP23XX_QMI_M1_WCMD); + + /* Allow the memory-mapped window to accept writes. */ + + putreg32(getreg32(RP23XX_XIP_CTRL_BASE) | RP23XX_XIP_CTRL_WRITABLE_M1, + RP23XX_XIP_CTRL_BASE); +} + +/**************************************************************************** + * Name: rp23xx_psram_detect + * + * Description: + * Read the PSRAM device ID over the QMI direct interface and return the + * detected size in bytes, or 0 if the part does not respond correctly. + * Runs from RAM with the caller holding interrupts disabled. + * + ****************************************************************************/ + +static size_t RP23XX_PSRAM_RAMFUNC +rp23xx_psram_detect(void) +{ + uint8_t kgd = 0; + uint8_t eid = 0; + size_t size; + size_t i; + + /* Enable direct mode at a conservative clock divisor. No BUSY wait is + * needed for the previous XIP transfer's cooldown: it drains before the + * first chip-select assertion below (verified on hardware). + */ + + putreg32((30 << RP23XX_QMI_DIRECT_CSR_CLKDIV_SHIFT) | + RP23XX_QMI_DIRECT_CSR_EN, RP23XX_QMI_DIRECT_CSR); + + /* Nudge the part out of any quad-continuation mode left by a prior init by + * clocking one quad byte with CS asserted. + */ + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) | + RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N, RP23XX_QMI_DIRECT_CSR); + putreg32(RP23XX_QMI_DIRECT_TX_OE | QMI_DIRECT_TX_IWIDTH_Q | 0xf5, + RP23XX_QMI_DIRECT_TX); + + /* This BUSY wait is required: the frame must finish shifting before the + * chip select is deasserted, else the nudge is truncated, the part stays + * in quad-continuation mode, and the ID read below returns garbage so + * detection fails (verified on hardware). + */ + + while ((getreg32(RP23XX_QMI_DIRECT_CSR) & RP23XX_QMI_DIRECT_CSR_BUSY) != 0) + { + } + + (void)getreg32(RP23XX_QMI_DIRECT_RX); + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) & + ~RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N, RP23XX_QMI_DIRECT_CSR); + + /* Read the identification: command 0x9f followed by six bytes. The + * Known-Good-Die marker is byte 5 and the size code is byte 6. + */ + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) | + RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N, RP23XX_QMI_DIRECT_CSR); + for (i = 0; i < 7; i++) + { + putreg32(i == 0 ? PSRAM_CMD_READ_ID : 0xff, RP23XX_QMI_DIRECT_TX); + + /* This BUSY wait is required: the byte must finish shifting in before + * DIRECT_RX is read, else the KGD/EID bytes are sampled early as + * garbage and detection fails (verified on hardware). A TXEMPTY wait + * ahead of it is redundant -- BUSY already covers the whole transfer. + */ + + while ((getreg32(RP23XX_QMI_DIRECT_CSR) & + RP23XX_QMI_DIRECT_CSR_BUSY) != 0) + { + } + + if (i == 5) + { + kgd = (uint8_t)getreg32(RP23XX_QMI_DIRECT_RX); + } + else if (i == 6) + { + eid = (uint8_t)getreg32(RP23XX_QMI_DIRECT_RX); + } + else + { + (void)getreg32(RP23XX_QMI_DIRECT_RX); + } + } + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) & + ~(RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N | RP23XX_QMI_DIRECT_CSR_EN), + RP23XX_QMI_DIRECT_CSR); + + if (kgd != PSRAM_KGD_PASS) + { + return 0; + } + + /* Reset the device and place it in quad mode: RSTEN, RST, quad-enable. */ + + putreg32((30 << RP23XX_QMI_DIRECT_CSR_CLKDIV_SHIFT) | + RP23XX_QMI_DIRECT_CSR_EN, RP23XX_QMI_DIRECT_CSR); + + for (i = 0; i < 3; i++) + { + /* The command byte is selected with a ternary rather than a lookup + * table on purpose: a "static const" array is emitted to .rodata in + * flash, and reading it here -- while the QMI is in direct mode and + * flash is inaccessible -- would fault. An immediate keeps it in RAM. + */ + + uint8_t cmd = (i == 0) ? PSRAM_CMD_RSTEN : + (i == 1) ? PSRAM_CMD_RST : + PSRAM_CMD_QUAD_ENABLE; + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) | + RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N, RP23XX_QMI_DIRECT_CSR); + putreg32(cmd, RP23XX_QMI_DIRECT_TX); + + /* This BUSY wait is required: the command must finish shifting before + * the chip select is deasserted. Cutting it short truncates the + * RSTEN/RST/quad-enable commands, so the part is not reset into quad + * mode and later accesses fail or wedge the shared QMI bus (verified + * on hardware). No extra settling delay is needed after CS deassert: + * the QMI's own minimum-deselect timing covers it. + */ + + while ((getreg32(RP23XX_QMI_DIRECT_CSR) & + RP23XX_QMI_DIRECT_CSR_BUSY) != 0) + { + } + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) & + ~RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N, RP23XX_QMI_DIRECT_CSR); + + (void)getreg32(RP23XX_QMI_DIRECT_RX); + } + + putreg32(getreg32(RP23XX_QMI_DIRECT_CSR) & + ~(RP23XX_QMI_DIRECT_CSR_ASSERT_CS1N | RP23XX_QMI_DIRECT_CSR_EN), + RP23XX_QMI_DIRECT_CSR); + + /* Decode the size from the EID byte (APS6404 family). */ + + size = 1024 * 1024; + if (eid == 0x26 || (eid >> 5) == 2) + { + size *= 8; + } + else if ((eid >> 5) == 0) + { + size *= 2; + } + else if ((eid >> 5) == 1) + { + size *= 4; + } + + return size; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_psramconfig + ****************************************************************************/ + +size_t RP23XX_PSRAM_RAMFUNC +rp23xx_psramconfig(void) +{ + irqstate_t flags; + size_t size; + + rp23xx_gpio_set_function(CONFIG_RP23XX_PSRAM_CS1_GPIO, + RP23XX_GPIO_FUNC_XIP_CS1); + + flags = up_irq_save(); + + size = rp23xx_psram_detect(); + if (size != 0) + { + rp23xx_psram_apply_format(); + } + + up_irq_restore(flags); + + g_psram_size = size; + return size; +} + +/**************************************************************************** + * Name: rp23xx_psram_size + ****************************************************************************/ + +size_t rp23xx_psram_size(void) +{ + return g_psram_size; +} + +/**************************************************************************** + * Name: rp23xx_psram_restore + ****************************************************************************/ + +void RP23XX_PSRAM_RAMFUNC +rp23xx_psram_restore(void) +{ + if (g_psram_size != 0) + { + rp23xx_psram_apply_format(); + } +} + +#endif /* CONFIG_RP23XX_PSRAM */ diff --git a/arch/arm/src/rp23xx/rp23xx_psram.h b/arch/arm/src/rp23xx/rp23xx_psram.h new file mode 100644 index 00000000000..58d5ce907d2 --- /dev/null +++ b/arch/arm/src/rp23xx/rp23xx_psram.h @@ -0,0 +1,89 @@ +/**************************************************************************** + * arch/arm/src/rp23xx/rp23xx_psram.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RP23XX_RP23XX_PSRAM_H +#define __ARCH_ARM_SRC_RP23XX_RP23XX_PSRAM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The QSPI PSRAM is mapped through QMI chip select 1 at this address */ + +#define RP23XX_PSRAM_BASE 0x11000000 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_psramconfig + * + * Description: + * Detect and initialise the external QSPI PSRAM on QMI chip select 1. + * Assigns the CS1 function to CONFIG_RP23XX_PSRAM_CS1_GPIO, reads the + * device ID to confirm an APS6404-family part is present, switches it to + * quad mode and programs the QMI M1 read/write formats so the region at + * RP23XX_PSRAM_BASE becomes directly addressable (and writable). + * + * Returned Value: + * The size of the detected PSRAM in bytes, or 0 if no PSRAM was found. + * + ****************************************************************************/ + +size_t rp23xx_psramconfig(void); + +/**************************************************************************** + * Name: rp23xx_psram_size + * + * Description: + * Return the size in bytes detected by the last rp23xx_psramconfig(), or 0 + * if PSRAM is absent or has not been configured. + * + ****************************************************************************/ + +size_t rp23xx_psram_size(void); + +/**************************************************************************** + * Name: rp23xx_psram_restore + * + * Description: + * Re-apply the QMI M1 (PSRAM) format and timing registers. Programming + * the flash goes through the bootrom, which reconfigures the shared QMI + * interface for chip select 0; this restores the CS1 configuration + * afterwards so the memory-mapped PSRAM keeps working across a flash + * erase or program. Runs from RAM and does nothing when no PSRAM was + * detected. + * + ****************************************************************************/ + +void rp23xx_psram_restore(void); + +#endif /* __ARCH_ARM_SRC_RP23XX_RP23XX_PSRAM_H */ diff --git a/boards/arm/rp23xx/pimoroni-pico-2-plus/configs/nsh/defconfig b/boards/arm/rp23xx/pimoroni-pico-2-plus/configs/nsh/defconfig index 36d7894cfb3..61b813f3dda 100644 --- a/boards/arm/rp23xx/pimoroni-pico-2-plus/configs/nsh/defconfig +++ b/boards/arm/rp23xx/pimoroni-pico-2-plus/configs/nsh/defconfig @@ -28,12 +28,14 @@ CONFIG_EXAMPLES_HELLO=y CONFIG_FS_PROCFS=y CONFIG_FS_PROCFS_REGISTER=y CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_MM_REGIONS=2 CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 CONFIG_NSH_BUILTIN_APPS=y CONFIG_NSH_READLINE=y CONFIG_RAM_SIZE=532480 CONFIG_RAM_START=0x20000000 CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RP23XX_PSRAM=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_WAITPID=y CONFIG_START_DAY=9