In embedded development, you might write something like this:
uint8_t* buf = malloc(1024); // Allocate 1KB of memory
It seems convenient, but in a multitasking system like FreeRTOS, there are some details regarding memory management that need attention.
Differences Between malloc Heap and FreeRTOS Heap
| Feature | malloc / free | pvPortMalloc / vPortFree |
|---|---|---|
| Heap Source | C Library heap | FreeRTOS heap_4 |
| Thread Safety | Potentially unsafe | Thread safe |
| Managed Objects | Own dynamic memory | Task stacks, queues, semaphores, dynamic objects |
| Memory Control | Separate from RTOS heap | Unified system management |
💡 Key Point:
-
<span>malloc</span>/<span>free</span>allocate from the C library managed heap, typically in the<span>.heap</span>section of the linker script or high address RAM. -
This portion of memory is not directly associated with FreeRTOS task stacks and queues.
-
In a multitasking environment, the thread safety of C library malloc/free depends on the compiler/library implementation, and some libraries may be unsafe in multitasking.
-
<span>pvPortMalloc</span>/<span>vPortFree</span>allocate from the FreeRTOS heap (heap_4, etc.), typically reserving a static array in STM32’s RAM:
#define configTOTAL_HEAP_SIZE (46 * 1024) // 46 KB
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
-
All task stacks, TCBs, dynamic queues, semaphores, and dynamic objects mapped using
<span>pvPortMalloc</span>/ LVGL are allocated from this RAM. -
Thread safe, with unified management in a multitasking environment, avoiding memory fragmentation and cross-task access issues.
In simple terms: on STM32, <span>malloc</span> is the “system heap”, while <span>pvPortMalloc</span> is the “RTOS heap”; the two heaps do not interfere with each other in RAM, but the FreeRTOS heap is more suitable for multitasking and GUI systems.
FreeRTOS provides various heap implementations, with heap_4 being the most commonly used:
Features of heap_4:
-
Task stacks, TCBs, queues, and semaphores can all be allocated from this heap
-
Supports dynamic release and merging of free blocks
-
Compatible with thread safety in multitasking
Dynamic Memory in LVGL
If you are using LVGL in a GUI system, you can also allocate memory through the FreeRTOS heap:
#define LV_MEM_CUSTOM_ALLOC pvPortMalloc
#define LV_MEM_CUSTOM_FREE vPortFree
void* buf = lv_mem_alloc(512); // Dynamically allocate
lv_mem_free(buf); // Release when done
-
Dynamic objects like LVGL controls and labels use the same heap, ensuring unified management
-
Avoid stack overflow or fragmented RAM
For large buffers (e.g., 240×240 double buffering), it is recommended to place them in a global array or Flash to save heap space.
Principles of Dynamic Memory Allocation
-
Small objects can be dynamically allocated
-
Both
<span>pvPortMalloc</span>and<span>lv_mem_alloc</span>are thread safe.
Large buffers should be statically allocated or placed in Flash
-
Avoid heap fragmentation and stack overflow.
Task stack sizes should be reasonable
-
GUI tasks ≥ 2 KB, regular tasks can be smaller.
Check allocation return values
-
Have handling logic for NULL to prevent system exceptions.
Example: Dynamic Memory Allocation in GUI Task
void gui_task(void *arg) {
uint8_t* temp_buf = lv_mem_alloc(512); // Allocate temporary buffer
if(temp_buf == NULL) {
printf("Insufficient memory!\n");
vTaskDelay(pdMS_TO_TICKS(1000));
return;
}
while(1) {
update_gui(temp_buf); // Draw interface
lv_task_handler();
vTaskDelay(pdMS_TO_TICKS(10));
}
lv_mem_free(temp_buf);
}
-
The temporary buffer is safely used within the task, not occupying global RAM.
-
Using LVGL’s memory mapped to the FreeRTOS heap allows for unified management.
Conclusion
-
malloc allocates from the C library heap, while pvPortMalloc allocates from the FreeRTOS heap, which is thread safe and managed alongside task stacks and queues.
-
It is best to map LVGL dynamic objects to the FreeRTOS heap, while drawing buffers should be statically allocated or placed in Flash.
-
For dynamic memory allocation, use the heap for small blocks, statically allocate large buffers, and ensure reasonable total RAM usage for higher system stability.