Dear forum members, On /fr-content-src/uploads/2019/07/index.html I found the really nice explanation about the internals of FreeRTOS, really a good job! I was curious if there was some more in-depth manual about memory management too. At http://www.freertos.org/FAQMem.html there is something written down, but it is very brief. I have a lot of beginner’s questions w.r.t. debugging an application on top of FreeRTOS. For example I use a call to uxTaskGetStackHighWaterMark to get some grips upon the stack size used by a task. However, that should be used after a task is using a lot of its stack, so if a task doesn’t return, I am too late. Is that possible by the way? Are stacks overrun always detected if the configCHECK_FOR_STACK_OVERFLOW flag is set to 2? And overwrites a task other memory if it overflows, or might it become corrupted? How exactly does the heap and the stacks relate to each other? The configTOTAL_HEAP_SIZE I set to 20kB of the total of 64kB RAM on my Cortex M3 processor (LM3S8962). So, this means that this amount is available to the "kernel" according to http://www.freertos.org/a00110.html, which however means that also my application / tasks use this heap isn’t it? Currently I am using the second heap strategy, see http://www.freertos.org/a00111.html, is it still possible to use malloc() and free(), or should I really use pvPortMalloc() and pvPortFree()? What does it give me for benefit? In my case I am exclusively accessing those data structures anyway (from one task), so I don’t need them defined as critical sections, isn’t it? In general I would like some clues about how to start debugging my applications. I have three tasks defined that I can dynamically load, so I can test them separately. Each of those tasks I started with 1kB of stack size? Is that too much? I figure that with 64kB – 20kB I have 44kB left, so I shouldn’t be to conservative to begin with. And 1kB is not a conservative figure isn’t it? The I am using the "arm-none-eabi-gdb" debugger via openocd to connect to my board. Compiling with -g -O0 flags should give me enough debug information I hope. It makes the binary bigger, 125kB, but still much less then the 256kB available. The problem is that after I start two tasks, the third task doesn’t want to be started. The breakpoint in the debugger is never reached, so it seems. So, there is probably some memory problem. I would appreciate any commentary that can give me some background information about how memory is handled within FreeRTOS. How do I know for example how much a task is using from the heap? If I define the heap as 20kB and 3 tasks use each 1kB for their stack, does that mean that I have 64kB – 23kB = 41kB left, which is not used at all (except for some for the stack for the FreeRTOS scheduler)? How do I know how much overall space is left on the heap? Kind regards, Anne
Hi, the stack obtained for Tasks is taken from kernel heap. So in your example each of the 1k stacks is taken from the 20k kernel heap. Also ich created queue or semaphore is taken from kernel heap. But keep in mind that a task stack size of 1k means 1024 byte. The value you pass for stack size means you want to allocate space for this number of stack items. On most 32-bit processors one stack item is 4 bytes long. So your examples allocates at least 12kb only for stack. Additional to that the task control blocks for each task are also taken from heap. And each call to pvPartMalloc allocates space for structural information for heap You are probly running out of heap memory. You could set a breakpoint in pvPortMalloc and see for yourself which calls allocate how much heap memory and then adjust e.g. the heap size. To give you a few numbers I’ll add some basic sizes that are allocated with my AT91SAM7 µC (also a 32 bit): Heap structure information: 8 Byte Task Control Block: 72 Byte Task Stack: passed_size * 4 queue/semaphore header: 76 Byte Example: a Task is given a stack size of 110 allocates a total of: (72 + 8) + (110 * 4 + 8) = 80 + 448 = 528 Bytes
Thanks for your response! You are right, the size for the stack is given in items, not in bytes. The parameter usStackDepth is given as an "unsigned portSHORT" so with a parameter 1000, it means 2kB is reserved on the heap for the stack of one task, isn’t it? I think you still may be right regarding the 4-bytes length of a stack item. In that case with an usStackDepth parameter of 1000, actually there might be space for 500 elements and the data type shouldn’t be a portSHORT. Correct? There are indeed less problems when I increase the heap to (30 * 1024), however, a further increase to (40 * 1024) is not possible, in that case the debugger ends up directly in the IntDefaultHandler1. That’s weird, because 40kB is way less then 64kB. Do you have idea why increasing the heap to 40kB crashes the application? Because of an incorrect indexing within Eclipse I thought there were malloc_hook and fellow routines available, so I overwrote the malloc calls to pvPortMalloc. However, there are no such hooks, so I rewrote my code/engine now so that it uses pvPortMalloc directly. I can’t use it now anymore as a separate engine in my simulator on my desktop. Is there a neat way to redirect malloc to pvPortMalloc without adding defines in my engine itself? It is working okay for now. However, I am not really a gdb guru, and I would like to know if it is possible to access the heap size for the future. Which commands with gdb can you recommend to inspect heap usage like you suggest? Regards, Anne
Not quite correct. The type in this case just means that the maximum number of stack items is 65535. The size of a stack item ist defined by the size of portSTACK_TYPE (see your portmacro.h). Although you have 64k RAM doesn’t necessarily mean you can use most of it as heap since global variables are stored outside the kernel heap. For the memory usage of your project see your map file. You could use heap_3.c for memory management. This scheme is a wrapper for malloc/free but however as far as I know you need to define the heap space in the linker file. Accessing heap space can be a bit complicated since it might suffer from fragmentation if calls to vPortFree are made (either directly or by kernel routines). I made a breakpoint in pvPortMalloc, let the program run to that point and examined how much space should be allocated and if space is available which address was going to returned and if it was necessary how the linked list of free blocks is managed. Regards P.S.: I only examined the memory management recently out of interest how it works and to find out where i could efficiently reduce RAM usage of my program.
Ah, yes, of course, okay. :-) And yes, global and static variables are stored outside of the kernel heap. Didn’t know about map-files. I see I can create them by /opt/arm-2008q1/bin/arm-none-eabi-ld SymbricatorRTOS.axf -Map SymbricatorRTOS.map. It’s nice! I see now that all my functions are quite tiny compared to the others, ha ha! :-) SymbricatorRTOS is a shell around FreeRTOS, not developed by myself, and it uses heap_2.c because that is most fit for dynamically swapping in and out tasks. Thanks a lot for everything!
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.