Lately I am having a lot of trouble with C++ and understanding static functions. I think I found a really elegant way to mix both concenpts: FreeRTOS and dinamic memory with OOP.
I was inspired by this CPP code that do that pretty nice.
Here is my code:
/*
This file contains the code for executing on the incoming commands from MC
*/
#include <Arduino.h>
#include <executor/Executor.h>
#include "sbcPacket/sbcPacket.h"
/* Constructor Set parameters*/
Executor::Executor(LoadSwitch* loadSwitches, Delayer* delayer){
    this->loadSwitches = loadSwitches;
    this->delayer = delayer;
    // Create FreeRTOS semaphore and task
    _asq_sem = xSemaphoreCreateBinary();
    _runSequenceTask = xTaskCreate(
        Executor::runSequenceHandlerTask,
        "runSequenceHandlerTask",
        500,
        this,
        2,
        &runSequencetaskHandle
    );
    configASSERT(_runSequenceTask);
}
void Executor::RunCommand(const uint8_t *buffer, size_t length) {
    ...
}
void Executor::runSequence(){
    while (true) {
        if (xSemaphoreTake(_asq_sem, portMAX_DELAY) == pdTRUE) {
            for (int i = 0; i < _sequenceLength; i++) {
                ...
                RunCommand(command, size);
            }
        }
    }
}
void Executor::runSequenceHandlerTask(void* instance){
    auto* app = static_cast<Executor*>(instance);
    app->runSequence();
}
void Executor::startSequence(){
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(_asq_sem, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 
}
#ifndef EXECUTOR_H
#define EXECUTOR_H
#include <STM32FreeRTOS.h>
#include "bControllable/bControllable.h"
#include "loadSwitch/loadSwitch.h"
#include "delayer/delayer.h"
#define SEQ_MAX_LENGTH 50
class Executor {
    LoadSwitch* loadSwitches;
    Delayer* delayer;
    public:
        Executor(LoadSwitch* LoadSwitches, Delayer* delayer);
        void RunCommand(const uint8_t *buffer, size_t length); // probably there will be more overloaded versions of RunCommand
        
        void buildSequence(const uint8_t *buffer, size_t bufferLength);   // For building the autosequence
        void startSequence();                                             // Start the saved autosequence
        void runSequence();
    private:
        // List of the dynamic arrays that are used to contain the autosequence
        int _asqControllablesArray[SEQ_MAX_LENGTH] = {0};
        int _asqValueArray[SEQ_MAX_LENGTH] = {0};
        int _sequenceLength = 0;
        static void runSequenceHandlerTask(void* instance);
        SemaphoreHandle_t _asq_sem;      // Semaphore used for executing the autosequence
        portBASE_TYPE _runSequenceTask;
        TaskHandle_t runSequencetaskHandle;
};
#endif /* EXECUTOR_H */
If you dont want to analize the code. Basically is that you are passing the object (this) as a parameter to FreeRTOS, and then to run the functions. So the HandlerTask is static, but accessign dynamic objects. For doing this is necessary to use a TaskHandle_t.