One of the parameters for xTaskCreate() defines the task's stack size. But where does the RAM being used for this stack come from? There are two options – dynamically allocated memory and statically allocated memory.
Dynamic memory allocation is implemented with a heap. FreeRTOS ports contain several different options regarding how heaps are implemented. Chapter 15, FreeRTOS Memory Management, provides details on how to select an appropriate heap implementation for a given project. For now, it is sufficient to assume a heap is available.
Static allocation permanently reserves RAM for a variable for the life of the program. Let's see what each approach looks like.