cancel
Showing results for 
Search instead for 
Did you mean: 

Integrating micro‑ROS over UDP using LWIP and FreeRTOS on Nucleo-H723ZG

tapererwaj
Associate II

 

Hello everyone,

I’m currently working with the STM32H723ZG Nucleo board and am trying to interface microROS using UDP transport. I’m using the following environment:

  • STM32CubeIDE: v1.16.1
  • STM32Cube Firmware: H7 V1.11.2
  • Toolchain: GNU Tools for STM32 (GCC 12.3.rel1)

I’ve carefully reviewed several guides covering MPU, Ethernet, LWIP, and FreeRTOS configurations. I was able to get microROS working over USART (per the Micro_ROS guide), but when I attempt the UDP transport I encounter a hard fault. I’ve tried replicating setups from the STM32H723_Nucleo_ETH and LWIP_UDP_Echo_Server examples (generated by CubeMX), but they don’t work as expected.

My project files are available here: tapererwaj/h723zg_microros_udp

Below, I have summarized my current configuration:


MPU Configuration

 

SCB_EnableICache();
SCB_EnableDCache();

/* Region 0: Ethernet DMA descriptors */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Region 1: Ethernet/LWIP heap region */
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Region 2: Additional region (512B) */
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.Size = MPU_REGION_SIZE_512B;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

 

FreeRTOS Configuration

  • Task definition:
    FREERTOS.Tasks01=defaultTask,24,512,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
  • Stack overflow checking enabled: FREERTOS.configCHECK_FOR_STACK_OVERFLOW=1
  • Minimal stack size: FREERTOS.configMINIMAL_STACK_SIZE=512
  • Total heap size: FREERTOS.configTOTAL_HEAP_SIZE=30*1024
  • Newlib reentrancy enabled: FREERTOS.configUSE_NEWLIB_REENTRANT=1

Ethernet (ETH) Settings

  • Interface: ETH.MediaInterface=HAL_ETH_RMII_MODE
  • Receive Buffer Address: ETH.RxBuffAddress=0x30000200
  • Receive Buffer Length: ETH.RxBuffLen=1536
  • Tx Descriptor Address: ETH.TxDescAddress=0x30000100

LWIP Configuration

  • Default thread stack size: LWIP.DEFAULT_THREAD_STACKSIZE=2048
  • Static IP: LWIP.IP_ADDRESS=192.168.1.10
  • DHCP disabled: LWIP.LWIP_DHCP=0
  • LWIP heap pointer: LWIP.LWIP_RAM_HEAP_POINTER=0x30000200
  • MEM_SIZE: LWIP.MEM_SIZE=32232
  • Netmask: LWIP.NETMASK_ADDRESS=255.255.255.0
  • TCP/IP thread stack size: LWIP.TCPIP_THREAD_STACKSIZE=2048
  • TCP MSS: LWIP.TCP_MSS=1460
  • TCP SND_BUF: LWIP.TCP_SND_BUF=5840
  • TCP SND_QUEUELEN: LWIP.TCP_SND_QUEUELEN=16

Linker Script Modifications

 

/* Modification start */
   .lwip_sec (NOLOAD) :
  {
    . = ABSOLUTE(0x30000000);
    *(.RxDecripSection) 
    
    . = ABSOLUTE(0x30000100);
    *(.TxDecripSection)
    
  } >RAM_D2
  /* Modification end */

 

LWIP Options (lwipopts.h)

 

#define WITH_RTOS 1
#undef LWIP_PROVIDE_ERRNO

#define CHECKSUM_BY_HARDWARE 1
#define ETH_RX_BUFFER_SIZE 1536
#define MEM_ALIGNMENT 4
#define MEM_SIZE 32232
#define LWIP_RAM_HEAP_POINTER 0x30000200
#define LWIP_SUPPORT_CUSTOM_PBUF 1
#define LWIP_ETHERNET 1
#define LWIP_DNS_SECURE 7
#define TCP_MSS 1460
#define TCP_SND_BUF 5840
#define TCP_SND_QUEUELEN 16
#define LWIP_NETIF_LINK_CALLBACK 1
#define TCPIP_THREAD_STACKSIZE 2048
#define TCPIP_THREAD_PRIO osPriorityNormal
#define TCPIP_MBOX_SIZE 6
#define SLIPIF_THREAD_STACKSIZE 1024
#define SLIPIF_THREAD_PRIO 3
#define DEFAULT_THREAD_STACKSIZE 2048
#define DEFAULT_THREAD_PRIO 3
#define DEFAULT_UDP_RECVMBOX_SIZE 6
#define DEFAULT_TCP_RECVMBOX_SIZE 6
#define DEFAULT_ACCEPTMBOX_SIZE 6
#define RECV_BUFSIZE_DEFAULT 2000000000
#define LWIP_STATS 0
#define CHECKSUM_GEN_IP 0
#define CHECKSUM_GEN_UDP 0
#define CHECKSUM_GEN_TCP 0
#define CHECKSUM_GEN_ICMP6 0
#define CHECKSUM_CHECK_IP 0
#define CHECKSUM_CHECK_UDP 0
#define CHECKSUM_CHECK_TCP 0
#define CHECKSUM_CHECK_ICMP6 0

 

 


