We can dynamically allocate memory with malloc() or use the dedicated ESP32 specific functions. In general we need to use byte aligned allocations (MALLOC_CAP_8BIT).

When we have used up all available memory space, we still have 4 byte aligned memory available that we can use to store arrays of int32_t data. Unfortunately we can not use this to store floats. Here is the info from the documentation:

Please note that on ESP32 series chips, MALLOC_CAP_32BIT cannot be used for storing floating-point variables. This is because MALLOC_CAP_32BIT may return instruction RAM, and the floating-point assembly instructions on ESP32 cannot access instruction RAM

The following code leads to a runtime exception:

float *data = nullptr;
const int count = 1000;

void setup() {
  data = (float*) heap_caps_malloc(count*sizeof(float), MALLOC_CAP_32BIT);
  assert(data!=nullptr);
}

void loop() {
  for (int j=0;j<count;j++){
    data[j]=0.1+j; // assign float value
    println(data[j]);
  }
}

But we can cheat and internally store the 4 float bytes as uint32_t and still provide floating point operations: C++ is cool and can help us to hide this complexity, so I created the float32 class that does exactly this.

The following sketch will work without any problems:

float32 *data = nullptr;
const int count = 1000;

void setup() {
  data = (float32*) heap_caps_malloc(count*sizeof(float), MALLOC_CAP_32BIT);
  assert(data!=nullptr);
}

void loop() {
  for (int j=0;j<count;j++){
    data[j]=0.1+j;
    println(data[j]);
  }
}

With the help of this hack we can use the full available memory of the ESP32 and not only the memory which is byte aligned!


1 Comment

stuart · 11. April 2023 at 13:28

Great hack, thanks

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *