FreeRTOS needs a way to manage memory for tasks and resources. Different heap implementations help control how memory is allocated and freed.
FreeRTOS heap implementations (heap_1 to heap_5)
/* Example: heap_4.c partial structure and functions */ /* Define the heap size */ #define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024)) /* Static array to hold the heap memory */ static uint8_t ucHeap[configTOTAL_HEAP_SIZE]; /* Function to allocate memory */ void *pvPortMalloc(size_t xSize); /* Function to free memory */ void vPortFree(void *pv); /* Function to initialize the heap */ void vPortInitialiseBlocks(void);
Each heap_x.c file implements these functions differently.
You include only one heap_x.c file in your project to select the heap method.
/* heap_1.c: Simple allocator, no free */ void *pvPortMalloc(size_t xSize) { static size_t xNextFreeByte = 0; if ((xNextFreeByte + xSize) <= configTOTAL_HEAP_SIZE) { void *pvReturn = &ucHeap[xNextFreeByte]; xNextFreeByte += xSize; return pvReturn; } else { return NULL; } } void vPortFree(void *pv) { /* Does nothing */ }
/* heap_2.c: Allocator with free but no coalescing */ /* Uses linked list to track free blocks but does not merge adjacent free blocks */
/* heap_4.c: Allocator with free and coalescing */ /* Uses linked list and merges adjacent free blocks to reduce fragmentation */
/* heap_5.c: Multiple heap regions */ /* Allows defining several separate memory regions to allocate from */
This program shows how heap_1 allocates memory until full, then fails. Free does nothing.
/* Sample FreeRTOS heap_1 usage example */ #include <stdio.h> #include <stdint.h> #include <stddef.h> #define configTOTAL_HEAP_SIZE ((size_t)(1024)) static uint8_t ucHeap[configTOTAL_HEAP_SIZE]; static size_t xNextFreeByte = 0; void *pvPortMalloc(size_t xSize) { if ((xNextFreeByte + xSize) <= configTOTAL_HEAP_SIZE) { void *pvReturn = &ucHeap[xNextFreeByte]; xNextFreeByte += xSize; return pvReturn; } else { return NULL; } } void vPortFree(void *pv) { /* heap_1 does not free memory */ } int main() { printf("Heap size: %zu bytes\n", configTOTAL_HEAP_SIZE); void *ptr1 = pvPortMalloc(100); printf("Allocated 100 bytes at %p\n", ptr1); void *ptr2 = pvPortMalloc(500); printf("Allocated 500 bytes at %p\n", ptr2); void *ptr3 = pvPortMalloc(500); if (ptr3 == NULL) { printf("Allocation of 500 bytes failed (not enough memory)\n"); } else { printf("Allocated 500 bytes at %p\n", ptr3); } vPortFree(ptr1); // Does nothing return 0; }
heap_1 is very simple but cannot free memory, so it is only good for static or simple use cases.
heap_4 is the most flexible and recommended for most applications because it supports freeing and reduces fragmentation.
heap_5 allows multiple memory regions, useful for complex memory layouts.
Time complexity for malloc in heap_4 is generally O(n) where n is number of free blocks.
Common mistake: Including more than one heap_x.c file causes linker errors.
Use heap_1 if you never free memory, heap_4 if you need full malloc/free support.
FreeRTOS provides five heap implementations named heap_1 to heap_5.
Each heap implementation offers different features for memory allocation and freeing.
Choose the heap implementation based on your application's memory management needs.