Allocating variables to SRAM or PSRAM.

gkeep01
Posts: 5
Joined: Tue Nov 01, 2022 6:28 am

Allocating variables to SRAM or PSRAM.

Postby gkeep01 » Sun Dec 15, 2024 5:27 am

Hi All,

I hope someone can help me. We are looking to use the ESP32 in a product and this all started becuase we need to send TFT sprites to SRAM however there seems to be a size limit on variables sent to SRAM when you have PSRAM enabled on a wrover. it seems to be around the 4KB mark (45 x 45 pixel of 2 bytes per pixel esprite). I have tried everything to force sprites and even malloc and ps_malloc of variables without any luck. does anyone know of a workaround for forcing more than 4kb into SRAM on a wrover while still accessing PSRAM?

If you have a look at the code below you can see I try and attempt to send a 6 and a 4 KB variable to SRAM as well as PSRAM. When attempting to send 6kb to the SRAM buffer its returning a PSRAM address on the serial monitor. Also only 4KB is seen in the SRAM buffer and 16KB is seen in the PSRAM buffer.

Can someone please help with this.

I have tried using different boards in the board manager :
ESP32 dev module
ESP32 wrover module
ESP32 wrover kit (all versions)

Im using:
arduino IDE version 2.3.3

Code: Untitled.cpp Select all


#include "esp_system.h"
#include "esp_spiram.h" // Include this header for PSRAM functions

long initialFreeSRAM;
long initialFreePSRAM;
long usedSRAM = 0; // Track used SRAM
long usedPSRAM = 0; // Track used PSRAM

int *heap1Var; // Pointer to dynamically allocated memory in heap
int *heap2Var; // Pointer to dynamically allocated memory in heap
int *PSRAM1Var; // Pointer to dynamically allocated memory in PSRAM
int *PSRAM2Var; // Pointer to dynamically allocated memory in PSRAM

void checkPSRAM() {
initialFreePSRAM = ESP.getFreePsram(); // Free PSRAM available
Serial.print("Total PSRAM size: ");
Serial.println(esp_spiram_get_size());
Serial.print("Free PSRAM size: ");
Serial.println(initialFreePSRAM);
}

void checkSRAM() {
initialFreeSRAM = ESP.getFreeHeap();
Serial.print("Free SRAM heap memory: ");
Serial.println(initialFreeSRAM);
Serial.println("");
}

void calculateRAMused() {
// Recalculate based on direct tracking
usedSRAM = initialFreeSRAM - ESP.getFreeHeap();
usedPSRAM = initialFreePSRAM - ESP.getFreePsram();
Serial.println("");
Serial.print("**SRAM allocated = ");
Serial.println(usedSRAM);
Serial.print("**PSRAM allocated = ");
Serial.println(usedPSRAM);
}

