embedded heap, eheap, is specifically designed for embedded systems. Traditionally, embedded systems have used block pools instead of heaps due to the need for determinism. However, that is changing. Many modern embedded systems and IoT devices incorporate components that require heaps. Attempting to use a group of block pools to emulate a heap can be wasteful [ref 1], especially for isolated partitions that require their own heaps. The purpose of this article is to discuss the basic features of eheap that set it apart from traditional heaps.
Multiple Heaps
As a result of dividing an embedded system into multiple isolated partitions, it may necessary to support multiple heaps. If a partition were to allocate multiple blocks from the main heap (h0 in the diagram), it would need to have all of h0 in one of its regions. As a consequence, malware in that partition could access the data of other partitions, thus breaking isolation. If a partition needs only a few protected blocks or messages, it may be possible to get them from the main heap as MPU regions, assuming that the partition has enough MPA[1] slots available for them. Otherwise, the partition needs its own heap (h1 or h2 in the diagram). eheap supports multiple heaps with the hn parameter, as follows:
void* HeapMalloc(u32 sz, u32 an, u32 hn)
where sz = size, an = alignment, and hn = heap number. This topic will be discussed in more detail in a future article.
Bins, Briefly
Like dlmalloc, and similar heaps, eheap uses bins. Each bin contains a unique range of free chunk[2] sizes. For example, bin 0 = 24 bytes, bin1 = 32 bytes, bin 2 = 40 to 104 bytes, etc. up to the maximum chunk size supported by the heap. The bins cover all chunk sizes in the range of 24 to the maximum size. eheap supports from 1 to 32 bins, in order to accommodate very small to very large heaps. Chunks are initially allocated from the top chunk, which initially is the whole heap. When freed, a chunk is put into the bin for its size. As bins fill up, chunks are allocated more often from bins than from the top chunk. Bins will be discussed more fully in Part 2 of this series.
Chunks and Links
dlmalloc, and similar heaps, have a forward link in each chunk, but they have a backward link only at the end of each free chunk, which links to the start of the free chunk. This link is used to enable merging chunks that are being freed with adjacent free chunks preceding them, if any. Forward links are used to merge chunks being freed with adjacent free chunks following them, if any. This saves a small amount of memory overhead (a backlink per inuse chunk), and apparently works ok for general purpose systems, which can re-run a job or reboot the system, if the heap breaks.
But this solution is not adequate for embedded systems because they are expected to run months or years without stopping and with no supervision. For this reason, all eheap chunks have both forward and backward links. This allows heaps to be continuously scanned forward, by the idle task, a few chunks at a time, while a system is running. When a broken link is found, a repair function is called to start from the end of the heap and scan backward until the break is found and fixed.

In the rare case of a double break, the repair function forms a bridge over the chunks in between the breaks, as shown above. Bridged inuse chunks can continue to be used. Bridged free chunks can be allocated from bins (e.g. #3 above). The system will continue running normally until either end chunk (C or E) is freed. Then the broken link between B and C or E and F is likely to cause an MMF. If a partition heap (h1 or h2) is involved, the partition might be stopped and restarted. If the main heap (h0) is involved, the system might be rebooted. In either case, it is also possible to just log the MMF and to continue running with the bridge in place. This would a allow a partition or a system to continue running until a convenient time to restart or reboot it.
Heap Allocation Failure
eheap normally runs with chunk merge, cmerge, off. An application can turn cmerge on when certain upper limits are reached such as: percent of heap used, number of allocated chunks, number of free chunks (a measure of fragmentation) and it can turn cmerge off when these drop below certain lower limits. While cmerge is on, chunks being freed are merged with adjacent free chunks. As a consequence, there is a migration of chunks to upper bins and eventually to the top chunk. This hurts performance because small chunks become less available and larger chunks may need to be split in order to satisfy smaller chunk allocations. When cmerge is turned off, there is a migration of chunks to lower bins and they get populated again, which helps performance.
In the event that an allocation failure occurs, eheap automatically scans the heap to find free chunks that can be merged to satisfy the allocation. If this fails, the application could reduce the requested block size or shed unused allocated chunks with cmerge on. Failing this, the partition must be shut down and restarted. Of course, a poorly written component could eat up a heap quickly and cause it to fail. However, that is a component selection problem, not a heap problem. In such a case, having an isolated heap protects the rest of the system.
If the main heap (h0) fails then the whole system must be shut down and rebooted. However, that is unlikely because the main heap is normally used mostly for one-time allocations during initialization. While running it is likely to be used only for protected blocks (pblocks) and protected messages (pmsgs), which are limited in number.
It is important to note that in isolated-partition, secure systems, limited MPU regions and limited resource tokens tend to reduce block allocations. Also, even open source components that are not written for embedded environments tend to fall into repetitive patterns in embedded environments. Hence, with adequate testing and sizing of a heap it should be possible to avoid draconian recovery measures. Also, since each isolated partition that needs a heap is given its own heap, heap usage is more predictable than for a single heap shared between many tasks.
Use With An RTOS
eheap is RTOS-agnostic and thus its functions are not reentrant. In order to use eheap in a multitasking environment, one approach is to protect eheap functions with a mutex per heap. A typical multitasking heap function looks like this:

where HeapEnter() tests a mutex and HeapExit() releases it. Each heap has its own timeout value, so it is not necessary to specify timeouts in heap function calls. Of course, this can be changed for a particular RTOS.
An alternative approach is to use a heap server that calls the eheap API directly. In this case, a client would send a message to the server, with requested size and alignment information, and the server would return a pointer to the allocated block. For protected blocks and messages, the client would also provide a pointer to an available slot in its MPA and the heap server would load the block’s region information into that slot.
Conclusion
This article, has reviewed a few features of eheap. There are many more to come. The next article will discuss eheap bins. The full source code for eheap can be found in eheap.c and eheap.h at www.github.com/Micro-Digital/SecureSMX.
References
1. “Heaps vs. Block Pools”, LinkedIn, Ralph Moore, January 2026.
2. “Memory Protection Unit, Part 1: Basics”, LinkedIn, Ralph Moore, March 2026.