FreeRTOS: Stack High Water Mark Confusion

Hello,

I am using statically allocated tasks and have disabled dynamic allocation.
For hunting down problems on stack usage and optimizing usage, I run the project, perform some tests and then read back the Stack High Water Mark via MCUXpresso from former NXP.

This is what it returns
image
So I calculated: Stack Top - Stack High Water Mark = Highest Stack Usage that was measured
(I am on Cortex M0+ so I guess the “measurement” is in bytes).

However this “measurement” value is always greater than the value I created the task with.
In this case I created the task with a stack of 512 Bytes, but it reads out to be 744 Bytes…
Even worse: Why is the Stack Top - Stack Base 3 times greater than 512 Bytes?
3 seems an odd number… if it was 4 I’d have made some sense out of it…

I am using FreeRTOS Kernel V10.0.1

Thanks a lot for your answers in advance.

I’m not sure what this is doing. Does the MCUXpresso debugger have a method of calculating the stack high water mark, as it is something that has to be calculated rather than read back.

The stack high water mark is accessible from a few FreeRTOS API functions, such as FreeRTOS - A FREE RTOS for small real time embedded systems, and returns the minimum amount of stack space there has been since the task started executing. So the closer the value is to zero the closer the task has got to overflowing its stack.

This looks like you are using the stack high water mark as an address - so assume in the method you are using it is not the minimum amount of stack space that there has been since the task started executing.

Can you please show how you declare the task’s statically allocated stack. It might be the stack is actually 512*4 bytes - the 4 coming from each stack variable being 4 bytes on the Cortex-M0.

Hello,

thank you for the quick response.

Here is how I initialize tasks:
taskHandle_readBuffer=xTaskCreateStatic(readBuffer,“CAN RX”, 512,
NULL, TASK_PRIORITY_CAN_READOUT, taskReadStack, &taskReadBuffer);

Also I now Integrated uxTaskGetStackHighWaterMark(NULL) in my tasks and the values are now plausible.

How do you go about finding the correct stack size, if memory is at premium?

Thanks in advance.

Have a look at the description of the ulStackDepth parameter here: This page describes the FreeRTOS xTaskCreateStatic() API function which allows an RTOS task to be created using statically allocated RAM. you are indeed telling the function the stack is 512*4 bytes, so 2KBytes.

Are you defining taskReadStack like this?

StackType_t taskReadStack[ 512 ]?

Note the StackType_t type. That would be right, but doing this:

uint8_t taskReadStack[ 512 ] would be wrong for a couple of reasons, first the stack may not be aligned correctly, and secondly it would only allocate one quarter of the required space.

If I were working on something safety critical then I would calculate the stack requirements - however normally I would be more pragmatic and ensure I have stack overflow detection turned on during development and testing (but off in production, as it is slow) in case the stack was too small, and then use something like RTOS - uxTaskGetSystemState() to view how much stack was actually used - then tune accordingly. Likewise for the heap, use xPortGetMinimumEverFreeHeapSize() to ensure I was not allocating an unnecessarily large heap.

(kernel aware debugger plug-ins make monitoring stacks simpler)

One tip for balance stack usage is look at the difference between the high water mark and the Stack Base value. That shows you how much is unused (remember the factor of 4). In your picture above there was over 0x500 bytes free, or a little over 256 words.

Be somewhat careful of cutting things too close, as High Water Mark was the most used on this run, and some things may be variable depending on what the task does. (That takes some understanding of what the task actually does and if it has any significant variability.)

Some compilers can take most tasks and compute a static stack usage as long as you don’t use recursion, function pointers, or dynamic stack usage.

Hello,

thanks a lot for clarification.
I am sure what I need to do now.