| File | Frees Memory? | Memory Behavior | Typical Use Case |
|---|---|---|---|
| heap_1.c | No | Never fragments | Allocate-once (tasks/queues created at startup and never deleted) |
| heap_2.c | Yes | Can fragment (doesn't merge free blocks) | Legacy designs only. Avoid for new projects |
| heap_3.c | Yes | Depends on compiler's C library | When you specifically need the standard C malloc/free |
| heap_4.c | Yes | Merges adjacent free blocks to reduce fragmentation | Default choice for most general-purpose RTOS projects |
| heap_5.c | Yes | Same as heap_4.c | Systems with multiple, non-contiguous RAM banks |

heap_1.c is the simplest FreeRTOS heap implementation and provides dynamic memory allocation through pvPortMalloc(). It manages a statically allocated heap defined by configTOTAL_HEAP_SIZE and allocates memory sequentially from the beginning of this heap. Once memory is allocated, it cannot be returned to the heap because heap_1.c does not support vPortFree(). This makes the implementation very small, fast, and deterministic, with no risk of heap fragmentation. It is most suitable for embedded applications in which all dynamic memory is allocated during system initialization and never released, such as systems that create all tasks, queues, semaphores, and other RTOS objects before starting normal operation.

heap_2.c provides dynamic memory allocation through pvPortMalloc() and supports releasing memory with vPortFree(). It manages a statically allocated heap and reuses previously freed blocks when possible. However, adjacent free blocks are not combined, so repeated allocations and deallocations of different sizes can cause memory fragmentation over time. It is mainly suitable for applications that allocate and free blocks of the same or similar sizes, although heap_4.c is generally preferred for most applications that require memory to be freed.

heap_3.c implements the FreeRTOS memory allocation interface by wrapping the standard C library functions malloc() and free(). Unlike the other FreeRTOS heap implementations, it does not use the memory region defined by configTOTAL_HEAP_SIZE; instead, memory management is handled by the C runtime library. This implementation is useful when an application already relies on the standard library heap, but its determinism, thread safety, fragmentation behavior, and memory usage depend on the specific C library and system configuration.

heap_4.c is a commonly used FreeRTOS heap implementation that supports both dynamic allocation with pvPortMalloc() and deallocation with vPortFree(). It manages a statically allocated heap and automatically combines adjacent free memory blocks, which significantly reduces memory fragmentation compared with heap_2.c. It provides a good balance between simplicity, efficiency, and flexibility, making it well suited for applications that dynamically create and delete tasks, queues, semaphores, and other RTOS objects during runtime.

// ---------------------- Example ----------------------
uint8_t *buffer = NULL;
buffer = pvPortMalloc(32);
printf("Allocated memory at address: %p\r\n", (void *)buffer);
printf("Freeing memory at address: %p\r\n", (void *)buffer);
vPortFree(buffer);
buffer = NULL;
size_t freeMem;
freeMem = xPortGetFreeHeapSize();
printf("Free heap memory: %u bytes\r\n", (uint16_t)freeMem);heap_5.c provides the same allocation and deallocation behavior as heap_4.c, including the ability to merge adjacent free blocks, but it can manage multiple separate memory regions instead of a single contiguous heap. The available regions are defined by the application using vPortDefineHeapRegions(), allowing FreeRTOS to use memory located in different RAM banks or address ranges. It is particularly useful on microcontrollers with multiple RAM regions, such as internal SRAM, CCM RAM, or external memory, where the application needs to combine several non-contiguous areas into a single FreeRTOS heap.
typedef struct HeapRegion {
uint8_t *pucStartAddress; // Start address of the memory block
size_t xSizeInBytes; // Size of the memory region
} HeapRegion_t;
HeapRegion_t xHeapRegions[] = {
{ ( uint8_t * ) 0X10000000UL, 0x10000 }, // CCM memory, start address 0X10000000, size 64 KB
{ ( uint8_t * ) 0X20000000UL, 0x20000 }, // Internal SRAM, start address 0X20000000, size 128 KB
{ ( uint8_t * ) 0X68000000UL, 0x100000 }, // External SRAM, start address 0X68000000, size 1 MB
{ NULL, 0 } // End of the array
};
// Initialize the heap memory
vPortDefineHeapRegions((const HeapRegion_t *)xHeapRegions);Back to top of the page