Is there a way to free RAM from ESP32?

I'm trying to write an application for ESP32 (16 MB flash, no PSRAM) that needs basically three things:

  • read/write from/to an SD card
  • decode MP3
  • send audio samples over BT A2DP

The minimal code is very simple:

#include <Arduino.h>
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <freertos/ringbuf.h>

#include "AudioTools.h"
#include "BluetoothA2DPSource.h"
#include "Audio.h"

#define PIN_SPI_SCK 27
#define PIN_SPI_MISO 26
#define PIN_SPI_MOSI 2
#define PIN_SD_CS 22

#define PIN_I2S_BCLK 17
#define PIN_I2S_LRC 18
#define PIN_I2S_DOUT 19

SET_LOOP_TASK_STACK_SIZE(4096);

Audio audio;
BluetoothA2DPSource a2dp_source;
RingbufHandle_t audioRingBuffer = xRingbufferCreate(2048, RINGBUF_TYPE_BYTEBUF);

void audio_process_i2s(int16_t* outBuff, uint16_t validSamples, uint8_t bitsPerSample, uint8_t channels, bool *continueI2S)
{
  // process samples
  *continueI2S = false;
}

int32_t get_data_channels(Frame *frame, int32_t channel_len)
{
  // process samples
  return channel_len;
}

void setup()
{
  Serial.begin(115200);
  SPI.setFrequency(1000000);
  SPI.begin(PIN_SPI_SCK, PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SD_CS);
  if (SD.begin(PIN_SD_CS)) Serial.println("SD card mounted!");
  else Serial.println("Failed to mount SD card");

  a2dp_source.start("BT speaker", get_data_channels);

  File root = SD.open("/");
  audio.setPinout(PIN_I2S_BCLK, PIN_I2S_LRC, PIN_I2S_DOUT);
  audio.setVolume(2);
  audio.connecttoFS(SD, "sample.mp3");
}

void loop()
{
  static unsigned long refTime = 0;
  if (millis() > refTime + 1000)
  {
    Serial.printf("%lu\t%lu\t%lu\t%lu\n", ESP.getHeapSize(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getMaxAllocHeap());
    refTime = millis();
  }

  audio.loop();
}

at compile time I get:

RAM:   [=         ]  11.5% (used 59880 bytes from 521984 bytes)
Flash: [======    ]  63.9% (used 2009777 bytes from 3145728 bytes)

and at run-time:

234336  17620   12844   11252

where:

  • ESP.getHeapSize(): 234336
  • ESP.getFreeHeap(): 17620
  • ESP.getMinFreeHeap(): 12844
  • ESP.getMaxAllocHeap(): 11252

still the mp3 decoder cannot be created:

info        PSRAM not found, inputBufferSize: 13951 bytes
[   789][V][ssl_client.cpp:321] stop_ssl_socket(): Cleaning SSL connection.
info        buffers freed, free Heap: 20300 bytes
info        Reading file: "/sample.mp3"
[   826][E][mp3_decoder.cpp:1602] MP3Decoder_AllocateBuffers(): not enough memory to allocate mp3decoder buffers
info        Closing audio file "sample.mp3"

Since I don't need to use WiFi, BLE, SSL, etc... is there a way to disable them in order to free more memory?

I'm aware the PSRAM would probably fix the issue, but we have a lot of these ESP32-WROOMs (w/o PSRAM) and I'm trying to use them is possibile.

Which partition scheme have you got selected in the IDE ?

Sorry, I didn't write it because I thought it related to flash only, not RAM!
I'm using the "huge_app" scheme:

board_build.partitions = huge_app.csv

I see something that makes no sense, the info message says 20300 free Heap but you only requested 13951. Looking back at the ESP.get calls something is using around 217,000 bytes leaving 17,620 but only 11,252 really available due to fragmentation. I would look for some heap utilities to discover what is using the roughly 217,000 bytes of heap.

I'm not sure if I understood your comment correctly.
The 13951 bytes requested are for the audio buffer only. But I bet all the other stuff (FS, BT, etc...) will use some resources, won't they?

Do you recommend any "heap utility"? The one I found (memviz) requires a debugging session and I cannot start it on ESP32, that hasn't a true USB/JTAG connection.

No idea re FS,BT,etc. The only heap analyzer I know of is for AVR not esp32. Have you searched github for esp heap libraries?

I searched in VSCode extensions. I'm going to do a search on github as well.

I have never heard of VSCode extensions. AFAIK all libraries are either in the library manager and/or github, no where else to my knowledge.