I’m not sure if this is possible to do, but someone may know a solution.
I have a structured array:
struct Plot
{
float lng, lat;
};
struct Plot roundplot[50000];
But this is too big for the internal memory.
So I was hoping to put this array in the PSRAM.
But this needs to be global so I can call a function and others that can access it like this for example:
void my_function()
{
roundplot[roundplotIndex] = {longitude, latitude};
roundplotIndex++;
}
I have seen this;
Hi all! Re-soldered the “ESP32-S2-Saola-1” board and replaced the “S2 wroom” on it with “S2 wrover”. I’ve encountered a problem that changing the “platformio.ini” file doesn’t allow to use 2 mb psram when compiling the project. The compiler sees only 320kb of internal psram (log: “Advanced Memory Usage is available via “PlatformIO Home > Project Inspect”
RAM: [==== ] 41.0% (used 134396 bytes from 327680 bytes)”).
Stack: Visual Studio Code + Platformio;
Framework: Arduino;
Core/module: esp3…
But I can’t get it working.
I’m using v1.0.6 and my “platformio.ini” is…
[env:esp-wrover-kit]
platform = espressif32@3.4.0
board = esp-wrover-kit
framework = arduino
build_flags =
-D_BSD_SOURCE
-DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
upload_speed = 1500000
monitor_speed = 921600
lib_deps =
vshymanskyy/TinyGSM@^0.11.5
knolleary/PubSubClient@^2.8
bblanchon/ArduinoJson@^6.19.4
adafruit/Adafruit GFX Library@^1.11.3
adafruit/Adafruit SSD1306@^2.5.6
I assume I have to change some settings in a config file somewhere?
Any help would be appreciated.
1 Like
Well first of all, is PSRAM generally detected initialized correctly? Run a simple
#include <Arduino.h>
void setup() {
log_d("Total heap: %d", ESP.getHeapSize());
log_d("Free heap: %d", ESP.getFreeHeap());
log_d("Total PSRAM: %d", ESP.getPsramSize());
log_d("Free PSRAM: %d", ESP.getFreePsram());
}
void loop() {}
what does it output?
1 Like
Yes, I have this (I’m using flash FFS too):
FFS available memory: 1378241 bytes
FFS memory used: 9789 bytes
PSRAM size: 4194252 bytes
PSRAM available memory: 4194252 bytes
I get this if I do this in setup():
Plot *roundplot = (Plot *)ps_malloc(128000 * sizeof(Plot));
Serial.printf("PSRAM available memory: %8d bytes\n", ESP.getFreePsram());
PSRAM available memory: 3170236 bytes
So it looks like it’s allocating the psram memory usage.
Great, just change your global variable to be
struct Plot* roundplot;
in which you allocated then and it should be fine.
1 Like
Many thanks @maxgerhardt
I’ve stitched in the code as below to my project and is looking good, it compiles no errors or warnings and runs, the psram memory allocation looks correct too.
#include <Arduino.h>
struct Plot
{
float lng, lat;
};
struct Plot* roundplot;
void setup()
{
Serial.printf("PSRAM size: %8d bytes\n", ESP.getPsramSize());
Serial.printf("PSRAM available memory: %8d bytes\n", ESP.getFreePsram());
roundplot = (Plot *)ps_malloc(128000 * sizeof(Plot));
Serial.printf("PSRAM available memory: %8d bytes\n", ESP.getFreePsram());
}
void loop(){};
1 Like
Attribute to force static allocation in PSRAM is:
EXT_RAM_BSS_ATTR uint8_t Buffer[30000];
In IDF you have to enable a few SDK settings to get this to work. In Arduino the pre-compiled SDK does not have this enabled, you you have to use this:
__ attribute __((section(“.ext_ram.bss”))) uint8_t Buffer[30000]; // remove spaces around underline
Dynamic allocation in PSRAM is achieved by:
uint8_t *Buffer = nullptr;
Buffer = (uint8_t *) heap_caps_malloc(30000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
Alternatively, you can use:
ps_malloc // same as above, just cleaner + checks for PSRAM presence
ps_calloc // same as all above + initializes memory to zero
Verify where it is actually located:
printf(“Address: %p\n”, (void *)Buffer);
Can you name the settings please?
I would like to try this with pioarduino’s hybrid compile feature.
In Espressif32 Arduino a simple malloc > 4096 bytes will allocate from PSRAM automatically if PSRAM is available.
The threshold of 4096 bytes can be changed by calling heap_caps_malloc_extmem_enable(size_t limit);
1 Like
SDK setting is: CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
#define RTC_RODATA_ATTR
#define COREDUMP_RTC_DATA_ATTR
#define RTC_SLOW_ATTR
#define RTC_IRAM_ATTR
#define RTC_FAST_ATTR
#define COREDUMP_RTC_FAST_ATTR
#endif
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
// Forces bss variable into external memory. "
#define EXT_RAM_BSS_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
#else
#define EXT_RAM_BSS_ATTR
#endif
/**
* Deprecated Macro for putting .bss on PSRAM
*/
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
// Forces bss variable into external memory. "
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) _Pragma ("GCC warning \"'EXT_RAM_ATTR' macro is deprecated, please use `EXT_RAM_BSS_ATTR`\"")
You are correct that malloc will automatically decide on the memory location, however sometimes user should be able to decide what to do. In my case I have a static 3kB array that is rarely used and in a non time critical code. I wanted to place it in PSRAM exclusively, so there is more space for fast operations in an integrated RAM.
Thank you for the reply!
I’m utlizing pioarduino’s hybrid compile feature which allows to change SDK config via the platformio.ini. But just changing CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
leads to a crash on my ESP32-S3 DevKit C1 N16R8:
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x400570e8
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x1188
load:0x403c8700,len:0x4
load:0x403c8704,len:0xbf0
load:0x403cb700,len:0x30e4
entry 0x403c88ac
Guru Meditation Error: Core 1 panic'ed (IllegalInstruction). Exception was unhandled.
Memory dump at 0x42006e0c: 08e0e666 03eb8000 89048d80
Core 1 register dump:
PC : 0x42006e11 PS : 0x00060034 A0 : 0x803768b4 A1 : 0x3fcec9e0
A2 : 0x3fceca50 A3 : 0x00000000 A4 : 0x00000004 A5 : 0x3fc96eb0
A6 : 0x00000001 A7 : 0x3fcec9ec A8 : 0x00600000 A9 : 0x3fcec9c0
A10 : 0x00000000 A11 : 0x3fc93cc0 A12 : 0x60020000 A13 : 0x00000002
A14 : 0x7fffffff A15 : 0x00000000 SAR : 0x00000006 EXCCAUSE: 0x00000000
EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0xffffffff
Backtrace: 0x42006e0e:0x3fcec9e0 0x403768b1:0x3fceca30 0x40378034:0x3fceca50 0x42006d7d:0x3fcecb10 0x403768b1:0x3fcecb60 0x40378034:0x3fcecb80 0x3ffffffd:0x3fcecc40 |<-CORRUPTED
[env:esp32s3]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip
board = esp32-s3-devkitc-1
framework = arduino
board_build.arduino.memory_type = qio_opi
board_build.flash_mode = qio
board_build.psram_type = opi
board_upload.flash_size = 16MB
board_upload.maximum_size = 16777216
board_build.extra_flags =
-DBOARD_HAS_PSRAM
custom_sdkconfig =
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
custom_component_remove =
espressif/esp_hosted
espressif/esp_wifi_remote
espressif/esp-dsp
espressif/esp32-camera
espressif/libsodium
espressif/esp-modbus
espressif/qrcode
espressif/esp_insights
espressif/esp_diag_data_store
espressif/esp_diagnostics
espressif/esp_rainmaker
espressif/rmaker_common
monitor_speed = 115200
#include <Arduino.h>
EXT_RAM_BSS_ATTR uint8_t buffer[4*1024*1024];
void setup() {
Serial.begin(115200);
Serial.printf("Free PSRAM: %d\r\n", ESP.getFreePsram());
memset(buffer, 0, 4*1024*1024);
}
void loop() {}
Interesting. There must be something else behind, that causes crash.
I am using those lines of code without any issues on ESP32-S3:
__ attribute__((section(“.ext_ram.bss”))) uint8_t gBuffer[3000];
__ attribute__((section(“.ext_ram.bss”))) uint8_t GIFimage[100000]; // 100 kB, typ image is 50 kB
I’ll crosscheck this against an Arduino as ESP-IDF component project.
I don’t know why, but now it works
Maybe I have forgotten a full clean
in between my tests.
Using pioarduino’s platform-espressif32 with the settings shown in the platformio.ini above and
EXT_RAM_BSS_ATTR uint8_t buffer[4 * 1024 * 1024];
will reduce my available PSRAM by 4 MB as expected.
Nice to know - thanks again @aly-fly !
1 Like