
The TCP/IP performance of a related gadget makes use of dynamic RAM allocation due to the unpredictable nature of community habits. For instance, if a tool serves an online dashboard, we can’t management what number of purchasers would possibly join on the identical time. Likewise, if a tool communicates with a cloud server, we could not know prematurely how giant the exchanged messages will probably be.
Due to this fact, limiting the quantity of RAM utilized by the TCP/IP stack improves the gadget’s safety and reliability, making certain it stays responsive and doesn’t crash as a result of inadequate reminiscence.
Microcontroller RAM overview
It’s widespread that on microcontrollers, out there reminiscence resides in a number of non-contiguous areas. Every of those areas can have completely different cache traits, efficiency ranges, or energy properties, and sure peripheral controllers could solely help DMA operations to particular reminiscence areas.
Let’s take the STM32H723ZG microcontroller for instance. Its datasheet, in part 3.3.2, defines embedded SRAM areas:

Right here is an instance linker script snippet for this microcontroller generated by the CubeMX:

Ethernet DMA reminiscence
We are able to clearly see that RAM is cut up into a number of areas. The STM32H723ZG gadget features a built-in Ethernet MAC controller that makes use of DMA for its operation. It’s necessary to notice that the DMA controller is in area D2, that means it can’t instantly entry reminiscence in area D1. Due to this fact, the linker script and supply code should be certain that Ethernet DMA knowledge constructions are positioned in area D2; for instance, in RAM_D2.
To attain this, first outline a bit within the linker script and place it within the RAM_D2 area:

Second, the Ethernet driver supply code should put respective knowledge into that part. It could appear like this:

Heap reminiscence
The following necessary half is the microcontroller’s heap reminiscence. The usual C library gives two fundamental features for dynamic reminiscence allocation:

Sometimes, ARM-based microcontroller SDKs are shipped with the ARM GCC compiler, which incorporates the Newlib C library. This library, like many others, has an idea of so-called “syscalls” that includes low degree routines that consumer can override, and that are referred to as by the usual C features. In our case, the malloc() and free() customary C routines name the _sbrk() syscall, which firmware code can override.
It’s usually finished within the sycalls.c or sysmem.c file, and should look this:

As we will see, the _sbrk() operates on a single reminiscence area:

That signifies that such implementation can’t be utilized in a number of RAM areas. There are extra superior implementations, like FreeRTOS’s heap4.c, which might use a number of RAM areas and gives pvPortMalloc() and pvPortFree() features.
In any case, customary C features malloc() and free() present heap reminiscence as a shared useful resource. If a number of subsystems in a tool’s firmware use dynamic reminiscence and their reminiscence utilization isn’t restricted by code, any of them can doubtlessly exhaust the out there reminiscence. This may go away the gadget in an out-of-memory state, which generally causes it to cease working.
Due to this fact, the answer is to have each subsystem that makes use of dynamic reminiscence allocation function inside a bounded reminiscence pool. This strategy protects the complete gadget from operating out of reminiscence.
Reminiscence swimming pools
The thought behind a reminiscence pool is to separate a single shared heap—with a single malloc and free—into a number of “heaps” or reminiscence swimming pools, every with its personal malloc and free. The pseudo-code would possibly appear like this:

The following step is to make every firmware subsystem use its personal reminiscence pool. This may be achieved by making a separate reminiscence pool for every subsystem and utilizing the pool’s malloc and free features as an alternative of the usual ones.
Within the case of a TCP/IP stack, this is able to require all elements of the networking code—driver, HTTP/MQTT library, TLS stack, and utility code—to make use of a devoted reminiscence pool. This may be tedious to implement manually.
RTOS reminiscence pool API
Some RTOSes present a reminiscence pool API. For instance, Zephyr gives reminiscence heaps:

The opposite instance of an RTOS that gives reminiscence swimming pools is ThreadX:

Utilizing exterior allocator
The opposite different is to make use of an exterior allocator. There are lots of implementations out there. Listed below are some notable ones:
- umm_malloc is particularly designed to work with the ARM7 embedded processor, nevertheless it ought to work on many different 32-bit processors, in addition to 16- and 8-bit processors.
- o1heap is a extremely deterministic constant-complexity reminiscence allocator designed for laborious real-time high-integrity embedded programs. The title stands for O(1) heap.
Instance: Mongoose and O1Heap
The Mongoose embedded TCP/IP stack makes it straightforward to restrict its reminiscence utilization, as a result of Mongoose makes use of its personal features mg_calloc() and mg_free() to allocate and launch reminiscence. The default implementation makes use of the C customary library features calloc() and free(), however Mongoose permits consumer to override these features with their very own implementations.
We are able to pre-allocate reminiscence for Mongoose at firmware startup, for instance 50 Kb, and use o1heap library to make use of that preallocated block and implement mg_calloc() and mg_free() utilizing o1heap. Listed below are the precise steps:
- Fetch o1heap.c and o1heap.h into your supply tree
- Add o1heap.c to the record of your supply recordsdata
- Preallocate reminiscence chunk on the firmware startup

- Implement mg_calloc() and mg_free() utilizing o1heap and preallocated reminiscence chunk

You possibly can see the complete implementation process within the video linked on the finish of this text.
Keep away from reminiscence exhaustion
This text gives info on the next design elements:
- Perceive STM32’s advanced RAM structure
- Guarantee Ethernet DMA buffers reside in accessible reminiscence
- Keep away from reminiscence exhaustion through the use of bounded reminiscence swimming pools
- Combine the o1heap allocator with Mongoose to implement TCP/IP RAM limits
By isolating the community stack’s reminiscence utilization, you make your firmware extra secure, deterministic, and safe, particularly in real-time or resource-constrained programs.
If you need to see a sensible utility of those rules, see the full tutorial, together with a video with a real-world instance, which describes how RAM limiting is carried out in apply utilizing the Mongoose embedded TCP/IP stack. This video tutorial gives a step-by-step information on easy methods to use Mongoose Wizard to limit TCP/IP networking on a microcontroller to a preallocated reminiscence pool.
As a part of this tutorial, a real-time internet dashboard is created to point out reminiscence utilization in actual time. The demo makes use of an STM32 Nucleo-F756ZG board with built-in Ethernet, however the identical strategy works seamlessly on different architectures too.
Sergey Lyubka is the co-founder and technical director of Cesanta Software program Ltd. He is called the creator of the open-source Mongoose Embedded Internet Server and Networking Library, which has been available on the market since 2004 and has over 12K stars on GitHub. Sergey tackles the difficulty of creating embedded networking less complicated to entry for all builders.
Associated Content material
- Creating Vitality-Environment friendly Embedded Programs
- Can MRAM Get EU Again within the Reminiscence Recreation?
- An MCU take a look at chip embeds 10.8 Mbit STT-MRAM reminiscence
- How MCU reminiscence dictates zone and area ECU architectures
- Breaking By way of Reminiscence Bottlenecks: The Subsequent Frontier for AI Efficiency
The publish restrict TCP/IP RAM utilization on STM32 microcontrollers appeared first on EDN.

