I am a many years Free RTOS user with the STM32 devices. So far I was able to work on platforms, in which the amount of available RAM memory was large enough, for me to freely extend the total heap size or stack sizes for the given tasks, whenever I have encountered any unexpected behavior issues.
From some time however, I am working on a project in which the available RAM is only 8 kB, but the features set is quite demanding. I have noticed that I am expecting unexpected behavior/ crashes related to FreeRtos queues. Increasing the available stack size in the given thread helps to resolve the issue.
My general question is, as I have never learned this over the years: What is the right way of deriving the right amount (or at least as close as possible to the exact right amount) the total heap (assuming heap 1 is used, no dynamic allocations) and thread stacks in the application? So far I was doing this via trial and error…
I would appreciate all help!
First, if you can use Heap1, you can probably also just switch to creating everything with the CreateStatic versions of the functions, and not need to worry about heap sizes at all. This will also reduce your RAM requirements as you remove some overhead.
As for stack size, some compilers have an option to figure out the stack usage of functions, which can help with that problem. Otherwise you need to estimate it by looking at how much stack each function is using in the form of automatic variables, add in the cost of a stack frame for that machine to implement a subroutine call, and add a bit for library functions called.
Thank you for the answer. Create static is something I thought about, but this would make all my libs that Ibuse for different projects to stop being portable (most of the projects would not use create static).
I guess I cod try your second suggestion, to count the stack used by functions. This still does notnput me in the assumed heap size ballpark though. For instance, I have a 4kB heap size and 3 tasks 256 B stack each- with this case I can still be short on heap memory…
Personally, I try to use create static whenever possible, and my C++ wrapper library checks the defines from FreeRTOSconfig.h to do this. This doesn’t work if you have set up that a library function needs to create objects, as then it can’t easily have the static buffer.
For Heap Usage, if you look at the structures defined for the create static, you can figure out how much ram each structure requires, and add in the data/stack blocks for Queues/Tasks and you can tally what your heap usage is. You could also include a out of heap call back to let you know it is too small and check how much space is left in the heap after everything is created to see if it is too big. This would be of course a manual operation. I might be tempted to create constants for all the queue/task stack sizes and put them in a header and create the heap based on a formula adding them up and adding values based on other needs to somewhat automate it.
Thank for the tips Damon, will.need to evaluate how to do it the right way in my case…
So, there is the heap array and there are stacks for each thread. The stacks memory is taken out of the total heap array. The automatic variables created in the threads consume the stack memory. Still the total heap array is a lot larger than the stacks together. What else consumes the total heap apart from the stacks (and rtos objects, like mutexes, queues etc)?
You could just set a breakpoint on
pvPortMalloc and check call stack and the requested size.
Automatic variables come from the stack of the tasks, so will be PART of the allocation you male for the task stack.
FIRST, you need to determine the usage for each task, and set its stack big enough to handle that need. THEN you need to add up all the heap usage: Task Stack, Queue/Stream buffers, and the control structures for tasks/queues/buffers etc. Add to that any buffers you explicitly allocate yourself from the Heap, and that tells to how much heap you need.
Hi, I am using heap 1, so I do not allocate dynamically.
Thanks. I am asking, because I sometimes experience a behavior, in which increasing the tasks stack too much makes the application crash during runtime, even though I am using heap1… The way I understand it then is that the stack takes too much out of the heap memory and itnis short for rtos objects?
Since at that Richard, by design is it even possible that the code can crash somehow during runtime (after all rtos allocations) even though I am using heap 1? Inreasing heap size resolves the problem.
As a mentioned before, define the Heap Allocation Failure Hook, i.e. define configUSE_MALLOC_FAILED_HOOK and provide a definition for void vApplicationMallocFailedHook( void ) to catch out of heap errors. If your application ‘crashes’ it says you aren’t checking for success in you creations. This will let you know that you don’t have enough heap.
The only reason not to define such a function is if you intentionally allow you heap to be exhausted at run time and check for that condition. Otherwise it is a cheap diagnostic.
You also should define configCHECK_FOR_STACK_OVERFLOW to catch many of the problems of overflowing the stack (it isn’t perfect, but does help a lot with overflows).
Ok, this is really helpfull. I will add thw functions to my code. BTW, I always check for correct thread, queues and other objects creations, but I am eager to check this though…