Add TCP/IP stack to STM32
This guide shows how to add a TCP/IP stack to an existing STM32 firmware project. The example uses STM32 Cube and CubeMX, which is the most common STM32 workflow.
The target board is Nucleo-H723ZG with built-in Ethernet, but the same integration approach applies to other STM32 devices and networking hardware.
Mongoose includes a built-in TCP/IP stack and networking library. In this guide, we integrate Mongoose into an STM32 firmware project and run a minimal HTTP server.
Copy Mongoose files
Mongoose is distributed as two core source files. The easiest way to integrate it is to copy them directly into your project.
Create a mongoose/ directory in the project root:
project/
mongoose/
mongoose.c
mongoose.h
mongoose_config.h
... rest of the project files ...
Download mongoose.c and
mongoose.h from the Mongoose repository and create mongoose_config.h:
#define MG_ARCH MG_ARCH_CUBE
#define MG_ENABLE_TCPIP 1
MG_ARCH_CUBE enables the STM32 Cube environment.MG_ENABLE_TCPIP enables the built-in TCP/IP stack.
Set Network Driver
Embedded networking typically follows a layered architecture:
driver → TCP/IP stack → TLS → protocols (HTTP, WebSocket, MQTT) → application
See TCP/IP stack for embedded devices for a detailed explanation.
In this section, we configure the lowest layer - the network driver, which connects your device to the network.
STM32 and other microcontrollers support multiple networking options:
- built-in Ethernet MAC
- external Ethernet controllers (e.g., W5500)
- WiFi modules (e.g., CYW43439)
- cellular modems
Mongoose provides built-in drivers for common embedded networking hardware, making it easy to bring up connectivity and build web-based device interfaces.
In particular, Mongoose includes drivers for STM32 microcontrollers with a built-in Ethernet MAC. The Nucleo-H723ZG uses its internal Ethernet MAC, so enable the STM32 Ethernet driver in mongoose_config.h:
#define MG_ENABLE_DRIVER_STM32H 1
#define MG_ETH_RAM __attribute__((section(".eth_ram")))
For STM32F devices, use MG_ENABLE_DRIVER_STM32F.
The MG_ETH_RAM definition places Ethernet DMA buffers into a memory region accessible by the MAC DMA engine. This part matters - if buffers land in the wrong RAM, Ethernet simply will not work.
Then configure the hardware in CubeMX:
- enable the Ethernet peripheral
- configure Ethernet pins
- enable a UART for debug output
Update the linker script
Ethernet DMA buffers must be placed into a valid RAM region. Update the linker script and define the .eth_ram section.
Example:
MEMORY {
RAM_D2(rwx): ORIGIN = 0x30000000, LENGTH = 32K
}
.eth_ram : { *(.eth_ram .eth_ram*) } > RAM_D2 AT > ROM
The exact RAM region depends on the STM32 model.
Create a minimal HTTP server
Open Core/Src/main.c. Include Mongoose header at the top:
#include "mongoose.h"
Before the main() function, add the following two functions:
// Redirect `printf()` to UART so debug output is visible:
int _write(int fd, unsigned char *buf, int len) {
HAL_UART_Transmit(&huart3, buf, len, HAL_MAX_DELAY);
return len;
}
// HTTP server event handler
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api/hello"), NULL)) {
mg_http_reply(c, 200, "", "{%m:%d}\n", MG_ESC("status"), 1);
} else {
mg_http_reply(c, 200, "", "hello world\n");
}
}
}
Modify your main() function main loop - before the loop, add
Mongoose instance initialisation, and inside the loop, add mg_mgr_poll() call:
struct mg_mgr mgr;
mg_mgr_init(&mgr);
mg_http_listen(&mgr, "http://0.0.0.0", http_ev_handler, NULL);
while (1) {
mg_mgr_poll(&mgr, 0);
The mg_mgr_poll() processes packets, parses protocols, and calls your event handler when something happens.
Build and run
Add the mongoose/ directory to the project include paths and build the firmware.
Open a serial console. Mongoose prints the assigned IP address during startup. Open that address in a browser and the board should reply with:
hello world
At this point your STM32 firmware has a working TCP/IP stack and HTTP server powered by Mongoose.