• Become a member
  • Log In
The Institution of Electronics
  • Home
  • About us
    • Our Objectives
    • Our History
    • Governance of the Institution
  • The Electron Magazine
    • 2024
      • 2024 – Winter
      • 2024 – Spring
      • 2024 – Summer
      • 2024 – Autumn
    • 2025
      • 2025 – Winter
      • 2025 – Spring
      • 2025 – Summer
      • 2025 – Autumn
    • 2026
      • 2026 – Winter
      • 2026 – Spring
  • Members
    • Membership Grades and Fees
    • Members’ Resources
      • The Electron Newsletter
      • The Archives
  • Education and Projects
    • National Electronics Competition
    • Student Members’ Projects
    • Arkwright Engineering Scholarships
  • News
  • Contact Us
  • Menu Menu
Uncategorised

How to limit TCP/IP RAM usage on STM32 microcontrollers

The TCP/IP functionality of a connected device uses dynamic RAM allocation because of the unpredictable nature of network behavior. For example, if a device serves a web dashboard, we cannot control how many clients might connect at the same time. Likewise, if a device communicates with a cloud server, we may not know in advance how large the exchanged messages will be.

Therefore, limiting the amount of RAM used by the TCP/IP stack improves the device’s security and reliability, ensuring it remains responsive and does not crash due to insufficient memory.

Microcontroller RAM overview

It’s common that on microcontrollers, available memory resides in several non-contiguous regions. Each of these regions can have different cache characteristics, performance levels, or power properties, and certain peripheral controllers may only support DMA operations to specific memory areas.

Let’s take the STM32H723ZG microcontroller as an example. Its datasheet, in section 3.3.2, defines embedded SRAM regions:

Here is an example linker script snippet for this microcontroller generated by the CubeMX:

Ethernet DMA memory

We can clearly see that RAM is split into several regions. The STM32H723ZG device includes a built-in Ethernet MAC controller that uses DMA for its operation. It’s important to note that the DMA controller is in domain D2, meaning it cannot directly access memory in domain D1. Therefore, the linker script and source code must ensure that Ethernet DMA data structures are placed in domain D2; for example, in RAM_D2.

To achieve this, first define a section in the linker script and place it in the RAM_D2 region:

Second, the Ethernet driver source code must put respective data into that section. It may look like this:

Heap memory

The next important part is the microcontroller’s heap memory. The standard C library provides two basic functions for dynamic memory allocation:

Typically, ARM-based microcontroller SDKs are shipped with the ARM GCC compiler, which includes the Newlib C library. This library, like many others, has a concept of so-called “syscalls” featuring low level routines that user can override, and which are called by the standard C functions. In our case, the malloc() and free() standard C routines call the _sbrk() syscall, which firmware code can override.

It’s typically done in the sycalls.c or sysmem.c file, and may look this:

As we can see, the _sbrk() operates on a single memory region:

That means that such implementation cannot be used in several RAM regions. There are more advanced implementations, like FreeRTOS’s heap4.c, which can use multiple RAM regions and provides pvPortMalloc() and pvPortFree() functions.

In any case, standard C functions malloc() and free() provide heap memory as a shared resource. If several subsystems in a device’s firmware use dynamic memory and their memory usage is not limited by code, any of them can potentially exhaust the available memory. This can leave the device in an out-of-memory state, which typically causes it to stop operating.

Therefore, the solution is to have every subsystem that uses dynamic memory allocation operate within a bounded memory pool. This approach protects the entire device from running out of memory.

Memory pools

The idea behind a memory pool is to split a single shared heap—with a single malloc and free—into multiple “heaps” or memory pools, each with its own malloc and free. The pseudo-code might look like this:

The next step is to make each firmware subsystem use its own memory pool. This can be achieved by creating a separate memory pool for each subsystem and using the pool’s malloc and free functions instead of the standard ones.

In the case of a TCP/IP stack, this would require all parts of the networking code—driver, HTTP/MQTT library, TLS stack, and application code—to use a dedicated memory pool. This can be tedious to implement manually.

RTOS memory pool API

Some RTOSes provide a memory pool API. For example, Zephyr provides memory heaps:

The other example of an RTOS that provides memory pools is ThreadX:

Using external allocator

The other alternative is to use an external allocator. There are many implementations available. Here are some notable ones:

  • umm_malloc is specifically designed to work with the ARM7 embedded processor, but it should work on many other 32-bit processors, as well as 16- and 8-bit processors.
  • o1heap is a highly deterministic constant-complexity memory allocator designed for hard real-time high-integrity embedded systems. The name stands for O(1) heap.