Issue:
When running the project, I encounter a hard fault. I suspect this might be due to potential MPU region overlap or an incorrect memory allocation in D2. (For example, my MPU configuration for Region 1 covers 0x30000000–0x30008000, which might conflict with the reserved descriptors.)

My Questions:

  1. How should I adjust the MPU configuration or memory allocation so that the lwIP heap (32232 bytes) in D2 does not overlap with the Ethernet DMA descriptors?
  2. Is there a recommended strategy for relocating the Ethernet RX buffers to AXI SRAM (RAM_D1) while keeping the lwIP heap entirely in D2?
  3. Are there any known issues with STM32CubeIDE v1.16.1 or FW H7 V1.11.2 that might contribute to this hard fault in the context of using microros over UDP?
  4. What would be the best configuration for reliable, fast, and stable communication with a Micro-ROS agent on an Ubuntu 22.04 running ROS2 Humble?

Any guidance or suggestions would be greatly appreciated!

Thank you in advance.

14 REPLIES 14

Thanks @Andrew Neil I will try to add a delay and check it tomorrow.

I found another anomaly/bug (if you can call it a bug), the same program, with the same nucleo board, I don't face this issue when i run it on a windows PC.  The ping fails on an ubuntu environment

  • Windows environment: STM32CubeIDE version 1.18.1 + Firmware version 1.17.3
  • Ubuntu environment: STM32CubeIDE version 1.18.0 + Firmware version 1.17.3

@ak52 wrote:

I will try to add a delay and check it tomorrow.


A delay is just a hack - If you look through those threads, you'll find a proper solution...

 


@ak52 wrote:

I don't face this issue when i run it on a windows PC.  The ping fails on an ubuntu environment


What is "it" here?  ie, What are you running on the PC?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@Andrew Neil wrote:

 

What is "it" here?  ie, What are you running on the PC?


I was referring to the same STM32Cube project (that was run both on Windows and Ubuntu), on windows the ping test works as expected i.e. after Flashing program on the chip the ping test succeeds, but on Ubuntu after flashing the program, the ping test fails.

 


@Andrew Neil wrote:

 

 

A delay is just a hack - If you look through those threads, you'll find a proper solution...

 

 This was marked as an accepted solution so i tried it out.

I added a delay to verify the ping test, it did seem to help but i noticed another issue, After flashing the code into the chip:

  • When I connect the ethernet cable and then power on the nucleo board, the ping test succeeds. Here when i disconnect/connect the ethernet cable many times(just to check), the ping test succeeds every time.(Note that the power is never removed)
  • When I power on the nucleo board first, and then connect the ethernet cable , the ping test fails.

Regarding a proper solution , i think you are talking about this post by @bouazizm ?

I have a few questions here:

  • For a FreeRTOS project would this work? I did not understand what was to be done , could you please elaborate.
  • HAL_ETH_SetMACConfig is called inside the low_level_init() function in my case. The function tree is like this(from what i have traced): MX_LWIP_Init();(from the default task) --> netif_add();(this takes in ethernetif_init as a parameter) --> low_level_init() --> and here HAL_ETH_SetMACConfig is called.
  • But nowhere i was able to find Ethernet_Link_Periodic_Handle. A search to this function lead to zero results. Further more if DHCP is disabled , what do we do in this case?

 

PS: I made a new thread with all the details for debugging the Ethernet issue, i think this thread should be for uRos related questions (Link)


@ak52 wrote:

PS: I made a new thread with all the details for debugging the Ethernet issue


You didn't include all the details; eg, you missed the bit about connecting & disconnecting the Ethernet cable.

 


@ak52 wrote:

 

@Andrew Neil wrote:

 

A delay is just a hack - If you look through those threads, you'll find a proper solution...

 This was marked as an accepted solution


and you'll see that I said in those threads that a delay is just a hack - it just masks the symptom, without curing the underlying issue.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@tapererwaj I was able to get micro-ros with UDP transport working on the NUCLEO-F767ZI.

You can see from the screenshot i could create a node and a dummy publisher. I used this sample file. Its a bit incomplete as the microros function prototypes are missing on the top, because of that a bunch of undefined references errors were coming, Once they were added i was able to communicate to the ros agent

ak52_0-1753941819675.png