Skip to main content
Associate
July 17, 2026
Question

Stm32h745 lwip issue

  • July 17, 2026
  • 6 replies
  • 165 views

Hi everybody,

I’m struggling with the lwip stack in order to get it working with freertos.

I had succesfully achieved to bring up the connection and optain an ip in dhcp mode and ping the board in bare metal mode, now I switched to freertos and I’m no longer able to send discovery packets on the network.

I followed the instructions stated here stm32-hotspot/STM32H7-LwIP-Examples: Ethernet examples using LwIP + FreeRTOS for STM32H7 Discovery and Nucleo boards and tried to copy .ioc configuration from H745 example but I still have the same problem, the phy connection goes up but I cannot obtain the IP address from dhcp server. I’m monitoring the network activity with wireshark but there is nothing coming from the board mac address (in bare metal mode I was able to see dhcp negotiations).

Please find the attached files in order to check what happens and addres the possible issue.

My configuration: 

STM32CubeIDE Version: 2.2.0

STM32CubeMX Version: 6.17.0

STM32Cube FW_H7 V1.13.0

PS: 
please note that ther is a bug in the generated ethernetif.c since it still tries to mange TxConfig in low_level_init function, but TxConfig is no longer a global variable like in the older version o library but it is declared local in low_level_output

 

Thank you.

6 replies

Visitor II
July 20, 2026

Dear STM32 Technical Support, in the project I am currently working on, I had to configure the network for the STM32H745 microcontroller with FreeRTOS and LwIP using STM32CubeMX. I am encountering exactly the same problem described by mbosisio_sl !

  • The compilation error in `ethernetif.c` – since it still attempts to manage `TxConfig` in the `low_level_init()` function – is the same. This is easily workarounded.
  • The PHY connection comes up, but I cannot obtain an IP address from the DHCP server. In `dhcp.c`, the `dhcp_discover()` function keeps retrying indefinitely to obtain the IP address, but nothing is being transmitted from the microcontroller’s Ethernet (ETH) peripheral TX.

My configuration: 

STM32Cube FW_H7 V1.13.0

STM32CubeMX Version: 6.17.0

STM32CubeIDE Version: 2.1.1 

 

I have enabled LWIP/DHCP debugging in the ‘lwipopts.h’ file: 

#define DHCP_DEBUG LWIP_DBG_ON
#define LWIP_DEBUG LWIP_DBG_ON

Using the microcontroller’s USART1, which had previously been integrated with `printf` via:

`int __io_putchar(int ch)` and `int __io_getchar(void)`

 

In the dhcp.c file, added:

-------------- Middlewares/Third_Party/LwIP/src/core/ipv4/dhcp.c --------------
index 12e0068..f08fdfb 100644
@@ -1009,6 +1009,11 @@ dhcp_decline(struct netif *netif)
}
#endif /* LWIP_DHCP_DOES_ACD_CHECK */

+int32_t raw_rx_interrupt_count = 0;
+int32_t raw_tx_interrupt_count = 0;
+int32_t raw_tx_packet_count = 0;
+int32_t raw_tx_error_count = 0;
+volatile uint32_t eth_irq_count = 0;

/**
* Start the DHCP process, discover a DHCP server.
@@ -1070,6 +1075,7 @@ dhcp_discover(struct netif *netif)
msecs = DHCP_REQUEST_BACKOFF_SEQUENCE(dhcp->tries);
dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("ETH INFO: rx_int_cnt:%"U32_F" tx_int_cnt:%"U32_F" tx_pkt_cnt:%"U32_F" tx_pkt_err:%"U32_F" eth_irq_cnt:%"U32_F"\n", raw_rx_interrupt_count, raw_tx_interrupt_count, raw_tx_packet_count, raw_tx_error_count, eth_irq_count));
return result;
}

 

In stm32h7xx_it.c

------------------------- CM7/Core/Src/stm32h7xx_it.c -------------------------
index c83e149..645ac25 100644
@@ -178,13 +178,15 @@ void USART1_IRQHandler(void)
/* USER CODE END USART1_IRQn 1 */
}

