Showing results for 
Search instead for 
Did you mean: 

STM32H7 Ethernet transmission comes to halt, eventually related to TX queue underflow interrupt?

Kolja Waschk
Associate III


I experience strange behaviour with the just reworked H7 ethernet driver in STM32H725 with LwIP + FreeRTOS environment. A continuous transmission of UDP frames (bursts of 3..4 frames every ~ 50 ms) comes to halt after just a few successful loops. The "heth.gState" changes to HAL_ETH_STATE_BUSY and remains so forever.

Interestingly, I added some lines of debug code that reads the MAC register contents just before calling HAL_ETH_Transmit_IT() in LwIP low_level_output() for later comparison, and the halting didn't occur anymore. The access can be further reduced to a single read access to the MAC MTLRQDR (Offset 0x0D38) and it still runs.. but without that particular register access, output reproducibly halts.

The MTLRQDR register by the way changes from 0 (first read) to 1 (second read) in approximately that moment where the halting otherwise would occur (but that's just an assumption, because reading it changes the behaviour).

Now I have two questions:

  • Why does reading that register change anything?
  • If there is an actual TX underflow, what might be the cause and what can I do against it?

My code uses the stm32h7xx_hal_eth.c driver and adapted ethernetif.c (from STM32CubeH7/Projects/NUCLEO-H723ZG/Applications/LwIP/LwIP_HTTP_Server_Socket_RTOS)

Thanks for your ideas and help in advance!


Kolja Waschk
Associate III

The behaviour changes as I further add or remove debug code. Might as well be timing related, but I'm running out of ideas currently. Sometimes even with the read access the MAC stalls. I double-double checked the MPU settings and placement of descriptors as documented in the various H7 ETH MAC postings and believe they're good now.. but there must be something still wrong.

Kolja Waschk
Associate III

Never mind.. the static "heth" structure in my system sometimes wasn't all zero at startup before low_level_init() (which doesn't zero its contents either). So the success of the initialization and everything after was dependent on some prior state (and this was dependent on placement of the heth somewhere in memory).



How many buffers you have for transmitting?

Drivers increment DMACTDTPR without checking who own next buffer. Head == Tail and DMA stopped.