最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - How to access PSRAM - Pimoroni Pico Plus 2 (RP2350) | PlatformIO - Stack Overflow

programmeradmin0浏览0评论

I'm trying to access the PSRAM on a Pimoroni pico plus 2 but im not very skilled in C++.

I'm using platform io.

platformio.ini:

[env:rpipico2]
platform = .git
build_flags = -fexceptions
board = rpipico2
board_build.core = earlephilhower
framework = arduino
lib_deps = 
    SPI

Things I've tried

1 - AndrewCapon's library

This library: , however the board would freeze when I called getInstance.

2 - Using lwmem directly

I was trying to do a simple routine of adding numbers to an array then printing them:

// ChatGPT slop:

#include <Arduino.h>
#include <lwmem/lwmem.h>

//---------------------------------------------------------------------------
// 1) Configure PSRAM region
//    (Addresses/size may differ on your board)
//---------------------------------------------------------------------------
#define PSRAM_LOCATION (0x11000000)  // Common base address on some Pico-like boards
#define PSRAM_SIZE (8 * 1024 * 1024) // Example: 8 MB PSRAM

static lwmem_region_t psram_regions[] = {
    {(void *)PSRAM_LOCATION, PSRAM_SIZE},
    {NULL, 0} // Terminator
};

//---------------------------------------------------------------------------
// 2) Global variables
//---------------------------------------------------------------------------
static int *myArray = nullptr;  // Pointer to array in PSRAM
static size_t arraySize = 10;   // How many elements in our array
static size_t currentIndex = 0; // Tracks where we write next

//---------------------------------------------------------------------------
// 3) Setup
//---------------------------------------------------------------------------
void setup()
{
    Serial.begin(115200);
    while (!Serial)
    {
        // Wait for Serial on some boards
    }
    delay(1000);

    // Let lwmem know it can use our PSRAM region
    lwmem_assignmem(psram_regions);
    Serial.println("Assigned PSRAM region to lwmem.");

    // Use calloc so the array is zero-initialized
    myArray = (int *)lwmem_calloc(arraySize, sizeof(int));
    if (!myArray)
    {
        Serial.println("PSRAM allocation failed!");
        while (true)
        { /* halt */
        }
    }
    Serial.println("Allocated zero-initialized array in PSRAM.");

    // Print initial contents (should all be zero)
    Serial.println("Initial array contents:");
    for (size_t i = 0; i < arraySize; i++)
    {
        Serial.print(myArray[i]);
        if (i < arraySize - 1)
        {
            Serial.print(", ");
        }
    }
    Serial.println();
}

//---------------------------------------------------------------------------
// 4) Loop
//---------------------------------------------------------------------------
void loop()
{
    static unsigned long lastPrint = 0;
    if (millis() - lastPrint >= 5000)
    {
        lastPrint = millis();

        // Store a random value in the array
        int value = random(0, 1000); // Range: [0 .. 999]
        myArray[currentIndex] = value;

        Serial.print("Added ");
        Serial.print(value);
        Serial.print(" at index ");
        Serial.println(currentIndex);

        // Print entire array
        Serial.print("Current array contents: ");
        for (size_t i = 0; i < arraySize; i++)
        {
            Serial.print(myArray[i]);
            if (i < arraySize - 1)
            {
                Serial.print(", ");
            }
        }
        Serial.println();

        // Move to next index, wrap around at the end
        currentIndex = (currentIndex + 1) % arraySize;
    }
}

Output was this so I figure the ram hasnt been mapped?

-initialized array in PSRAM.
Initial array contents:
0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524
Added 933 at index 0
Current array contents: 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524
Added 743 at index 1
Current array contents: 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524

3 - Attempt to map the PSRAM

I asked ChatGPT to configure the PSRAM before running the same demo. It gave the following and when I ran it, I would get the same freezing behaviour as the first attempt.

// main.cpp
#include <Arduino.h>

