Skip to main content
_AdamNtrx
Associate III
January 30, 2026
Question

Ethernet DMA error - how to handle it?

  • January 30, 2026
  • 6 replies
  • 666 views

Hello!

I am writing a program for STM32F769I-DISCO board that uses FreeRTOS and LwIP to communicate with the server and send data to it. It generally works, but unplugging and plugging Ethernet cable (especially doing it several times within a few seconds) usually causes Ethernet DMA errors which make program stop calling HAL_ETH_IRQHandler and thus board can't even try to reconnect to server. I don't know how I should handle those errors and where to look for information that could offer a solution to my problem.

Any kind of help, whether a direct response or a link to helpful resources, is appreciated.

 

Ethernet DMASR registerEthernet DMASR registerheth error codeheth error code

MPU and Ethernet descriptorsMPU and Ethernet descriptors

 

EDIT 1: Added ethernetif.c and lwip.c files to attachments and screenshot of MPU configuration.

 

6 replies

Associate III
January 30, 2026

Can you share your lwip.c implementation as well as ethernetif.c? Also how often per second do you plug it out?

It could be possible that something in the ethernet thread is silently failing or a mutex is internally overflowing. Maybe you could internally in the thread implement a logging mechanism and track it, or you accept that it is maybe out of scope XD

_AdamNtrx
_AdamNtrxAuthor
Associate III
January 30, 2026

I added files to attachments. In short, I didn't really change those files, only added attributes to semaphores and inserted some uint8_t variables to check them in debugger. The biggest changes are in lwipopts.h file where I decided to turn off some features without regenerating code with CubeMX.

_AdamNtrx
_AdamNtrxAuthor
Associate III
February 2, 2026

I made some progress in regard to restarting the Ethernet peripheral and its DMA, but I still have a problem with reconnecting to the server.

if (resetDMA==1) {
	resetDMA=0;

	heth.Instance->DMAOMR &= ~(ETH_DMAOMR_ST | ETH_DMAOMR_SR); //clear start/stop transmit and receive flags
	heth.Instance->DMABMR |= (ETH_DMABMR_SR); //set software reset flag
	while (heth.Instance->DMABMR & ETH_DMABMR_SR) {
		//wait
	}

	volatile HAL_StatusTypeDef ethInit=HAL_ETH_Init(&heth);
	volatile HAL_StatusTypeDef ethStartIt=0x04;
	if (netif_is_up(&gnetif) && netif_is_link_up(&gnetif)) {
		ethStartIt=HAL_ETH_Start_IT(&heth);
	}
}

 

Screenshot from RM0410 documentScreenshot from RM0410 document

 

EDIT 1: Spelling mistakes.

LCE
Principal II
February 2, 2026

Working a) without RTOS, b) H723, and c) only as TCP server here, so I don't know if that helps.

Usually lwip has a function called something like Ethernet_Link_Periodic_Handle().

I have it in LwIpProcess().

This checks periodically the PHY if it's still connected, then calls ethernetif_update_config() if necessary, which was set as netif->link_callback. Only used if LWIP_NETIF_LINK_CALLBACK is set in some lwip opt.h file.

ethernetif_update_config() re-inits the ETH peripheral if it's up, or stops the peripheral (Tx & RX stop, flush FIFOs, disable state machine).

At least here with server only functions, it works like a charm.
IDK if that helps if the STM32 is the client.

_AdamNtrx
_AdamNtrxAuthor
Associate III
February 3, 2026

Could you please share ethernetif_update_config() function's body here? I generated new STM32 project with LwIP and without FreeRTOS and there is no ethernetif_update_config(), only ethernet_link_check_state() which exists in the same form in my project but as a separate thread.

LCE
Principal II
February 3, 2026

in ethernetif.c:

#if LWIP_NETIF_LINK_CALLBACK

/**
 * @brief Link callback function, this function is called on change of link status
 * to update low level driver configuration.
 * @PAram pNetif: The network interface
 * @retval None
 */

void ethernetif_update_config(struct netif *pNetIf)
{
	if( netif_is_link_up(pNetIf) )
	{
	/* Restart the auto-negotiation */
		/* PHY settings and readback done in MAC init */

		/* ETHERNET MAC Re-Configuration */
		EthMacInit();

		/* Restart MAC interface */
		EthStartIT();
	}
	else
	{
		/* Stop MAC interface */
		EthStop();
	}

	ethernetif_notify_conn_changed(pNetIf);
}


#endif /* LWIP_NETIF_LINK_CALLBACK */
_AdamNtrx
_AdamNtrxAuthor
Associate III
February 3, 2026

Is this code generated by STM32CubeMX? I created new project for STM32H723ZGTx MCU and it doesn't have functions You have.

Associate III
February 3, 2026

When generating code for LWIP, only ethernetif.c is out-of-the-box working. lwip.c, where you write the application layer functions, which you later call from freertos.c, is nothing useful as it comes from CubeMX. I implemented funtions for DHCP, the functions to connect, reconnect and disconnect as well as a few tweaks to stack sizes in my lwip.c.

In generel, go to the github of you MCU and copy the pieces of that what you want to achieve. Be aware trhat you need to decide first, which API you want to use, I am personally a fan of Netconn API.

Feel free to ask further questions!

 

Best regards

LCE
Principal II
February 3, 2026

But as I said, I have no idea how lwip handles being a TCP client when disconnecting.

_AdamNtrx
_AdamNtrxAuthor
Associate III
February 9, 2026

I still wasn't able to solve my problem. I have to wait for watchdog reset when Ethernet DMA error appears. Also netconn_connect() function sometimes returns ERR_MEM  due to no memory available for enqueueing the SYN segment. If anybody has solution for that, I would be thankful for sharing it here.