on 2025-06-27 4:30 AM
In this article, we go through the necessary steps to create a working UDP echo server for the STM32F767 MCU. This demo is applicable to other F7 series microcontrollers with some minor differences in memory addresses depending on the model. This resulting project is available on our GitHub STM32 hotspot that you can access by clicking here.
Hardware:
Software:
To create a new project in STM32CubeMX for the Nucleo-F767 board, start by launching STM32CubeMX and clicking on [New Project]. In the "Board Selector" tab, locate and select the [NUCLEO-F767ZI] board. After doing so, a pop-up will appear asking, "Initialize all peripherals in default mode? Choose [No] to avoid applying default configurations to the peripheral. Once the project is created, we proceed by clicking on [Pinout] and selecting [Clear Pinouts] to remove all the default pin assignments. After doing this step, we can finally start configuring our project.
To optimize performance and ensure memory protection, enable [Instruction Cache (ICACHE)] and [Data Cache (DCACHE)] in STM32CubeMX. Navigate to the "Cortex-M7" settings under the "System Core" section. Enable the Memory Protection Unit (MPU) and set it to [Background Region Privileged access only + MPU Disabled during hard fault] mode. Configure the MPU regions as shown in the provided image.
For example, set "Region 0" with a base address of 0x0, 4GB size, and access permissions as ALL ACCESS NOT PERMITTED. Similarly, configure Region 1 and Region 2 with their respective base addresses, sizes, and access permissions. These settings ensure efficient memory management and protection for your application.
To configure Ethernet for the Nucleo-F767 board in STM32CubeMX, enable the Ethernet peripheral in the "Pinout & Configuration" tab. Set it to [RMII mode], as this is the mode supported on the board. Next, enable the [Ethernet interrupt] and set its preemption priority to [5], which is required by FreeRTOS™ to ensure that its functions can be called from the interrupt handler. Additionally, configure the speed of the Ethernet-related GPIO pins to [Very High] to support the high-speed data transfer required for Ethernet communication.
To enable FreeRTOS™ in STM32CubeMX, go to the Middleware section and activate FreeRTOS™ with the CMSIS_V1 API. The CMSIS_V2 API is not supported for the STM32F7 series. Once enabled, navigate to the "Tasks and Queues" tab and locate the defaultTask. Increase the stack size of the defaultTask to [512 words] to ensure sufficient memory allocation for task execution. This adjustment is crucial for handling the application's requirements without running into stack overflow issues.
To configure LwIP in STM32CubeMX, start by enabling the LwIP stack in the "Middleware" section. For IP assignment, use DHCP to automatically obtain an IP address. If manual configuration is preferred, disable DHCP and assign a static IP address. Next, navigate to the "Platform Settings" tab and select LAN8742 in both dropdown boxes. The LAN8742 driver is compatible with the LAN8740 Ethernet PHY device present on the Nucleo-F767 board, ensuring proper Ethernet communication.
In the "Key options" tab, make the following adjustments:
Once all configurations are complete, select a destination folder and generate the project files by clicking on the [Generate Code] button. In this project, we selected the option to generate a source and header file for each peripheral, ensuring better code organization. While we use STM32CubeIDE as the development environment in this example, the generated project is also compatible with other supported IDEs. Ensure that the selected toolchain matches your preferred IDE during the code generation process.
After configuring STM32CubeMX, the final step is to adjust the generated code to ensure the project functions as intended.
This step can be skipped for Keil® and IAR, as these IDEs support placing variables at specific addresses directly in the C code. You need to make the following adjustments to STM32F767ZITX_FLASH.ld as shown below.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
Memory_B1(xrw) : ORIGIN = 0x2007C000, LENGTH = 0xA0
Memory_B2(xrw) : ORIGIN = 0x2007C0A0, LENGTH = 0xA0
}
...
.RxDecripSection (NOLOAD) : { *(.RxDecripSection) } >Memory_B1
.TxDescripSection (NOLOAD) : { *(.TxDecripSection) } >Memory_B2
In the default task created by STM32CubeMX, we add a function to initialize the UDP server thread. Include the provided UDP_echoserver.c file by adding it to the src folder (source files) of your project. This file contains the implementation of the UDP echo server, which handles incoming UDP packets. Ensure that the initialization function is properly called within the default task to start the server.
...
/* USER CODE BEGIN PFP */
extern void udpecho_init(void);
/* USER CODE END PFP */
...
void StartDefaultTask(void const * argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN 5 */
udpecho_init();
/* Infinite loop */
for(;;)
{
osThreadTerminate(defaultTaskHandle);
}
/* USER CODE END 5 */
}
The server listens for incoming UDP packets on a specified port, processes the data, and sends the same data back to the sender. Below is a summary of its key components:
Compile the code. Using an application or utility like Packet Sender, you can test whether the server is successfully receiving UDP test messages. The board can obtain its IP address in two ways: either dynamically from a DHCP server running on the testing computer or network using, for example, Tftpd32, or through a statically defined IP address. In this example, we format a UDP packet to send to port 7 using the IP address, whether it is assigned by the DHCP server or manually configured.
After this, you should see that the response echoed back by the UDP server running on the board, confirming that the server is functioning correctly and everything is working as intended.
With this information, you can now develop a basic application using DHCP with the LwIP middleware. For more advanced implementations, check out our demonstration projects on GitHub, such as those for the STM32F7 series, or connect with us through the ST community for support.
Here are some useful links to assist with development using the LwIP middleware within ST’s ecosystem:
Hello @mƎALLEm ,
Thank you for this detailed tutorial. I also really appreciated the explanatory side notes all over the article indicating, for instance, that CMSIS V2 is not supported in the STM32CubeF7 firmware or that the linker file modification can be skipped if using EWARM or Keil, answering questions that may arise in one's mind while reading.
With regards,