1
votes

I want to know how to calculate Task stack size or the factors are used for this. any help with example please

1
There is no blanket ruling for task size calculation. How much size to be allocated depends on your requirements implementation. - Babajan
How would you calculate how long a rope should be? - Lundin
functions allocate local variables on stack. so if you have single function (wich represent your task) without extra calls with local variables char z[1024]; int y[5]; then you would need stack of about 1044 bytes. add extra bytes to this sum and you will probably have proper size. add to this local vars of nested calls to other functions + up to 40 bytes for save of 10 registers and you will get more precise value. Something like this. I recommend you to read about allocation of local vars on stack. - Maxim Sagaydachny
"calculate" is probably the wrong word. "estimate" is probably a better term. - Clifford

1 Answers

3
votes

The stack requirement is determined by the call depth and the number of local non-static variables instantiated in each function in a call chain. So the task stack required would be the the worst case of all possible call chains being the sum of the stack frame size of each call in that chain.

In an RTOS environment the RTOS itself will have a per-task overhead in addition to the application call chain. Moreover in targets where interrupt contexts do not have a separate stack, you may need to consider the worst case nested interrupt stack requirement on top of that.

In some toolchains, the linker can perform stack requirement analysis for all possible call-chains and output that information to the map file. In that case the values you are interested in will be that for each task entry point function. You need to add to that the minimum task stack requirement for your RTOS and a margin to account for interrupts. Such linker analysis will however be confounded by functions called through pointers such as callbacks and also recursive calls, so you need also to consider that possibility for each task and set the stack accordingly.

The RTOS itself may have stack analysis tools whereby the "high-tide" mark of the stack can be reported. In that case you would necessarily set a relatively large stack size, exercise the task under conditions likely to cause the maximum stack usage, and then modify the stack allocation to suit. This method is only as good as your test, and I would generally add a margin such that you generally never exceed 80% stack capacity for each task. Often it is unusual or unexpected error handling that causes the maximum stack usage, and you may not be able to test those conditions easily.

Static analysis of stack requirement is generally the safer method (with manual consideration of function pointers, recursion and interrupt handling), but dynamic stack analysis and checking support in FreeRTOS is supported by overflow checking and high-tide reporting. Overflow checking is unreliable, since an overflow can cause your code to crash before the scheduler has an opportunity to perform the check.

For accounting for interrupts, you might assume worst case that all interrupts could occur simultaneously and nest so you might add the sum of the stack requirements for all defined interrupt handlers. If nesting is not supported, then just the largest interrupt. This is an argument for keeping your interrupt handlers very simple and without deep call graphs or large local data objects.

The easiest way to deal with the uncertainty of recursion is to not use recursion. Call backs and function pointers are often used extensively in RTOS and device driver abstractions, so you need to consider those carefully. Not always straightforward when using third-party libraries and drivers.

This app note is specific to the Keil/ARM clang toolchain and RTX5 RTOS, but the principles discussed apply generally and is a detailed explanation of the points above.