// ============== Attempt to pull in Pico SDK hardware headers ==============
extern "C" {
#include <lwmem/lwmem.h>
}
#include "pico/stdlib.h"
#include "hardware/structs/ioqspi.h"
#include "hardware/structs/qmi.h"
#include "hardware/structs/xip_ctrl.h"
#include "hardware/sync.h"
#include "hardware/clocks.h"

// ------------- Config for your external PSRAM -------------
#define PIMORONI_PICO_PLUS2_PSRAM_CS_PIN 29
#define PSRAM_BASE_ADDR 0x11000000
#define PSRAM_SIZE_BYTES (8 * 1024 * 1024) // 8 MB example

// ------------- lwmem region for PSRAM -------------
static lwmem_region_t psram_regions[] = {
    { (void*)PSRAM_BASE_ADDR, PSRAM_SIZE_BYTES },
    { NULL, 0 }
};

// ------------- Mark function to (try to) place in ramfunc -------------
#define PSRAM_INIT_FN __attribute__((section(".ramfunc")))

// ------------- Minimal PSRAM init function -------------
PSRAM_INIT_FN bool psram_init_minimal(uint cs_pin) {
    // 1) Setup CS pin for XIP
    gpio_set_function(cs_pin, GPIO_FUNC_XIP_CS1);

    // Disable interrupts
    uint32_t save = save_and_disable_interrupts();

    // Enter direct mode with safe divider
    qmi_hw->direct_csr = (30 << QMI_DIRECT_CSR_CLKDIV_LSB) | QMI_DIRECT_CSR_EN_BITS;
    while (qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) {
        tight_loop_contents();
    }

    // Example: Send "QPI enable" command (0x35)
    qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
    qmi_hw->direct_tx = 0x35;
    // Wait for TX empty
    while (!(qmi_hw->direct_csr & QMI_DIRECT_CSR_TXEMPTY_BITS)) {
        tight_loop_contents();
    }
    // Wait for not busy
    while (qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) {
        tight_loop_contents();
    }
    qmi_hw->direct_csr &= ~QMI_DIRECT_CSR_ASSERT_CS1N_BITS;

    // Setup M1 region
    int clk_sys_hz = clock_get_hz(clk_sys);
    int desired_psram_freq = 133000000;
    int divisor = (clk_sys_hz + desired_psram_freq - 1) / desired_psram_freq;
    if (divisor < 2) {
        divisor = 2;
    }
    int rxdelay = divisor;
    int max_select = 10;
    int min_deselect = 2;

    qmi_hw->m[1].timing =
          (1 << QMI_M1_TIMING_COOLDOWN_LSB)
        | (QMI_M1_TIMING_PAGEBREAK_VALUE_1024 << QMI_M1_TIMING_PAGEBREAK_LSB)
        | (max_select << QMI_M1_TIMING_MAX_SELECT_LSB)
        | (min_deselect << QMI_M1_TIMING_MIN_DESELECT_LSB)
        | (rxdelay << QMI_M1_TIMING_RXDELAY_LSB)
        | (divisor << QMI_M1_TIMING_CLKDIV_LSB);

    // QPI read: 0xEB
    qmi_hw->m[1].rfmt =
          (QMI_M0_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_PREFIX_WIDTH_LSB)
        | (QMI_M0_RFMT_ADDR_WIDTH_VALUE_Q   << QMI_M0_RFMT_ADDR_WIDTH_LSB)
        | (QMI_M0_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_SUFFIX_WIDTH_LSB)
        | (QMI_M0_RFMT_DUMMY_WIDTH_VALUE_Q  << QMI_M0_RFMT_DUMMY_WIDTH_LSB)
        | (QMI_M0_RFMT_DATA_WIDTH_VALUE_Q   << QMI_M0_RFMT_DATA_WIDTH_LSB)
        | (QMI_M0_RFMT_PREFIX_LEN_VALUE_8   << QMI_M0_RFMT_PREFIX_LEN_LSB)
        | (6 << QMI_M0_RFMT_DUMMY_LEN_LSB);
    qmi_hw->m[1].rcmd = 0xEB;

    // QPI write: 0x38
    qmi_hw->m[1].wfmt =
          (QMI_M0_WFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_PREFIX_WIDTH_LSB)
        | (QMI_M0_WFMT_ADDR_WIDTH_VALUE_Q   << QMI_M0_WFMT_ADDR_WIDTH_LSB)
        | (QMI_M0_WFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_SUFFIX_WIDTH_LSB)
        | (QMI_M0_WFMT_DUMMY_WIDTH_VALUE_Q  << QMI_M0_WFMT_DUMMY_WIDTH_LSB)
        | (QMI_M0_WFMT_DATA_WIDTH_VALUE_Q   << QMI_M0_WFMT_DATA_WIDTH_LSB)
        | (QMI_M0_WFMT_PREFIX_LEN_VALUE_8   << QMI_M0_WFMT_PREFIX_LEN_LSB);
    qmi_hw->m[1].wcmd = 0x38;

    // Exit direct mode
    qmi_hw->direct_csr = 0;

    // Enable writes to M1
    hw_set_bits(&xip_ctrl_hw->ctrl, XIP_CTRL_WRITABLE_M1_BITS);

    restore_interrupts(save);
    return true;
}

