When using the FreeRTOS Task List in the Eclipse based MCUXpresso IDE, it shows the list of tasks with their stack size used. But with the default FreeRTOS settings it is not able to determine the correct stack size and shows a warning icon:
The warning should tell me that the information shown about the stack size is wrong: I did create the App Task with 110 stack units (each 4 bytes) so it should show 440 bytes, but it shows only 308 bytes.
Why is that? The reason is that the debugger (or FreeRTOS Kernel Awareness in Eclipse) does not know the total size of the memory allocated for the task.
On ARM Cortex the stack is growing from the higher to the lower addresses, as shown in the image below:
What FreeRTOS stores in its TCB (Task Control Block, the descriptor of the task) is the pxTopOfStack (current task stack pointer, ‘Stack Top‘ in the Kernel Awareness view) and pxStack (the end of the stack, ‘Stack Base‘ in the Kernel Awareness view). The beginning of the task stack is not stored in the TCB as not necessary for the Kernel.
The ‘Stack High Water Mark’ is something very useful: FreeRTOS fills the stack space at task creation time with a 0x5a byte pattern. The debugger or the RTOS can find out that way the ‘high water mark’ for each task.
The solution is to add the following macro to the FreeRTOSConfig.h file:
#define configRECORD_STACK_HIGH_ADDRESS (1)
With this turned on, FreeRTOS stores an extra pointer pxEndOfStack in each Task TCB:
Below such a TCB in the Global Variables View in Eclipse (MCUXpresso IDE):
With this, the debugger or FreeRTOS Task Awareness knows the real size of the stack and can show the correct information:
Actually it is still showing 432 Bytes and 440, because it does not count the first and last entry on the stack.
The image below should help you understand the information provided:
- Blue: at the bottom there is the currently used stack, the stack is growing upwards here (from the higher to the lower addresses)
- Orange: Used stack so far (high water mark) as it has overwritten the 0xA5 pattern
- Yellow: not used stack space so far with the 0xA5 pattern
Of course there is a reason for FreeRTOS not to store that pxEndOfStack by default: it is not needed by the Kernel. So enabling configRECORD_STACK_HIGH_ADDRESS will need 4 more bytes of RAM for each task plus a few code bytes to set that value. But for debugging purposes and this is very well spent.
Happy Stacking 🙂
Thanks fort this article Eric.
I am just wondering if FreeRTOS Kernel Awareness can be installed as a stand-alone add-on for native Eclipse (so for version without MCUExpresso base) ?
Yes, with the plugin from that download area described in https://mcuoneclipse.com/2016/07/06/freertos-kernel-awareness-for-eclipse-from-nxp/
Mmmh, it seems there is this non free solution for Eclipse : https://marketplace.eclipse.org/content/code-confidence-tools-freertos
There is a free version available from NXP, see https://mcuoneclipse.com/2016/07/06/freertos-kernel-awareness-for-eclipse-from-nxp/
Pingback: Tutorial: Understanding and Using FreeRTOS Software Timers | MCU on Eclipse
1. when xTaskCreate API is used TCB and stack is allocated using memory is allocated using pvPortMalloc which means its allocated on HEAP section of memory, what should be stack size in linkerscript?
2.which stack pointer FreeRTOS uses(on cortex-M)? I read somewhere on internet Cortex-M port of FreeRTOS uses only MSP for both OS and Application code if that is true then what will happen if task currently executing uses almost all stack and either OS API is called or interrupt comes?
I read your article ARM Cortex-M, Interrupts and FreeRTOS, disregard the second question, how to determine minimal stack size in linker script for executing main which contains peripheral init and same stack will be used for Interrupts.
That stack size really depends on what you are doing in your initialization. I usually allocate 0x100 or 0x200, but again: it depends. You have to find that out empirically: for example fill your stack with a pattern and check with the debugger how much it uses. Or use the approach described in https://mcuoneclipse.com/2015/08/21/gnu-static-stack-usage-analysis/
I hope this helps,
1. Unless you are using the FreeRTOS Heap Scheme 3 (using stdlib malloc/free), everything is managed by the FreeRTOS heap manager and you don’t have to specify anything in the linker file.
2. during startup and in main, the Cortex core uses the MSP by default. With starting the scheduler, the PSP is used for the task stacks, while the interrupts are still on the MSP.
I’m not sure which version of FreeRTOS you’re using, but for v9.0.0, configRECORD_STACK_HIGH_ADDRESS is not used in any of the FreeRTOS code. For v9, configUSE_TRACE_FACILITY needs to be set.
I used FreeRTOS V10.0.x