+extern volatile uint32_t eth_irq_count;
+
/**
* @brief This function handles Ethernet global interrupt.
*/
void ETH_IRQHandler(void)
{
/* USER CODE BEGIN ETH_IRQn 0 */
-
+ eth_irq_count++;
/* USER CODE END ETH_IRQn 0 */
HAL_ETH_IRQHandler(&heth);
/* USER CODE BEGIN ETH_IRQn 1 */

In ethernetif.c :
 

------------------------- CM7/LWIP/Target/ethernetif.c -------------------------
index 2949c87..288e110 100644
@@ -155,7 +165,10 @@ lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
ETH_PHY_IO_GetTick};

/* USER CODE BEGIN 3 */
-
+extern int32_t raw_rx_interrupt_count;
+extern int32_t raw_tx_interrupt_count;
+extern int32_t raw_tx_packet_count;
+extern int32_t raw_tx_error_count;
/* USER CODE END 3 */

/* Private functions ---------------------------------------------------------*/
@@ -168,6 +181,7 @@ void pbuf_free_custom(struct pbuf *p);
*/
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
+ raw_rx_interrupt_count++;
osSemaphoreRelease(RxPktSemaphore);
}
/**
@@ -177,6 +191,7 @@ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
*/
void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *handlerEth)
{
+ raw_tx_interrupt_count++;
osSemaphoreRelease(TxPktSemaphore);
}
/**
@@ -188,6 +203,9 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth)
{
if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMACSR_RBU) == ETH_DMACSR_RBU)
{
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("ETH error cb: err=0x%08"X32_F" dmacsr=0x%08"X32_F"\n",
+ HAL_ETH_GetError(handlerEth), READ_REG(handlerEth->Instance->DMACSR)));
osSemaphoreRelease(RxPktSemaphore);
}
}
@@ -357,7 +379,7 @@ static void low_level_init(struct netif *netif)
#endif /* LWIP_ARP || LWIP_ETHERNET */

/* USER CODE BEGIN LOW_LEVEL_INIT */
-
+ printf("DMATxDscrTab=%p DMARxDscrTab=%p Rx_Buff=%p\n",(void*)DMATxDscrTab, (void*)DMARxDscrTab, (void*)memp_memory_RX_POOL_base);
/* USER CODE END LOW_LEVEL_INIT */
}

@@ -424,11 +446,16 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
if(HAL_ETH_Transmit_IT(&heth, &tx_config) == HAL_OK)
{
+ raw_tx_packet_count++;
errval = ERR_OK;
}
else
{
-
+ raw_tx_error_count++;
+ uint32_t dmacsr = READ_REG(heth.Instance->DMACSR);
+ uint32_t err = HAL_ETH_GetError(&heth);
+ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("ETH TX fail err=0x%08"X32_F" DMACSR=0x%08"X32_F"\n", err, dmacsr));
if(HAL_ETH_GetError(&heth) & HAL_ETH_ERROR_BUSY)
{
/* Wait for descriptors to become available */

 

The log output will be :

DMATxDscrTab=0x30000080 DMARxDscrTab=0x30000000 Rx_Buff=0x30000100
dhcp_start(netif=0x240003ec) st0
dhcp_start(): mallocing new DHCP client
dhcp_start(): allocated dhcp
dhcp_start(): starting DHCP configuration
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 2000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:0 eth_irq_cnt:1
dhcp_fine_tmr(): request timeout
dhcp_timeout()
dhcp_timeout(): restarting discovery
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ETH TX fail err=0x00000008 DMACSR=0x00055002
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 4000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:1 eth_irq_cnt:1
dhcp_fine_tmr(): request timeout
dhcp_timeout()
dhcp_timeout(): restarting discovery
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ETH TX fail err=0x00000008 DMACSR=0x0005d042
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 8000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:2 eth_irq_cnt:1
dhcp_fine_tmr(): request timeout
dhcp_timeout()
dhcp_timeout(): restarting discovery
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ETH TX fail err=0x00000008 DMACSR=0x0005d0c2
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 16000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:3 eth_irq_cnt:1
dhcp_fine_tmr(): request timeout
dhcp_timeout()
dhcp_timeout(): restarting discovery
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ETH TX fail err=0x00000008 DMACSR=0x0005d0c2
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 32000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:4 eth_irq_cnt:1
dhcp_coarse_tmr()
dhcp_fine_tmr(): request timeout
dhcp_timeout()
dhcp_timeout(): restarting discovery
dhcp_discover()
transaction id xid(4bb5f646)
dhcp_discover: making request
dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)
ETH TX fail err=0x00000008 DMACSR=0x0005d0c2
dhcp_discover: deleting()
dhcp_discover: SELECTING
dhcp_discover(): set request timeout 60000 msecs
ETH INFO: rx_int_cnt:0 tx_int_cnt:0 tx_pkt_cnt:1 tx_pkt_err:5 eth_irq_cnt:1
  • 'rx_int_cnt' and “tx_int_cnt” remain at 0
  • “tx_pkt_cnt” and “eth_irq_cnt” go to 1 after the first iteration
  • whilst “tx_pkt_err” continues to increment with each subsequent attempt…

 

