Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8bb30fd
Working PSRAM support
will-v-pi Apr 16, 2026
9c91318
Make auto-detect work
will-v-pi Apr 17, 2026
5f629d9
Delete boot2 method for PSRAM
will-v-pi Apr 20, 2026
2ddafcb
Add kitchen_sink_psram to bazel
will-v-pi Apr 20, 2026
33c8386
Add auto-detection of CS pin too
will-v-pi Apr 20, 2026
b3ce50f
Improve the API and tidy up
will-v-pi Apr 20, 2026
56ee783
More API improvements, add returns, and add multiple kitchen sink bin…
will-v-pi Apr 21, 2026
aaa31a6
Add PICO_TEST_FAILURE_STRING for psram kitchen sink, as it prints ERROR:
will-v-pi Apr 30, 2026
3c9331f
Add pico_override_flash_size function to match pico_override_psram_size
will-v-pi May 1, 2026
c7eab48
Prioritise flash_devinfo over compile definitions
will-v-pi May 1, 2026
c5a4164
Fix bazel build
will-v-pi May 1, 2026
691165a
Add psram_check_address to check if psram variable can be used
will-v-pi May 1, 2026
cc3163d
Add psram_or_malloc and psram_or_free
will-v-pi May 1, 2026
ed1e025
Fix for new bazel checks
will-v-pi May 1, 2026
b584ceb
Use empty PSRAM linker incls on RP2040
will-v-pi May 5, 2026
68a3016
Review fixups
will-v-pi May 6, 2026
bf3510d
Fix config check
will-v-pi May 6, 2026
25bd5b7
Merge remote-tracking branch 'origin/develop' into pico-psram
will-v-pi May 6, 2026
2afd108
Add psram to some adafruit boards
will-v-pi May 6, 2026
a3a6beb
Add psram to defcon32 badge
will-v-pi May 6, 2026
5e19f9b
Merge remote-tracking branch 'origin/develop' into pico-psram
will-v-pi May 6, 2026
1434c71
Review fixups
will-v-pi May 6, 2026
b6f9c9d
Review fixups
will-v-pi May 7, 2026
d670c2c
Reorder sizes in psram_eid_to_size
will-v-pi May 7, 2026
dc8f34a
Review fixups
will-v-pi May 7, 2026
8cfc503
Review fixups
will-v-pi May 8, 2026
b3caac8
Tweak check_board_header.py to also validate the PSRAM settings (#2924)
lurch May 8, 2026
7092268
Minor fixups
will-v-pi May 8, 2026
bac3b5b
Fix low power compilation issue with clang
will-v-pi May 8, 2026
c244bf5
Improve readability of atrans setup
will-v-pi May 8, 2026
78a83b3
Merge branch 'develop' into pico-psram
lurch May 9, 2026
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
12 changes: 0 additions & 12 deletions src/rp2_common/hardware_psram/include/hardware/psram.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,6 @@
#define PICO_AUTO_DETECT_PSRAM_CS_SKIP_DEFAULTS PICO_AUTO_DETECT_PSRAM_CS
#endif

#if PICO_AUTO_DETECT_PSRAM_CS
#if PICO_RP2350
#if PICO_RP2350A
#define PICO_AVAILABLE_CS1_GPIOS {0, 8, 19}
#else
#define PICO_AVAILABLE_CS1_GPIOS {0, 8, 19, 47}
#endif
#else
#error "PICO_AVAILABLE_CS1_GPIOS must be defined for this platform to use PICO_AUTO_DETECT_PSRAM_CS"
#endif
#endif

// PICO_CONFIG: PICO_DEFAULT_PSRAM_ID, Default ID of psram used for auto-detection, type=int, default=0x5D, group=hardware_psram
#ifndef PICO_DEFAULT_PSRAM_ID
#define PICO_DEFAULT_PSRAM_ID 0x5D
Expand Down
53 changes: 32 additions & 21 deletions src/rp2_common/hardware_psram/psram.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,13 @@ size_t psram_detect_cs_and_size(uint8_t *cs_gpios, size_t num) {
for (size_t i=0; i < num; i++) {
uint8_t gpio = cs_gpios[i];
flash_devinfo_set_cs_gpio(1, gpio);
#if PICO_RP2350_A2_SUPPORTED
// Workaround for RP2350-E14, where the bootrom only does this for GPIO 0 instead of the correct CS pin
hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
#endif
gpio_set_function(gpio, GPIO_FUNC_XIP_CS1);
psram_size = psram_detect_size();
if (psram_size > 0) {
// CS GPIO found, so will be left configured in flash_devinfo
Comment thread
lurch marked this conversation as resolved.
break;
}
gpio_set_function(gpio, GPIO_FUNC_NULL);
}
for (size_t i=0; i < num; i++) {
// Restore previous function to all CS GPIOs
Expand Down Expand Up @@ -267,7 +265,7 @@ static void __no_inline_not_in_flash_func(psram_initialise_internal)(void) {
hw_set_bits(&xip_ctrl_hw->ctrl, XIP_CTRL_WRITABLE_M1_BITS);
}

static bool has_psram = false;
static bool psram_initialized = false;

int psram_reinitialise(void) {
// flash_devinfo must be configured correctly to use this function
Expand All @@ -286,17 +284,17 @@ int psram_reinitialise(void) {
// Call flash_start_xip, which calls psram_initialise_internal
flash_start_xip();

has_psram = true;
psram_initialized = true;

return PICO_OK;
}

bool psram_is_available(void) {
return has_psram;
return psram_initialized;
}

size_t psram_get_size(void) {
if (!has_psram) {
if (!psram_initialized) {
return 0;
}
return flash_devinfo_size_to_bytes(flash_devinfo_get_cs_size(1));
Expand All @@ -312,6 +310,18 @@ bool psram_check_address(void* addr) {
}

#if !PICO_RUNTIME_NO_INIT_PSRAM
#if PICO_AUTO_DETECT_PSRAM_CS
#if PICO_RP2350
#if PICO_RP2350A
#define PICO_AVAILABLE_CS1_GPIOS {0, 8, 19}
#else
#define PICO_AVAILABLE_CS1_GPIOS {0, 8, 19, 47}
#endif
#else
#error "PICO_AVAILABLE_CS1_GPIOS must be defined for this platform to use PICO_AUTO_DETECT_PSRAM_CS"
#endif
#endif

void runtime_init_setup_psram(void) {
// Setup flash_devinfo from compile definitions if it is unset
#if defined(PICO_PSRAM_CS_PIN) && !PICO_AUTO_DETECT_PSRAM_CS
Comment thread
will-v-pi marked this conversation as resolved.
Expand Down Expand Up @@ -348,25 +358,26 @@ void runtime_init_setup_psram(void) {
}
#endif

has_psram = flash_devinfo_get_cs_size(1) != FLASH_DEVINFO_SIZE_NONE;
flash_devinfo_size_t psram_flash_devinfo_size = flash_devinfo_get_cs_size(1);
Comment thread
will-v-pi marked this conversation as resolved.

psram_initialized = psram_flash_devinfo_size != FLASH_DEVINFO_SIZE_NONE;

static_assert(FLASH_DEVINFO_SIZE_MAX == FLASH_DEVINFO_SIZE_16M, "expected max region size of 16M");
extern uint32_t __psram_start__;
extern uint32_t __psram_end__;
uint32_t psram_words = (uint32_t)(&__psram_end__ - &__psram_start__);
if (psram_words > (flash_devinfo_size_to_bytes(flash_devinfo_get_cs_size(1)) >> 2)) { // >>2 is /4, for words
if (psram_words > (flash_devinfo_size_to_bytes(psram_flash_devinfo_size) >> 2)) { // >>2 is /4, for words
// Setup to bus fault for variables that don't fit in available PSRAM
flash_devinfo_size_t psram_size = flash_devinfo_get_cs_size(1);
int clear_start = 8; // Clear no regions by default
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I found this code pretty hard to read. Instead of setting a clear_start value and then iterating from clear_start to 7, would it make more sense to have a clear_regions value and then iterate from (8 - clear_regions) to 7? (or similar, if I've got the maths slightly wrong)

if (psram_size == FLASH_DEVINFO_SIZE_NONE) {
if (psram_flash_devinfo_size == FLASH_DEVINFO_SIZE_NONE) {
clear_start = 4; // Clear all PSRAM regions
} else if (psram_size < FLASH_DEVINFO_SIZE_4M) {
} else if (psram_flash_devinfo_size < FLASH_DEVINFO_SIZE_4M) {
clear_start = 5; // Clear last 3x 4M regions
// And reduce size of first PSRAM region
qmi_hw->atrans[4] = (1u << psram_size) << QMI_ATRANS4_SIZE_LSB; // units are 4 kiB
} else if (psram_size == FLASH_DEVINFO_SIZE_4M) {
qmi_hw->atrans[4] = (1u << psram_flash_devinfo_size) << QMI_ATRANS4_SIZE_LSB; // units are 4 kiB
} else if (psram_flash_devinfo_size == FLASH_DEVINFO_SIZE_4M) {
clear_start = 5; // Clear last 3x 4M regions
} else if (psram_size == FLASH_DEVINFO_SIZE_8M) {
} else if (psram_flash_devinfo_size == FLASH_DEVINFO_SIZE_8M) {
clear_start = 6; // Clear last 2x 4M regions
}

Expand All @@ -375,21 +386,21 @@ void runtime_init_setup_psram(void) {
}
}

if (!has_psram) {
if (!psram_initialized) {
return;
}

// Configure the PSRAM parameters with the default values
int ret = psram_configure_params(PICO_DEFAULT_PSRAM_MAX_FREQ, PICO_DEFAULT_PSRAM_MAX_SELECT, PICO_DEFAULT_PSRAM_MIN_DESELECT);
if (ret != PICO_OK) {
has_psram = false;
psram_initialized = false;
return;
}

// Initialise the PSRAM
ret = psram_reinitialise();
if (ret != PICO_OK) {
has_psram = false;
psram_initialized = false;
return;
}

Expand All @@ -399,10 +410,10 @@ void runtime_init_setup_psram(void) {
extern uint32_t __psram_load_end__;
uint32_t stored_words = (uint32_t)(&__psram_load_end__ - &__psram_load_start__);
if (stored_words > 0) {
if (stored_words > (flash_devinfo_size_to_bytes(flash_devinfo_get_cs_size(1)) >> 2)) {
if (stored_words > (flash_devinfo_size_to_bytes(psram_flash_devinfo_size) >> 2)) {
// Only copy into available PSRAM, to avoid triggering bus faults here,
// they will be triggered later when the variable is accessed
stored_words = flash_devinfo_size_to_bytes(flash_devinfo_get_cs_size(1)) >> 2;
stored_words = flash_devinfo_size_to_bytes(psram_flash_devinfo_size) >> 2;
}
memcpy(&__psram_load_start__, &__psram_load_source__, stored_words * sizeof(uint32_t));
}
Expand Down
Loading