Loading...
Searching...
No Matches
hardware_psram

Low level PSRAM setup functions. More...

Macros

#define psram_or_malloc(group, type, var, size)
 Provide a static PSRAM allocation, or malloc if PSRAM is not available.
#define psram_or_free(var)
 Free a buffer if it is not in PSRAM.

Functions

bool psram_is_available (void)
 Check if PSRAM is available and initialized.
size_t psram_get_size (void)
 Get the size of the PSRAM.
bool psram_check_address (void *addr)
 Check if an address is in available PSRAM.
size_t psram_detect_size (void)
 Detect PSRAM size.
size_t psram_detect_cs_and_size (uint8_t *cs_gpios, size_t num)
 Detect PSRAM chip select pin and size.
int psram_configure_params (uint32_t max_psram_freq, uint32_t max_select_ns, uint32_t min_deselect_ns)
 Configure PSRAM timing parameters.
int psram_set_params (uint32_t divisor, uint32_t rxdelay, uint32_t max_select, uint32_t min_deselect)
 Explicitly set PSRAM timing parameters.
int psram_reinitialize (void)
 Re-initialize PSRAM.
size_t psram_eid_to_size (uint8_t kgd, uint8_t eid)
 Convert PSRAM EID to size.

Detailed Description

Low level PSRAM setup functions.

When using the runtime_init initialization, this can initialize PSRAM in 3 ways, listed from highest to lowest priority:

  1. If flash_devinfo is setup (e.g. configured in OTP), it will initialize PSRAM with the flash_devinfo size and GPIO for CS1
  2. If PICO_AUTO_DETECT_PSRAM is set it will attempt to detect PSRAM size and CS GPIO on CS1. This will attempt to use all available QMI CS1n GPIOs as chip selects, so they will be wiggled. By default, it will skip over some which are defined in the board header (see PICO_AUTO_DETECT_PSRAM_CS_SKIP_DEFAULTS).
    • If the CS GPIO is known and set in PICO_PSRAM_CS_PIN, you can just enable PICO_AUTO_DETECT_PSRAM_SIZE to only detect the size. Some board headers use this behavior if they have variants both with and without PSRAM fitted (e.g. adafruit_feather_rp2350)
  3. If PICO_PSRAM_SIZE_BYTES and PICO_PSRAM_CS_PIN are set (e.g. configured in the board header, or with pico_override_psram_size) it will initialize PSRAM with that size and CS GPIO

Only the PICO_AUTO_DETECT_PSRAM methods (including PICO_AUTO_DETECT_PSRAM_SIZE) will verify that PSRAM is present before using it.

Variables can be placed in PSRAM using __in_psram or __uninitialized_psram macros, and you can also read/write the memory addresses directly.

If there are variables placed in PSRAM, XIP will be set up to cause bus faults on any access to PSRAM addresses greater than the size available. The psram_check_address function should be used before accessing variables in PSRAM when auto-detection is on, to prevent these bus faults.

Note some of these functions are unsafe if you are using both cores, and the other is executing from flash or psram concurrently with the operation. In this case, you must perform your own synchronization to make sure that no XIP accesses take place while running these functions. One option is to use the flash_safe_execute functions in pico_flash.

Likewise they are unsafe if you have interrupt handlers or an interrupt vector table in flash or psram, so you must disable interrupts before calling in this case - flash_safe_execute handles this case too.

The unsafe functions are:

Macro Definition Documentation

◆ psram_or_free

#define psram_or_free ( var)
Value:
if (!psram_check_address(var##_psram)) { free(var); }
bool psram_check_address(void *addr)
Check if an address is in available PSRAM.
Definition psram.c:322

Free a buffer if it is not in PSRAM.

This will free the buffer from psram_or_malloc if it was created by malloc

◆ psram_or_malloc

#define psram_or_malloc ( group,
type,
var,
size )
Value:
static type __uninitialized_psram(group) var##_psram[size]; static type* var; \
if (!var) { \
if (psram_check_address(var##_psram + (size))) { \
var = (type*)var##_psram; \
} else { \
var = (type*)malloc((size) * sizeof(type)); \
} \
}
#define __uninitialized_psram(group)
Section attribute macro for placement in uninitialised PSRAM.
Definition sections.h:139

Provide a static PSRAM allocation, or malloc if PSRAM is not available.

This will allocate a static buffer in PSRAM and if available use that, otherwise it will use the heap.

This will fail to compile if PICO_PSRAM_SIZE_BYTES is not set

Function Documentation

◆ psram_check_address()

bool psram_check_address ( void * addr)

Check if an address is in available PSRAM.

Returns
true if the address is in available PSRAM, false otherwise

◆ psram_configure_params()

int psram_configure_params ( uint32_t max_psram_freq,
uint32_t max_select_ns,
uint32_t min_deselect_ns )

Configure PSRAM timing parameters.

This will calculate and set the PSRAM timing parameters based on the given values.

Note: This will also implement the workaround for RP2350-E14 if PICO_RP2350_A2_SUPPORTED is set.

Parameters
max_psram_freqMaximum frequency of PSRAM
max_select_nsMaximum select time in ns
min_deselect_nsMinimum deselect time in ns
Returns
PICO_OK on success, PICO_ERROR_INVALID_ARG if unable to calculate valid parameters

◆ psram_detect_cs_and_size()

size_t psram_detect_cs_and_size ( uint8_t * cs_gpios,
size_t num )

Detect PSRAM chip select pin and size.

This runs psram_detect_size() for each CS GPIO in the array in turn, and returns the size as soon as a PSRAM chip is detected.

This will setup the CS GPIO using flash_devinfo if PSRAM is found.

Parameters
cs_gpiosArray of CS GPIOs to try
numNumber of CS GPIOs in the array
Returns
size of PSRAM, or 0 if none found

◆ psram_detect_size()

size_t psram_detect_size ( void )

Detect PSRAM size.

This will read the ID of the PSRAM chip and return the size based on the ID.

You must configure the GPIO function for the CS pin before calling this function, and should also configure the CS GPIO in flash_devinfo to prevent toggling of the previously configured GPIO (usually 0, so prints invalid characters to default UART).

Returns
size of PSRAM, or 0 if none found

◆ psram_eid_to_size()

size_t psram_eid_to_size ( uint8_t kgd,
uint8_t eid )

Convert PSRAM EID to size.

This will convert the PSRAM EID to the size in bytes.

This is not intended to be called by the user, but is provided as a weak function so it can be overridden if other PSRAM chips are used that have different EID to size mapping.

This is used by psram_detect_size to check the KGD and convert the EID to the size.

Parameters
kgdKnown Good Die
eidEID
Returns
size of PSRAM in bytes, or 0 if the KGD/EID is not recognised

◆ psram_get_size()

size_t psram_get_size ( void )

Get the size of the PSRAM.

Retrieve the size of the PSRAM, either from PICO_PSRAM_SIZE_BYTES, flash_devinfo, or auto-detection.

Returns
size of PSRAM in bytes, or 0 if none

◆ psram_is_available()

bool psram_is_available ( void )

Check if PSRAM is available and initialized.

Returns
true if PSRAM is available and initialized, false otherwise

◆ psram_reinitialize()

int psram_reinitialize ( void )

Re-initialize PSRAM.

This will re-initialize the PSRAM with the parameters set by psram_configure_params.

This calls flash_start_xip internally, so will reset any QSPI pads changes you have made.

Returns
PICO_OK on success, PICO_ERROR_PRECONDITION_NOT_MET if the PSRAM size is not set in flash_devinfo or the PSRAM parameters are not set by psram_configure_params or psram_set_params

◆ psram_set_params()

int psram_set_params ( uint32_t divisor,
uint32_t rxdelay,
uint32_t max_select,
uint32_t min_deselect )

Explicitly set PSRAM timing parameters.

This will explicitly set the PSRAM timing parameters to the given values.

This may be necessary if the parameters calculated by psram_configure_params are not suitable.

Parameters
divisorDivisor for PSRAM clock
rxdelayRX delay for PSRAM clock
max_selectMaximum select time in multiples of 64 system clocks
min_deselectMinimum deselect time in system clock cycles - ceil(divisor / 2)
Returns
PICO_OK on success, PICO_ERROR_INVALID_ARG if any of the parameters are invalid