Skip to content

rp2/rp2_psram: Switch to upstream hardware_psram.#19416

Open
Gadgetoid wants to merge 2 commits into
micropython:masterfrom
pimoroni:patch-rp2-sdk-psram
Open

rp2/rp2_psram: Switch to upstream hardware_psram.#19416
Gadgetoid wants to merge 2 commits into
micropython:masterfrom
pimoroni:patch-rp2-sdk-psram

Conversation

@Gadgetoid

@Gadgetoid Gadgetoid commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Edit: Sorry this has become something of a stream of consciousness as I feel out how this change should take shape.

⚠️ PSA ⚠️ I feel we ought to go for a full upstream conversion, as presented in: #19418

This PR remains for comment/comparison.

Summary

I petitioned for upstream support for PSRAM in Pico SDK back when we first started the RP2350 bringup, it didn't arrive quickly enough for us to skip a downstream alternative but now it's here and we should switch to it.

Originally asked for raspberrypi/pico-sdk#2372

Fixes #19209

Testing

Tested on a Pico LiPo 2 with 8MB PSRAM. This will probably need verification from other vendors with PSRAM-enabled boards, since we (Pimoroni) use the same boring part on everything we ship so my tests are extremely narrow.

So, uh, gentle nudge to:

  • @gatesphere: ADAFRUIT_FEATHER_RP2350
  • @sfe-SparkFro: SPARKFUN_IOTNODE_LORAWAN_RP2350, SPARKFUN_PROMICRO_RP2350, SPARKFUN_THINGPLUS_RP2350, SPARKFUN_XRP_CONTROLLER
  • @SFE-Brudnerd: SPARKFUN_IOTREDBOARD_RP2350
  • @bikeNomad: WAVESHARE_RP2350B_CORE

Things To Do

Set your PSRAM config upstream:

// --- PSRAM ---
#ifndef PICO_PSRAM_CS_PIN
#define PICO_PSRAM_CS_PIN 19
#endif

pico_board_cmake_set_default(PICO_PSRAM_SIZE_BYTES, (8 * 1024 * 1024))
#ifndef PICO_PSRAM_SIZE_BYTES
#define PICO_PSRAM_SIZE_BYTES (8 * 1024 * 1024)
#endif

A few boards already have an assumed 8MB, I'm not sure of its provenance but downstream (MicroPython) should endeavour to respect this - https://github.com/search?q=repo%3Araspberrypi%2Fpico-sdk+PICO_PSRAM_SIZE_BYTES+path%3A%2F%5Esrc%5C%2Fboards%5C%2Finclude%5C%2Fboards%5C%2F%2F&type=code

Things To Test

  • Board starts up and runs, a good start 😆
  • gc.mem_free() reports the correct gc_heap region (may include SRAM, will exclude a large chunk for GC tracking)
  • machine.freq() changes (within reason) do not push PSRAM timings out of whack or baulk the board
  • flash writes (merely saving a file, or otherwise, since these disable IRQs and more) restore the PSRAM settings upon completion

Trade-offs and Alternatives

As with linker includes we'd be silly not to defer to upstream for this, but as with any deferral it does remove some downstream flexibility. Either way we probably don't want to own grotty code like this if we don't have to.

Right now this change is an attempt at a minimal impact switch over to Pico SDK's hardware_psram, but linking this library includes auto-bringup which we could leverage to more or less remove rp2_psram.c altogether.

We'd need to set PICO_PSRAM_CS_PIN, and either PICO_PSRAM_SIZE_BYTES or PICO_AUTO_DETECT_PSRAM_SIZE. We can also potentially use PICO_AUTO_DETECT_PSRAM but since we already have a CS configured I suggest the best approach would be PICO_PSRAM_CS_PIN + PICO_AUTO_DETECT_PSRAM_SIZE to replicate the current behaviour. Then we could use the SDK's psram_get_size() instead of our psram_init()

For clock changes we'd need:

psram_configure_params(PICO_DEFAULT_PSRAM_MAX_FREQ, PICO_DEFAULT_PSRAM_MAX_SELECT, PICO_DEFAULT_PSRAM_MIN_DESELECT);
psram_reinitialize();