Associate
July 20, 2026

Hi, the good news is that if you took the example like I did, the main problem is a typo in the linker file: RxDecripSection instead of RxDescripSection and TxDecripSection instead of RxDescripSection.

The bad one is that it only fixes the reception of dhcp discovery but I still have memory access issues wich run into hardware falt in several points of the lwip stack.

I suppose that freertos and lwip versions are not properly aligned or something is missing in the mpu configuration.

For sure the example provided was not working at all, pretty strane nobody complained about it in such amount of time.

Anyway still waiting for fixes by the company support.

ST Employee
July 20, 2026

Hello All,

 

Thank you for your detailed report. This issue has been tracked internally.

Internal ticket number: CDM0064499

 

With Regards

If your question is answered, please close this topic by clicking ""Accept as Solution"".
Associate
July 21, 2026
/* Stack size of the interface thread */
#define INTERFACE_THREAD_STACK_SIZE ( 350 )

I changed 350 with 1024 

I’m checking the watermarks with vTaskList and this is the result:

defaultTask X 24 53 1

EthLink R 16 194 6

IDLE R 0 489 2

tcpip_thread B 24 287 4

EthIf B 48 147 5

Tmr Svc B 2 982 3

EthIf task has (147*4) bytes never used, it means that it used at least once (1024-(147*4)) which is more than 350 initially provided by the library.

The default value of tcpip stack set by default in cubemx is too tiny as well, 1024 bytes is the minimum required to run but it is totally used since the beginning with no safety  margin, 2048 is strongly suggested (like set in the example).

With this configuration it seems that I’m stable to obtain ip from dhcp, ping the board and keep the connection up without memory leaks or corrupted data issues.

PS: a mention about the need to modify both .ld files for m4 and m7 could be appreciated in the readme

Visitor II
July 23, 2026

Dear mbosisio_sl,

Could you tell me which example in this repository https://github.com/stm32-hotspot/STM32H7-LwIP-Examples/tree/main you’ve used, and whether it works for the STM32H745? (I can see four)

STM32H745_Disco_M4_ETH

STM32H745_Disco_M7_ETH

STM32H745_Nucleo_M4_ETH

STM32H745_Nucleo_M7_ETH

This is apart from the corrections you had to make, as you mentioned, to the linker script and the change to INTERFACE_THREAD_STACK_SIZE

 

Thanks!

Associate
July 27, 2026

Hi, I did not ran any example since I’m not working on demo board but on a custom board with STM32H745. I only looked at them in order to cherry pick the ioc file. If you have the same situation I suggest you to work on your own project by using stm32bubemx, after enabling eth, mpu, freertos and lwip set them as follows.

Set mpu like this:

set eth buffer addresses according to mpu section 2:

and enable interrupt:

set lwip heap according to mpu section 1:

and stacks:

and finally define sections in linker file

set freertos min stack size:

If you are running lwip on m7 this will be you m7 memory map:

and this for M4:

Generate code and fix enthernetif.c for stack size and garbage lines like we said.

Print ip address once at the end of ethernet_link_thread:

I cannot guarantee that this is the perfect configuation but it works for me with minimal changes to default configuration in cubemx.

Hope it will be helpful for you.

Bye