ESP32 Stack configuration (reloaded)

You can also make dynamic stack size, configurable from your program code, by doing as follows

File ./cores/esp32/main.cpp

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_task_wdt.h"
#include "Arduino.h"

#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
  #define CONFIG_ARDUINO_LOOP_STACK_SIZE 8192
#endif

#define USING_DEFAULT_ARDUINO_LOOP_STACK_SIZE      false

#if !(USING_DEFAULT_ARDUINO_LOOP_STACK_SIZE)
//KH
// Have to use in your code as follows
// uint16_t USER_CONFIG_ARDUINO_LOOP_STACK_SIZE = 16384;
#warning Using USER_CONFIG_ARDUINO_LOOP_STACK_SIZE, You have to declare USER_CONFIG_ARDUINO_LOOP_STACK_SIZE in your code
extern uint16_t USER_CONFIG_ARDUINO_LOOP_STACK_SIZE;
//////
#endif

TaskHandle_t loopTaskHandle = NULL;

#if CONFIG_AUTOSTART_ARDUINO

bool loopTaskWDTEnabled;

void loopTask(void *pvParameters)
{
    setup();
    for(;;) {
        if(loopTaskWDTEnabled){
            esp_task_wdt_reset();
        }
        loop();
        if (serialEventRun) serialEventRun();
    }
}

extern "C" void app_main()
{
    loopTaskWDTEnabled = false;
    initArduino();
    
    
    
#if USING_DEFAULT_ARDUINO_LOOP_STACK_SIZE
    // Original
    xTaskCreateUniversal(loopTask, "loopTask", CONFIG_ARDUINO_LOOP_STACK_SIZE, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
#else
    if (USER_CONFIG_ARDUINO_LOOP_STACK_SIZE < 8192)
      USER_CONFIG_ARDUINO_LOOP_STACK_SIZE = 8192;
    else if (USER_CONFIG_ARDUINO_LOOP_STACK_SIZE > 32768)
      USER_CONFIG_ARDUINO_LOOP_STACK_SIZE = 32768;
      
    xTaskCreateUniversal(loopTask, "loopTask", USER_CONFIG_ARDUINO_LOOP_STACK_SIZE, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
#endif    
}

#endif

then in your program code

void * StackPtrAtStart;
void * StackPtrEnd;
UBaseType_t watermarkStart;

#if !(USING_DEFAULT_ARDUINO_LOOP_STACK_SIZE)
  uint16_t USER_CONFIG_ARDUINO_LOOP_STACK_SIZE = 16384;
#endif

void setup()
{
  void* SpStart = NULL;
  StackPtrAtStart = (void *)&SpStart;
  watermarkStart =  uxTaskGetStackHighWaterMark(NULL);
  StackPtrEnd = StackPtrAtStart - watermarkStart;

  Serial.begin(115200);
  delay(2000);

  Serial.printf("\r\n\r\nAddress of Stackpointer near start is:  %p \r\n",  (void *)StackPtrAtStart);
  Serial.printf("End of Stack is near: %p \r\n",  (void *)StackPtrEnd);
  Serial.printf("Free Stack near start is:  %d \r\n",  (uint32_t)StackPtrAtStart - (uint32_t)StackPtrEnd);
}

void loop()
{
  // put your main code here, to run repeatedly:
  void* SpActual = NULL;
  Serial.printf("Free Stack at actual position is: %d \r\n", (uint32_t)&SpActual - (uint32_t)StackPtrEnd);
  delay(60000);
}

By changing USER_CONFIG_ARDUINO_LOOP_STACK_SIZE value, you can change the loop() stack size without the need to modify the ./tools/sdk/esp32/include/config/sdkconfig.h every time you need to change.

This is good for testing many different programs and see which stack size is the best fit for each.

1 Like