// ------------- Demo array -------------
static int*    myArray      = nullptr;
static size_t  arraySize    = 10;
static size_t  currentIndex = 0;

// ------------- Setup -------------
void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("Starting Arduino + PSRAM + lwmem demo...");

    // Attempt to init PSRAM
    Serial.println("Initializing external PSRAM...");
    if (!psram_init_minimal(PIMORONI_PICO_PLUS2_PSRAM_CS_PIN)) {
        Serial.println("PSRAM init failed!");
        while (true) { }
    }
    Serial.println("PSRAM init success (hopefully)!");

    // Assign lwmem region
    lwmem_assignmem(psram_regions);
    Serial.println("Assigned lwmem to use PSRAM region.");

    // Allocate array in PSRAM
    myArray = (int*) lwmem_calloc(arraySize, sizeof(int));
    if (!myArray) {
        Serial.println("PSRAM allocation failed!");
        while (true) { }
    }
    Serial.print("Allocated an array of ");
    Serial.print(arraySize);
    Serial.println(" integers in PSRAM.");

    // Print initial contents
    Serial.println("Initial array contents:");
    for (size_t i = 0; i < arraySize; i++) {
        Serial.print(myArray[i]);
        if (i < arraySize - 1) Serial.print(", ");
    }
    Serial.println();
}

// ------------- Loop -------------
void loop() {
    static unsigned long lastPrint = 0;
    if (millis() - lastPrint >= 5000) {
        lastPrint = millis();

        // Store a random value
        int val = random(0, 1000);
        myArray[currentIndex] = val;

        Serial.print("Wrote ");
        Serial.print(val);
        Serial.print(" at index ");
        Serial.println(currentIndex);

        // Print the whole array
        Serial.print("Array: ");
        for (size_t i = 0; i < arraySize; i++) {
            Serial.print(myArray[i]);
            if (i < arraySize - 1) Serial.print(", ");
        }
        Serial.println();

        currentIndex = (currentIndex + 1) % arraySize;
    }
}

ChatGPT suggested that using the Arduino framework is my issue because it interrupts the reading of the code from flash.

Unfortunately this is not my wheelhouse so im really struggling. A minimal working demo similar to the above would be so helpful but I can't find anything online.

I'm trying to access the PSRAM on a Pimoroni pico plus 2 but im not very skilled in C++.

I'm using platform io.

platformio.ini:

[env:rpipico2]
platform = https://github/maxgerhardt/platform-raspberrypi.git
build_flags = -fexceptions
board = rpipico2
board_build.core = earlephilhower
framework = arduino
lib_deps = 
    SPI

Things I've tried

1 - AndrewCapon's library

This library: https://github/AndrewCapon/PicoPlusPsram, however the board would freeze when I called getInstance.

2 - Using lwmem directly

I was trying to do a simple routine of adding numbers to an array then printing them:

// ChatGPT slop:

#include <Arduino.h>
#include <lwmem/lwmem.h>

//---------------------------------------------------------------------------
// 1) Configure PSRAM region
//    (Addresses/size may differ on your board)
//---------------------------------------------------------------------------
#define PSRAM_LOCATION (0x11000000)  // Common base address on some Pico-like boards
#define PSRAM_SIZE (8 * 1024 * 1024) // Example: 8 MB PSRAM

static lwmem_region_t psram_regions[] = {
    {(void *)PSRAM_LOCATION, PSRAM_SIZE},
    {NULL, 0} // Terminator
};

//---------------------------------------------------------------------------
// 2) Global variables
//---------------------------------------------------------------------------
static int *myArray = nullptr;  // Pointer to array in PSRAM
static size_t arraySize = 10;   // How many elements in our array
static size_t currentIndex = 0; // Tracks where we write next

//---------------------------------------------------------------------------
// 3) Setup
//---------------------------------------------------------------------------
void setup()
{
    Serial.begin(115200);
    while (!Serial)
    {
        // Wait for Serial on some boards
    }
    delay(1000);

    // Let lwmem know it can use our PSRAM region
    lwmem_assignmem(psram_regions);
    Serial.println("Assigned PSRAM region to lwmem.");

    // Use calloc so the array is zero-initialized
    myArray = (int *)lwmem_calloc(arraySize, sizeof(int));
    if (!myArray)
    {
        Serial.println("PSRAM allocation failed!");
        while (true)
        { /* halt */
        }
    }
    Serial.println("Allocated zero-initialized array in PSRAM.");

    // Print initial contents (should all be zero)
    Serial.println("Initial array contents:");
    for (size_t i = 0; i < arraySize; i++)
    {
        Serial.print(myArray[i]);
        if (i < arraySize - 1)
        {
            Serial.print(", ");
        }
    }
    Serial.println();
}

//---------------------------------------------------------------------------
// 4) Loop
//---------------------------------------------------------------------------
void loop()
{
    static unsigned long lastPrint = 0;
    if (millis() - lastPrint >= 5000)
    {
        lastPrint = millis();

        // Store a random value in the array
        int value = random(0, 1000); // Range: [0 .. 999]
        myArray[currentIndex] = value;

        Serial.print("Added ");
        Serial.print(value);
        Serial.print(" at index ");
        Serial.println(currentIndex);

        // Print entire array
        Serial.print("Current array contents: ");
        for (size_t i = 0; i < arraySize; i++)
        {
            Serial.print(myArray[i]);
            if (i < arraySize - 1)
            {
                Serial.print(", ");
            }
        }
        Serial.println();

        // Move to next index, wrap around at the end
        currentIndex = (currentIndex + 1) % arraySize;
    }
}

Output was this so I figure the ram hasnt been mapped?

-initialized array in PSRAM.
Initial array contents:
0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524
Added 933 at index 0
Current array contents: 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524
Added 743 at index 1
Current array contents: 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524, 0, -858993524

3 - Attempt to map the PSRAM

I asked ChatGPT to configure the PSRAM before running the same demo. It gave the following and when I ran it, I would get the same freezing behaviour as the first attempt.

// main.cpp
#include <Arduino.h>

// ============== Attempt to pull in Pico SDK hardware headers ==============
extern "C" {
#include <lwmem/lwmem.h>
}
#include "pico/stdlib.h"
#include "hardware/structs/ioqspi.h"
#include "hardware/structs/qmi.h"
#include "hardware/structs/xip_ctrl.h"
#include "hardware/sync.h"
#include "hardware/clocks.h"

// ------------- Config for your external PSRAM -------------
#define PIMORONI_PICO_PLUS2_PSRAM_CS_PIN 29
#define PSRAM_BASE_ADDR 0x11000000
#define PSRAM_SIZE_BYTES (8 * 1024 * 1024) // 8 MB example