Example: Mongoose and O1Heap

The Mongoose embedded TCP/IP stack makes it easy to limit its memory usage, because Mongoose uses its own functions mg_calloc() and mg_free() to allocate and release memory. The default implementation uses the C standard library functions calloc() and free(), but Mongoose allows user to override these functions with their own implementations.

We can pre-allocate memory for Mongoose at firmware startup, for example 50 Kb, and use o1heap library to use that preallocated block and implement mg_calloc() and mg_free() using o1heap. Here are the exact steps:

  1. Fetch o1heap.c and o1heap.h into your source tree
  2. Add o1heap.c to the list of your source files
  3. Preallocate memory chunk at the firmware startup

  1. Implement mg_calloc() and mg_free() using o1heap and preallocated memory chunk

You can see the full implementation procedure in the video linked at the end of this article.

Avoid memory exhaustion

This article provides information on the following design aspects:

  • Understand STM32’s complex RAM layout
  • Ensure Ethernet DMA buffers reside in accessible memory
  • Avoid memory exhaustion by using bounded memory pools
  • Integrate the o1heap allocator with Mongoose to enforce TCP/IP RAM limits

By isolating the network stack’s memory usage, you make your firmware more stable, deterministic, and secure, especially in real-time or resource-constrained systems.

If you would like to see a practical application of these principles, see the complete tutorial, including a video with a real-world example, which describes how RAM limiting is implemented in practice using the Mongoose embedded TCP/IP stack. This video tutorial provides a step-by-step guide on how to use Mongoose Wizard to restrict TCP/IP networking on a microcontroller to a preallocated memory pool.

As part of this tutorial, a real-time web dashboard is created to show memory usage in real time. The demo uses an STM32 Nucleo-F756ZG board with built-in Ethernet, but the same approach works seamlessly on other architectures too.

Sergey Lyubka is the co-founder and technical director of Cesanta Software Ltd. He is known as the author of the open-source Mongoose Embedded Web Server and Networking Library, which has been on the market since 2004 and has over 12K stars on GitHub. Sergey tackles the issue of making embedded networking simpler to access for all developers.

Related Content

  • Developing Energy-Efficient Embedded Systems
  • Can MRAM Get EU Back in the Memory Game?
  • An MCU test chip embeds 10.8 Mbit STT-MRAM memory
  • How MCU memory dictates zone and domain ECU architectures
  • Breaking Through Memory Bottlenecks: The Next Frontier for AI Performance

The post How to limit TCP/IP RAM usage on STM32 microcontrollers appeared first on EDN.

13 November 2025
http://institutionofelectronics.ac.uk/wp-content/uploads/2022/12/IOE_LOGO.png 0 0 whdsolutions http://institutionofelectronics.ac.uk/wp-content/uploads/2022/12/IOE_LOGO.png whdsolutions2025-11-13 07:43:312025-11-13 07:43:31How to limit TCP/IP RAM usage on STM32 microcontrollers

Latest news

  • Secrets of Oscilloscope Time Measurements14 August 2026 - 13:44
  • Radon: Level detection, risk determination, and as-needed mitigation13 August 2026 - 13:16
  • TI a first mover in CAN XL transceivers13 August 2026 - 10:13
  • Four-channel USB-UART IC boosts server management13 August 2026 - 05:08
  • eFuse speeds overcurrent detection13 August 2026 - 05:08
  • Memory platform tackles AI bottlenecks13 August 2026 - 05:08
  • 6.5-kV SiC MOSFET reaches 8-kV blocking13 August 2026 - 05:08
  • Made by Google 2026: This limited silicon-supply situation really sucks13 August 2026 - 05:08
  • Cheap and cheerful LMC555 RC PWM pulse generator12 August 2026 - 13:56
  • Record high wafer shipments. Can fabs keep pace?12 August 2026 - 07:51
IOE LOGO 2

Become a member

click here

Become a member

click here

Become a subscriber

click here

Become a sponsor

click here

© Copyright - The Institution of Electronics | Website by WHD Solutions
  • Link to LinkedIn
  • Link to Facebook
  • Link to X
Link to: Predictive maintenance at the heart of Industry 4.0 Link to: Predictive maintenance at the heart of Industry 4.0 Predictive maintenance at the heart of Industry 4.0 Link to: Basic design equations for three precision current sources Link to: Basic design equations for three precision current sources Basic design equations for three precision current sources
Scroll to top Scroll to top Scroll to top