And if psram_reinitialize() fails we'll need to panic, since rugging the PSRAM portion of gc_heap from under the running system is never going to be recoverable.

Generative AI

I used generative AI tools when creating this PR, but a human has checked the
code and is responsible for the code and the description above.

(P.S. if anyone wants to throw their boards my way - or gently remind me I can pilfer one from stock - for verifying stuff like this, it would be helpful!)

Required by the include-based linker script support that follows.

Signed-off-by: Phil Howard <github@gadgetoid.com>
@Gadgetoid Gadgetoid force-pushed the patch-rp2-sdk-psram branch from d683081 to 1e32081 Compare July 3, 2026 16:55
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.51%. Comparing base (964803a) to head (3e3aca9).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #19416   +/-   ##
=======================================
  Coverage   98.51%   98.51%           
=======================================
  Files         177      177           
  Lines       22927    22927           
=======================================
  Hits        22586    22586           
  Misses        341      341           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Pico SDK 2.3.0 adds a hardware_psram library that covers what the port's
rp2_psram.c did by hand: detecting the chip, computing QMI timing for the
current clock, and enabling QPI. Replace the downstream implementation
with a thin psram_init() wrapper over psram_detect_size(),
psram_configure_params() and psram_reinitialize(), keeping the existing
call sites unchanged.

The SDK detection also handles ISSI parts (8/16 MiB), which the previous
code did not. Link hardware_psram on RP2350 only, and disable its
runtime_init auto-setup (PICO_RUNTIME_NO_INIT_PSRAM) since the port
initialises PSRAM itself.

Signed-off-by: Phil Howard <github@gadgetoid.com>
@Gadgetoid Gadgetoid force-pushed the patch-rp2-sdk-psram branch from 1e32081 to 3e3aca9 Compare July 3, 2026 17:03
@Gadgetoid

Gadgetoid commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Note: Without the change to disable the SDK's own bringup, and without using the SDK's include-based linker scripts (which define these symbols) a straight bringup will fail to link with:

hardware_psram/psram.c.o: in function `runtime_init_setup_psram':
hardware_psram/psram.c:442:(.text.runtime_init_setup_psram+0xb4): undefined reference to `__psram_start__'
hardware_psram/psram.c:442:(.text.runtime_init_setup_psram+0xb8): undefined reference to `__psram_end__'
hardware_psram/psram.c:442:(.text.runtime_init_setup_psram+0xc4): undefined reference to `__psram_load_start__'
hardware_psram/psram.c:442:(.text.runtime_init_setup_psram+0xc8): undefined reference to `__psram_load_end__'
hardware_psram/psram.c:442:(.text.runtime_init_setup_psram+0xcc): undefined reference to `__psram_load_source__'

Just linking hardware_psram will trigger the automatic bringup (maybe we want this, and ought to use the linker symbols when adding heap) and PICO_RUNTIME_NO_INIT_PSRAM=1 suppresses this.

Edit: I'm going to prep a counterpart to this PR which rebases on top of the linker migrations and removes rp2_psram.c altogether in favour of SDK bringup and SDK functions. Functionally the two approaches should be very, very similar but the SDK approach avoids us having to handle a redundant layer of indirection.

Irrespective of upstream board config settings, I think we still want a MICROPY_HW_ENABLE_PSRAM downstream opt-in, which will:

  • Check for an upstream configured size/chip-select, use that if found
  • Check for a downstream configured chip-select and do an auto-detect

If and when upstream (board headers) is fully consistent with downstream then perhaps MICROPY_HW_ENABLE_PSRAM becomes redundant and we simply defer to the Pico SDK board headers? Unsure.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Code size report:

Reference:  nrf: Restore interrupt-based I2C with nrfx v3. [964803a]
Comparison: rp2: Use the SDK hardware_psram library for PSRAM bring-up. [merge of 3e3aca9]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
      esp32:    +0 +0.000% ESP32_GENERIC
     mimxrt:    +0 +0.000% TEENSY40
        rp2:  -764 -0.080% RPI_PICO_W[incl -424(bss)]
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rp2: Upstream PSRAM support in Pico SDK

1 participant