void setup() {
Serial.begin(115200);
psramInit();
Serial.println("Before allocation of RAM");
checkPSRAM();
checkSRAM();

// Dynamically allocate 4KB of memory on the heap
heap1Var = (int *)malloc(4096); // Allocate 4KB (4096 bytes) on the heap
if (heap1Var != NULL) {
*heap1Var = 14; // Assign a value to the allocated memory

// Print the memory address of the allocated heap memory
Serial.print("Memory address of heap1Var (Heap): ");
Serial.println((intptr_t)heap1Var, HEX);

// Print the value stored in the heap
Serial.print("heap1Var value: ");
Serial.println(*heap1Var);
} else {
Serial.println("Failed to allocate 4KB of memory on the heap");
}

heap2Var = (int *)malloc(6144); // Allocate 6KB (6144 bytes) on the heap
if (heap2Var != NULL) {
*heap2Var = 16; // Assign a value to the allocated memory

// Print the memory address of the allocated heap memory
Serial.print("Memory address of heap2Var (Heap): ");
Serial.println((intptr_t)heap2Var, HEX);

// Print the value stored in the heap
Serial.print("heap2Var value: ");
Serial.println(*heap2Var);
} else {
Serial.println("Failed to allocate 6KB of memory on the heap");
}

// Dynamically allocate 4KB of memory on PSRAM
PSRAM1Var = (int *)ps_malloc(4096); // Allocate 4KB (4096 bytes) in PSRAM
if (PSRAM1Var != NULL) {
*PSRAM1Var = 24; // Assign a value to the allocated PSRAM memory

// Print the memory address of the allocated PSRAM memory
Serial.print("Memory address of PSRAM1Var (PSRAM): ");
Serial.println((intptr_t)PSRAM1Var, HEX);

// Print the value stored in PSRAM
Serial.print("PSRAM1Var value: ");
Serial.println(*PSRAM1Var);
} else {
Serial.println("Failed to allocate 4KB of memory in PSRAM");
}

PSRAM2Var = (int *)ps_malloc(6144); // Allocate 6KB (6144 bytes) in PSRAM
if (PSRAM2Var != NULL) {
*PSRAM2Var = 26; // Assign a value to the allocated PSRAM memory

// Print the memory address of the allocated PSRAM memory
Serial.print("Memory address of PSRAM2Var (PSRAM): ");
Serial.println((intptr_t)PSRAM2Var, HEX);

// Print the value stored in PSRAM
Serial.print("PSRAM2Var value: ");
Serial.println(*PSRAM2Var);
} else {
Serial.println("Failed to allocate 6KB of memory in PSRAM");
}

// Print free heap memory after allocation
Serial.println("");
Serial.println("After Allocating memory to PSRAM");
calculateRAMused();
checkPSRAM();
checkSRAM();

}

void loop() {
// Nothing to do here
}

Sprite
Espressif staff
Espressif staff
Posts: 10609
Joined: Thu Nov 26, 2015 4:08 am

Re: Allocating variables to SRAM or PSRAM.

Postby Sprite » Sun Dec 15, 2024 5:44 am

malloc() in esp-idf uses a very simple strategy to decide where to allocate memory: if the area is larger than some number (seemingly 4K in the arduino configuration) it goes to psram, otherwise to internal memory. If you want to specifically get RAM from some particular source, you can use heap_caps_malloc with the capabilities you need specified.

gkeep01
Posts: 5
Joined: Tue Nov 01, 2022 6:28 am

Re: Allocating variables to SRAM or PSRAM.

Postby gkeep01 » Mon Dec 16, 2024 12:24 am

Hi ESP_Sprite,

Cool name by the way!

Thank you for your reply I appreciate your time.

I tried what you recommended using heap_caps_malloc to manually allocate memory and maybe im doing something wrong but it keeps acting like its going into SRAM but in fact going into PSRAM once investigated.

Do you know what might be going on here? or what i might be able to do to force this without disabling PSRAM all together.

Code: Select all

#include <TFT_eSPI.h>  // Include the TFT library

TFT_eSPI tft = TFT_eSPI();  // Create TFT object
TFT_eSprite spr1 = TFT_eSprite(&tft);  // Create sprite object

uint8_t *spr1Buffer;  // Pointer for sprite buffer
int spriteXSize = 64;  // Example sprite width
int spriteYSize = 64;  // Example sprite height

long initialFreeSRAM;
long initialFreePSRAM;
long usedSRAM = 0;  // Track used SRAM
long usedPSRAM = 0; // Track used PSRAM

void checkPSRAM() {
  initialFreePSRAM = ESP.getFreePsram();  // Free PSRAM available
  Serial.print("Total PSRAM size: ");
  Serial.println(esp_spiram_get_size());
  Serial.print("Free PSRAM size:  ");
  Serial.println(initialFreePSRAM);
}

void checkSRAM() {
  initialFreeSRAM = ESP.getFreeHeap();
  Serial.print("Free SRAM heap memory: ");
  Serial.println(initialFreeSRAM);
  Serial.println("");
}

