Questions regarding stack

rtel wrote on Saturday, March 01, 2008:

[moved from private email]

1. Is the stack for each task derived from the heap defined in the
options header file?

2. Is the RTOS heap (defined in options file) separate from the main
program heap?

3. Is there any easy way to check the amount of RTOS heap remaining?

4. Is there any easy way to check the amount of stack used by each task?

rtel wrote on Saturday, March 01, 2008:

>1. Is the stack for each task derived from the heap defined in the
>options header file?

Yes - the heap defined by configTOTAL_HEAP_SIZE in FreeRTOSConfig.h is used by the kernel to obtain the memory it needs each time it creates a task, semaphore, mutex or queue.  In most cases this is separate from the heap defined in your linker script or project file - other than when heap_3.c is included in your project in which case the heap setup by the linker is used and configTOTAL_HEAP_SIZE has no effect.

See for more information.

>2. Is the RTOS heap (defined in options file) separate from the main
>program heap?

Yes - as above - provided you are not using heap_3.c.

>3. Is there any easy way to check the amount of RTOS heap remaining?

If your application does not dynamically create and delete tasks (or queues, etc) at run time then the amount of heap required is a constant but seeing how much is used depends on the memory scheme being used.  If you step into vTaskStartScheduler() you will see that it creates the idle task before starting the scheduler.  If there is insufficient heap left to create the idle task the call to vTaskStartScheduler() will return, rather than the scheduler actually starting.  You can simply reduce the heap size set by configTOTAL_HEAP_SIZE until this happens, then you know there is too little heap and roughly how much is required. 

Alternatively step into the vTaskCreate() function when the idle task is created - it makes two calls to pvPortMalloc(), one to allocate the TCB and one to allocate the heap.  If you step into pvPortMalloc() you can sometimes see how much heap is left, but as above this depends on the scheme being used.  As a short cut for this:

1) Run up to and break on the call to vTaskStartScheduler().
2) Then put a break point in pvPortMalloc() (in heap_1.c, heap_2.c or heap_3.c).
3) Continue the program execution - you will break on the break point in pvPortMalloc(), the first time this happens continue until you hit the break point again.  The second time you hit the break point you are in the final call to pvPortMalloc() before the scheduler starts so you can inspect the heap structures to see how much space is left.

>4. Is there any easy way to check the amount of stack used by each task?

The stack used by each task is filled with 0xa5 when the task is created.  In the debugger you can inspect the memory pointed to by the stack pointer to see how much is still filled with 0xa5 - this being the stack that has not been used.

Additionally, if you set configUSE_TRACE_FACILITY to 1 in FreeRTOSConfig.h you can then make a call to usTaskCheckFreeStackSpace() but this is a little tricky as you have to pass in a pointer to the task start of the stack.  I’m going to make this easier in the next release, for now you can add the following code to task.c:

unsigned short usTaskGetUnusedStack( void )
____return usTaskCheckFreeStackSpace( pxCurrentTCB->pxStack );

This will return the free stack space in bytes of the calling task.


rtel wrote on Saturday, March 01, 2008:

> Hi Richard,
> I now know my stack usage for each task, if I add up all of the stack
> sizes, how much more memory should I add to this to get a figure for
> the minimum heap size to configure in the options file?

This is not an easy calculation, but goes something like this:

Total heap usage =
(Number of tasks * sizeof( tskTCB ) +
(Number of tasks * stack size allocated to tasks[1]) +
(Number of queues created[2] * sizeof( xQUEUE)) +
(Number of queues created * size of queue storage allocated to each queue[3])

Notes from above equation:

[1] Each task can have a different stack size.
[2] Total number of queues and semaphores and mutexes.
[3] The queue storage area can be different for each queue and is the queue length * the size of the object being queued.


piero74 wrote on Tuesday, March 04, 2008:

Hi Richard. Hi all.

My idea about how write custom functions for stack check, using macros in create functions, is to save pxTopOfStack of each task in global var with requested stack size, when task is created.
After, it could be possible check stack usage or stack free, using current pxTopOfStack  and a simple difference and compare.

Function usTaskCheckFreeStackSpace could be usefull, but i think it’s slow because has to search first fill byte 0xa5.

For heap usage, my idea is to have a GV memory, which contains number of bytes allocated using pvPortMalloc, based on formulas above.

When a task is creted or when a queue is created, this variable will increase, when task or queue are deleted it will decrease.
The value inside will give an idea of heap usage dinamically, but without care about fragmentation (see heap2 schema).
I think will be a usefull information in run time or during debugging, especially when using application dynamically creates and deletes tasks (or queues, etc), i.e. using LWIP tcpip stack.

I will use hooks in create e delete functions to do this, but if you think it could be usefull, this idea could be implemented in future freertos trace functions.