0

I have an ESP32 microcontroller with 64Mb PSRAM onboard. How can i move into PSRAM a multidimensional array I have on my code , too big to fit into the ESP32 RAM?

Miguel Tomás
  • 1,714
  • 1
  • 13
  • 23

1 Answers1

0

Let's assume I need a 3D multidimensional array of char string, piBuffer , with dimensions 10x10x10 and I need to store it in the SPI PSRAM IC and not on the MCU's internal RAM

char ****piBuffer = NULL; //pointer to pointer
int nRow = 10; //variable store size of 1st dimension
int nColumn = 10; //variable store size of 2nd dimension
int dim3 = 10; // variable store size of 3rd dimension

int iRow = 0; //Variable for looping 1st dimension, "row"
int iCol = 0; //Variable for looping 2nd dimension "column"
int i3D = 0;  //Variable for looping 3rd dimension 

First one needs to allocate memory for the 1st dimension, "rows":

piBuffer = (char ****)heap_caps_malloc(nRow * sizeof(char***), MALLOC_CAP_SPIRAM);
//Check memory validity
if(piBuffer == NULL){
   Serial.println("FAIL");
}

Next, one needs to allocate memory for the 2nd dimension, "columns":

for (iRow =0 ; iRow < nRow ; iRow++){
    piBuffer[iRow] = (char ***)heap_caps_malloc(nColumn * sizeof(char**), MALLOC_CAP_SPIRAM);
    //Check memory validity
    if(piBuffer[iRow] == NULL){
     // freeAllocatedMemory(piBuffer,iRow);
      Serial.println("FAIL");
    }
}

Next, one need to allocate memory for the 3rd dimension, "dim3":

for (iRow =0 ; iRow < nRow ; iRow++){
  for (iCol =0 ; iCol < nColumn ; iCol++){
    piBuffer[iRow][iCol] = (char **)heap_caps_malloc(dim3 * sizeof(char*), MALLOC_CAP_SPIRAM);
    //Check memory validity
    if(piBuffer[iRow] == NULL){
      //freeAllocatedMemory(piBuffer,iRow);
      Serial.println("FAIL");
    }
  }
}

Finally, one need to allocate memory for the char string size it self. On the piece of code below char strings are initialized with a 20 char string size:

for (iRow =0 ; iRow < nRow ; iRow++) {
    for (iCol =0 ; iCol < nColumn ; iCol++){
      for (i3D =0 ; i3D < dim3 ; i3D++){
        piBuffer[iRow][iCol][i3D] =  (char *)heap_caps_malloc(20 * sizeof(char), MALLOC_CAP_SPIRAM);
      }
    }
}

The code above was only to initialize the multidimensional 3D array of char strings. To use it and assign (set) char string values to it one can do it like so:

for (iRow =0 ; iRow < nRow ; iRow++) {
    for (iCol =0 ; iCol < nColumn ; iCol++){
      for (i3D =0 ; i3D < dim3 ; i3D++){
        String("MTasdfsa").toCharArray(piBuffer[iRow][iCol][i3D], String("MTasdfsa").length()+1);
      }
    }
}

To get , output or print values stored into the multidimensional array on can do it like the next piece of code:

for (iRow =0 ; iRow < nRow ; iRow++) {
  for (iCol =0 ; iCol < nColumn ; iCol++) {
    for (i3D =0 ; i3D < dim3 ; i3D++){
      Serial.println("piBuffer["+String(iRow)+"]["+String(iCol)+"]["+String(i3D)+"] = " +String(piBuffer[iRow][iCol][i3D]));
    }
  }
}

At the end, is required to free the memory block reserved for the multidimensional array. This can be done using a function, freeAllocatedMemory, defined as follows:

//Free Allocated memory
void freeAllocatedMemory(int ***piBuffer, int nRow, int nColumn, int dim3){
    int iRow = 0;
    int iCol=0;
    int i3D=0; 
    
    for (iRow =0; iRow < nRow; iRow++){
      for (iCol =0 ; iCol < nColumn ; iCol++){
        for (i3D =0 ; i3D < dim3 ; i3D++){
          free(piBuffer[iRow][iCol][i3D]); // free allocated memory
        }
        free(piBuffer[iRow][iCol]); // free allocated memory                       
      }
      free(piBuffer[iRow]); // free allocated memory    
    }
    free(piBuffer);
}

One final note

this multidimensional array can be initialized differently, as a 1D array and keep track of memory block positions for the corresponding rows, columns and 3rd dimens. To do it one can use the next math. formula

iRow x nCol +icol + nRow x nCol x i3D

to get or set char string values into the multidimensional array.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Miguel Tomás
  • 1,714
  • 1
  • 13
  • 23