// ------------- lwmem region for PSRAM -------------
static lwmem_region_t psram_regions[] = {
    { (void*)PSRAM_BASE_ADDR, PSRAM_SIZE_BYTES },
    { NULL, 0 }
};

// ------------- Mark function to (try to) place in ramfunc -------------
#define PSRAM_INIT_FN __attribute__((section(".ramfunc")))

// ------------- Minimal PSRAM init function -------------
PSRAM_INIT_FN bool psram_init_minimal(uint cs_pin) {
    // 1) Setup CS pin for XIP
    gpio_set_function(cs_pin, GPIO_FUNC_XIP_CS1);

    // Disable interrupts
    uint32_t save = save_and_disable_interrupts();

    // Enter direct mode with safe divider
    qmi_hw->direct_csr = (30 << QMI_DIRECT_CSR_CLKDIV_LSB) | QMI_DIRECT_CSR_EN_BITS;
    while (qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) {
        tight_loop_contents();
    }

    // Example: Send "QPI enable" command (0x35)
    qmi_hw->direct_csr |= QMI_DIRECT_CSR_ASSERT_CS1N_BITS;
    qmi_hw->direct_tx = 0x35;
    // Wait for TX empty
    while (!(qmi_hw->direct_csr & QMI_DIRECT_CSR_TXEMPTY_BITS)) {
        tight_loop_contents();
    }
    // Wait for not busy
    while (qmi_hw->direct_csr & QMI_DIRECT_CSR_BUSY_BITS) {
        tight_loop_contents();
    }
    qmi_hw->direct_csr &= ~QMI_DIRECT_CSR_ASSERT_CS1N_BITS;

    // Setup M1 region
    int clk_sys_hz = clock_get_hz(clk_sys);
    int desired_psram_freq = 133000000;
    int divisor = (clk_sys_hz + desired_psram_freq - 1) / desired_psram_freq;
    if (divisor < 2) {
        divisor = 2;
    }
    int rxdelay = divisor;
    int max_select = 10;
    int min_deselect = 2;

    qmi_hw->m[1].timing =
          (1 << QMI_M1_TIMING_COOLDOWN_LSB)
        | (QMI_M1_TIMING_PAGEBREAK_VALUE_1024 << QMI_M1_TIMING_PAGEBREAK_LSB)
        | (max_select << QMI_M1_TIMING_MAX_SELECT_LSB)
        | (min_deselect << QMI_M1_TIMING_MIN_DESELECT_LSB)
        | (rxdelay << QMI_M1_TIMING_RXDELAY_LSB)
        | (divisor << QMI_M1_TIMING_CLKDIV_LSB);

    // QPI read: 0xEB
    qmi_hw->m[1].rfmt =
          (QMI_M0_RFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_PREFIX_WIDTH_LSB)
        | (QMI_M0_RFMT_ADDR_WIDTH_VALUE_Q   << QMI_M0_RFMT_ADDR_WIDTH_LSB)
        | (QMI_M0_RFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_RFMT_SUFFIX_WIDTH_LSB)
        | (QMI_M0_RFMT_DUMMY_WIDTH_VALUE_Q  << QMI_M0_RFMT_DUMMY_WIDTH_LSB)
        | (QMI_M0_RFMT_DATA_WIDTH_VALUE_Q   << QMI_M0_RFMT_DATA_WIDTH_LSB)
        | (QMI_M0_RFMT_PREFIX_LEN_VALUE_8   << QMI_M0_RFMT_PREFIX_LEN_LSB)
        | (6 << QMI_M0_RFMT_DUMMY_LEN_LSB);
    qmi_hw->m[1].rcmd = 0xEB;

    // QPI write: 0x38
    qmi_hw->m[1].wfmt =
          (QMI_M0_WFMT_PREFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_PREFIX_WIDTH_LSB)
        | (QMI_M0_WFMT_ADDR_WIDTH_VALUE_Q   << QMI_M0_WFMT_ADDR_WIDTH_LSB)
        | (QMI_M0_WFMT_SUFFIX_WIDTH_VALUE_Q << QMI_M0_WFMT_SUFFIX_WIDTH_LSB)
        | (QMI_M0_WFMT_DUMMY_WIDTH_VALUE_Q  << QMI_M0_WFMT_DUMMY_WIDTH_LSB)
        | (QMI_M0_WFMT_DATA_WIDTH_VALUE_Q   << QMI_M0_WFMT_DATA_WIDTH_LSB)
        | (QMI_M0_WFMT_PREFIX_LEN_VALUE_8   << QMI_M0_WFMT_PREFIX_LEN_LSB);
    qmi_hw->m[1].wcmd = 0x38;

    // Exit direct mode
    qmi_hw->direct_csr = 0;

    // Enable writes to M1
    hw_set_bits(&xip_ctrl_hw->ctrl, XIP_CTRL_WRITABLE_M1_BITS);

    restore_interrupts(save);
    return true;
}

