Sorry that I haven’t worked with FreeRTOS for a while. Recently when I re-picked up the latest FreeRTOS, I found out that the MPU wrappers of pvPortMalloc()/vPortFree() are removed from MPU_wrappers.h, even though MPU_pvPortMalloc()/MPU_vPortFree() still exist in mpu_wrappers.c
I didn’t found out the description in the change log. Could anyone tell me the purpose of this removal? If I have to malloc() with MPU configuration, does it mean that I shall directly call MPU_pvPortMalloc(), rather than pvPortMalloc()?
pvPortMalloc() is a privileged function, so if the calling task is privileged then you can call it directly. I don’t recall why the wrappers were removed, maybe because an unprivileged task would not have access to the memory returned from the heap anyway?
It confuses me a little since I always thought that malloc() family was specially for application-level heap management.
Assumed that an unprivileged thread requires to dynamically allocate buffers whose size can vary, how should this thread be implemented?
Since MPU_pvPortMalloc() is still available, can I call MPU_pvPortMalloc() in this unprivileged thread to ask for heap memory?
I am also confused that if the unprivileged task can not access the memory dedicated for allocation how the unprivileged task allocate a memory. And also, similar APIs such as MPU_vQueueDelete, can be called by a unprivileged task. I see no difference between pvPortMalloc and other APIs in the mpu_wrappers.h.
Remember that an unprivileged task can only directly access memory from a limited number of segments, and has full access to memory in any of those segments.
If an unprivileged task could call pvPortMalloc, then for it to be able to use that memory, the entire heap would need to be in unprivileged memory (as pvPortMalloc doesn’t know if the request is from a privileged or unprivileged task. That means that none of the memory given to a privileged task would be protected from unprivileged tasks, which sort of defeats the purpose of making tasks unprivileged.
One solution would be to take the desired heap function file, make a copy of it, and change the function name and the name of the globals in it to let it provide for unprivileged memory. Note, that you will then need to make sure that the block of memory assigned to the heap is made accessible to all the unprivileged tasks that use that heap (so two unprivileged tasks could interfere with each other).
So what about MPU_pvPortMalloc()? Can unprivileged task call it or not, according to current FreeRTOS design?
Yes, an unprivileged task can call it.
Got it. Thanks for the answer.
So two heaps should be prepared. One should be configured as privileged access only by the MPU and is for the privileged tasks. The other should be configured as unprivileged access and privileged access by the MPU and is for the unprivileged tasks. So that the tasks can access their dedicated heap and the unprivileged tasks can not access the privileged tasks’ memory.
Is my understanding right?
If so, the MPU_pvPortMalloc should not exist. Because it raises to privileged to access the heap. An unprivileged task can still access the privileged tasks’ heap by calling MPU_pvPortMalloc.
@richard-damon Could you comment on the reply I posted above? Thanks!
First, a small disclaimer, I don’t use the MPU/Protected task feature much, so I am not real familiar with it.
The basic thing to remember is that FreeRTOS starts as a simple RTOS, designed for a single simple processor, and then uses add-on code to support things like memory protection. As such, the ‘default’ task would be ‘priviledged’ and restricted tasks need to be somewhat special cased. One big implication of this is that FreeRTOS itself only provides/supports a single heap to make its objects/stack space from, and if restricted tasks could access that memory, they wouldn’t be that restricted, so the heap is really only for privileged task, and restricted tasks need to be created specially (which allows their memory to be aligned in a way to make them restricted). Since restricted tasks can’t access the memory in the FreeRTOS heap, there is no reason to allow them to allocate memory from that heap.
Making two heaps doesn’t help a lot either, as that says that one restricted task is able to interfere with another restricted task, which is normally not desired when using the MPU. Really, each restricted task that needs dynamic memory, should have its own heap carved out of the tasks personal memory segment (the one its stack is located in) to keep itself restricted.
BTW there is a related maybe also interesting topic in the forum.
Yes, you are right and we will remove these.
MPU_vPortFree have been removed in this PR: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/88
Thank you for reporting this issue.
Does the FreeRTOS’s heap management support creating a task with a dedicated heap just like with a dedicated stack?
You have full control about task context and stack when using xTaskCreateStatic.
FreeRTOS does NOT have support for giving a task a dedicated heap, that is the responsibility of the application programer.
Thanks for your prompt reply!
So currently, the FreeRTOS provides heap_1…4 heap management implementation examples which do not cover the case of creating a privileged stack and an unprivileged. The user should implement this case heap management. Is my understanding correct?
If the user needs some specialized heap management, like a heap for one specific task, then they need to provide that code, though it could be based on the other heap codes provided.
So currently, the FreeRTOS provides heap_1…4 heap management implementation examples which do not cover the case of creating a privileged stack and an unprivileged
I want to make sure that the distinction of stack and heap is clear. If you want to create an unprivileged task, use
xTaskCreateRestrictedStatic. Both these APIs allow you to supply the memory to be used for task’s stack. You can see an example here: https://github.com/FreeRTOS/FreeRTOS/blob/master/FreeRTOS/Demo/CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil/Demo/mpu_demo.c#L233
If you want to use heap functionality in an unprivileged task, you need to provide the implementation and use an MPU region to grant the task access to this memory: https://github.com/FreeRTOS/FreeRTOS/blob/master/FreeRTOS/Demo/CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil/Demo/mpu_demo.c#L225
Depending on what your application needs are, you may also consider using a statically allocated buffer instead of dynamic allocation.