void calculateRAMused() {
  // Recalculate based on direct tracking
  usedSRAM = initialFreeSRAM - ESP.getFreeHeap();
  usedPSRAM = initialFreePSRAM - ESP.getFreePsram();
  Serial.println("");
  Serial.print("**SRAM allocated = ");
  Serial.println(usedSRAM);
  Serial.print("**PSRAM allocated = ");
  Serial.println(usedPSRAM);
}


void setup() {
  Serial.begin(115200);
  Serial.println("Starting setup...");
  Serial.println("Before allocation of RAM");
  checkPSRAM();
  checkSRAM();

  tft.begin();  // Initialize the TFT display
  tft.setRotation(3);
  Serial.println("TFT initialized");
  tft.fillScreen(TFT_GREENYELLOW);
  // Allocate sprite buffer in SRAM
  spr1Buffer = (uint8_t*)heap_caps_malloc(spriteXSize * spriteYSize, MALLOC_CAP_INTERNAL);
  if (spr1Buffer == NULL) {
    Serial.println("Failed to allocate sprite buffer in SRAM");
    return;
  }
  Serial.println("Sprite buffer allocated in SRAM");

  // Create sprite with custom buffer (TFT_eSprite will handle the internal buffer)
  spr1.createSprite(spriteXSize, spriteYSize);  // Just create sprite, no custom buffer yet
  Serial.println("Sprite created");

  // Example operation: Fill the sprite with color
  spr1.fillSprite(TFT_RED);
  Serial.println("Sprite filled with red");

  // Push the sprite to the screen
  spr1.pushSprite(10, 10);  // Push the sprite to the screen at position (10, 10)
  Serial.println("Sprite pushed to screen at (10, 10)");
  
  Serial.println("After Allocating memory to PSRAM");
  calculateRAMused();
  checkPSRAM();
  checkSRAM();
  checkSpriteMemory("spr1",spr1);
}

void loop() {
  // Your main loop code
}

void checkSpriteMemory(const char* spriteName, TFT_eSprite& sprite) {
  uint8_t* spriteBuffer = (uint8_t*)sprite.getPointer();
  if (spriteBuffer != nullptr) {
    if (esp_ptr_external_ram(spriteBuffer)) {
      Serial.print(spriteName);
      Serial.println(" is stored in PSRAM...........................***********");
    } else if (esp_ptr_internal(spriteBuffer)) {
      Serial.print(spriteName);
      Serial.println(" is stored in internal SRAM..........................");
    } else {
      Serial.print(spriteName);
      Serial.println(" memory location could not be determined.");
    }
  } else {
    Serial.print(spriteName);
    Serial.println(" buffer is NULL (not allocated).");
  }
}


Serial OUTPUT:

Code: Select all

Before allocation of RAM
Total PSRAM size: 8388608
Free PSRAM size:  4191847
Free SRAM heap memory: 301604

TFT initialized
Sprite buffer allocated in SRAM
Sprite created
Sprite filled with red
Sprite pushed to screen at (10, 10)
After Allocating memory to PSRAM

**SRAM allocated = -872
**PSRAM allocated = 8212
Total PSRAM size: 8388608
Free PSRAM size:  4183635
Free SRAM heap memory: 302476

spr1 is stored in PSRAM...........................***********


lbernstone
Posts: 1132
Joined: Mon Jul 22, 2019 3:20 pm

Re: Allocating variables to SRAM or PSRAM.

Postby lbernstone » Mon Dec 16, 2024 3:07 am

It's very likely that when you call createSprite it is trashing whatever you had allocated, and then starting over (using the default allocator).
You will probably have to customize the Sprite.cpp functions to only call the ps_ allocation functions when the sprite fits in the range you want.

boarchuz
Posts: 656
Joined: Tue Aug 21, 2018 5:28 am

Re: Allocating variables to SRAM or PSRAM.

Postby boarchuz » Mon Dec 16, 2024 5:42 am

You allocate spr1Buffer in internal memory but it's never used. Look into C++'s "placement new".

Who is online

Users browsing this forum: Applebot, Qwantbot and 2 guests