// ------------- Demo array -------------
static int*    myArray      = nullptr;
static size_t  arraySize    = 10;
static size_t  currentIndex = 0;

// ------------- Setup -------------
void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("Starting Arduino + PSRAM + lwmem demo...");

    // Attempt to init PSRAM
    Serial.println("Initializing external PSRAM...");
    if (!psram_init_minimal(PIMORONI_PICO_PLUS2_PSRAM_CS_PIN)) {
        Serial.println("PSRAM init failed!");
        while (true) { }
    }
    Serial.println("PSRAM init success (hopefully)!");

    // Assign lwmem region
    lwmem_assignmem(psram_regions);
    Serial.println("Assigned lwmem to use PSRAM region.");

    // Allocate array in PSRAM
    myArray = (int*) lwmem_calloc(arraySize, sizeof(int));
    if (!myArray) {
        Serial.println("PSRAM allocation failed!");
        while (true) { }
    }
    Serial.print("Allocated an array of ");
    Serial.print(arraySize);
    Serial.println(" integers in PSRAM.");

    // Print initial contents
    Serial.println("Initial array contents:");
    for (size_t i = 0; i < arraySize; i++) {
        Serial.print(myArray[i]);
        if (i < arraySize - 1) Serial.print(", ");
    }
    Serial.println();
}

// ------------- Loop -------------
void loop() {
    static unsigned long lastPrint = 0;
    if (millis() - lastPrint >= 5000) {
        lastPrint = millis();

        // Store a random value
        int val = random(0, 1000);
        myArray[currentIndex] = val;

        Serial.print("Wrote ");
        Serial.print(val);
        Serial.print(" at index ");
        Serial.println(currentIndex);

        // Print the whole array
        Serial.print("Array: ");
        for (size_t i = 0; i < arraySize; i++) {
            Serial.print(myArray[i]);
            if (i < arraySize - 1) Serial.print(", ");
        }
        Serial.println();

        currentIndex = (currentIndex + 1) % arraySize;
    }
}

ChatGPT suggested that using the Arduino framework is my issue because it interrupts the reading of the code from flash.

Unfortunately this is not my wheelhouse so im really struggling. A minimal working demo similar to the above would be so helpful but I can't find anything online.

Share Improve this question edited Feb 3 at 9:47 Steve asked Feb 2 at 1:12 SteveSteve 5,0051 gold badge34 silver badges43 bronze badges 1
  • Print the value of myArray[currentIndex] immediately after myArray[currentIndex] = val; instead of waiting for the loop that prints the entire array. If after assigning the value into the array you don't see the value, then start from there, as there would be something very suspicious if after you assign a value, you don't see it assigned. In other words, you could create a more minimal minimal reproducible example (and I am not an arduino programmer). – PaulMcKenzie Commented Feb 2 at 1:56
Add a comment  | 

2 Answers 2

Reset to default 0

The answer was in the config

发布评论

评论列表(0)

  1. 暂无评论