A stack is used for function-scoped storage. Each time a function is called, information for that function (like its parameters and local variables) are placed onto a stack. When the function exits, all of the information that was placed onto the stack is removed (this is why passing pointers to local variables is a problem). In FreeRTOS, each task has its own private stack whose size is determined when the task is created.
Since stacks have such an orderly way of being accessed, it isn't possible for them to become fragmented, like a heap. It is possible, however, to overflow the stack by placing more information onto it than its size allows.
Initialization of the stack and heap takes place in Chapter_*startupstartup_stm32f767xx.s. The exact size of the main stack is defined in the linker script STM32F767ZI_FLASH.ld. If necessary, the size of the stack and heap available to the system before the FreeRTOS scheduler is started can be adjusted by modifying _Min_Heap_Size or _Min_Stack_Size:
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
It is best to try and keep these both to minimal sizes since any RAM used here will be unavailable to the tasks. These stacks/heaps are only for code that is run before the scheduler is started, as well as the ISRs. This is not the same stack that is used by any of the tasks.
The FreeRTOS kernel manipulates the process stack pointer (PSP) to point to the task stack that has context (is in the running state).
The most important thing to keep in mind with stacks is that they must be adequately sized to hold all of the local variables that a task will execute for the deepest call level. We'll discuss ways of getting a handle on this in the Keeping an eye on stack space section.