cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Ethernet interrupt not triggering for up to 1500 ms after random period of time.

Quibi
Associate II

Hey,

After debugging for a long time I still haven't been able to find the cause of ethernet interrupt not triggering for up to 1500 ms.

What I'm doing is opening a socket on my STM32F4 + LAN8742A. I am running a script that sends an "heartbeat" every 50 ms from my machine, however after a random period of time (20 minutes to sometimes 2 hours) a few heartbeats fails to receive.

I've noticed by resetting a timer in HAL_ETH_IRQHandler that the IRQhandler doesn't get called during the time that the heartbeats fail to receive.

The error callback is not being called either.

What I've tried to fix this issue:

  • Clean project with only TCP/IP + RTOS + CMSIS1
  • Fixed the Physical configuration
  • Checking for errors/dma errors.
  • Increasing/decreasing NVIC priority
  • Sending heartbeats from a different machine / microcontroller
  • Disabling MMC interrupts
  • Updating CubeMX + firmware

The issues occur on a Nucleo f429ZI as well as our custom board so I assume it's not something hardware related.

Any help/tips that would help finding the cause of this problem would be appreciated.

8 REPLIES 8
LCE
Principal

Have you compared the external PHY settings with the STM internal MAC settings?

I had some trouble on a F7 with the STM HAL reading back a wrong config register of the PHY.

That lead to collisions, because the PHY was set to full duplex, but the MAC to half duplex because of the wrong PHY register reading.

in F7 hal_eth.c "PHY_SR" is the wrong register to check the LAN8742's status:

/* Read the result of the auto-negotiation */

if((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK)

It must be register PHY_SSR at address 31d.

And stop relying on that Cube / HAL stuff.

If you're doing some serious work, you have to check every line of that Cube / HAL functions. And then you'll find you can do a lot of things better and faster. And sometimes just get it working.

LCE
Principal

... and :

  • use wireshark to see what's happening.
  • check the PHY's status registers for errors
  • and the RX descriptors for errors
  • and you could try to poll the RX registers instead of using the interrupt
Quibi
Associate II

After reading the phy's status registers it seems I often get a "Link down" and "Extended status".

I've also checked the addresses of the registers and the auto neg register you mentioned which isn't a bug in the latest STM32F4 firmware.

The datasheet points to register 15 for extended status but there doesn't seem to be a register 15? I probably miss something as low level TCP/IP debugging is new to me. Thanks for your help, I will try your other points as well.

(Also, it seems that ST isn't even using the configuration generated by cubeMX, instead it uses the config located in lan8742.h. Guess you were right about not relying on Cube)

LCE
Principal

Here are the PHY registers when my stuff is working:

PHY (LAN8742A) registers:
PHY reg 00d:    1100
 
PHY_REG_BCR:    1100 @ 0
         Loopback OFF
         Auto-negotiation ON
         Power ON
         Isolate OFF
PHY_REG_BSR:    782D @ 1
         Link Status UP
        connection abilities:
         100BASE-TX full duplex
         100BASE-TX half duplex
         10BASE-T half duplex
         10BASE-T half duplex
         Auto-negotiation  possible,  completed
         Extended Capabilities supported (?)
PHY_REG_SSR:    1058 @ 31
         Auto-negotiation DONE
         Speed indication: 100BASE-TX full-duplex

PHY_REG_SSR is the important one to check if PHY setup was okay.

Here's my UART source:

	uart_printf("PHY (LAN8742A) registers:\n\r");
	sscanf((char *)u8Uart3RxBuf, "cr Ep %lu", &u32RegAddr);
	if( u32RegAddr > 31 ) u32RegAddr = 0;
 
/* Read PHY Register */
	HAL_ETH_ReadPHYRegister(&hgEth, u32RegAddr , &u32Val);
	uart_printf("PHY reg %02lud:\t%04lX\n\r\n\r", u32RegAddr, u32Val);
 
/* Read PHY Register Configuration */
	HAL_ETH_ReadPHYRegister(&hgEth, PHY_REG_BCR , &u32Val);
	uart_printf("PHY_REG_BCR:\t%04lX @ %d\n\r", u32Val, PHY_REG_BCR);
 
		uart_printf("\t Loopback ");
		if( u32Val & PHY_REG_BCR_LOOPBACK ) uart_printf("ON\n\r");
		else uart_printf("OFF\n\r");
		uart_printf("\t Auto-negotiation ");
		if( u32Val & PHY_REG_BCR_AUTONEGEN ) uart_printf("ON\n\r");
		else
		{
			uart_printf("OFF\n\r");
			uart_printf("\t -> Speed Select ");
			if( u32Val & PHY_REG_BCR_SPSEL100M ) uart_printf("100M\n\r");
			else uart_printf("10M\n\r");
			uart_printf("\t -> Duplex Mode ");
			if( u32Val & PHY_REG_BCR_DUPLMODE ) uart_printf("FULL\n\r");
			else uart_printf("HALF\n\r");
		}
		uart_printf("\t Power ");
		if( u32Val & PHY_REG_BCR_PWRDWN ) uart_printf("DOWN\n\r");
		else uart_printf("ON\n\r");
		uart_printf("\t Isolate ");
		if( u32Val & PHY_REG_BCR_ISOLATE ) uart_printf("ON\n\r");
		else uart_printf("OFF\n\r");
 
	HAL_ETH_ReadPHYRegister(&hgEth, PHY_REG_BSR , &u32Val);
	uart_printf("PHY_REG_BSR:\t%04lX @ %d\n\r", u32Val, PHY_REG_BSR);
 
		uart_printf("\t Link Status ");
		if( u32Val & PHY_REG_BSR_LINK_STATUS ) uart_printf("UP\n\r");
		else uart_printf("DOWN\n\r");
 
		uart_printf("\tconnection abilities:\n\r");
		if( u32Val & PHY_REG_BSR_100_T4 ) 		uart_printf("\t 100BASE-T4\n\r");
		if( u32Val & PHY_REG_BSR_100TX_FULL ) 	uart_printf("\t 100BASE-TX full duplex\n\r");
		if( u32Val & PHY_REG_BSR_100TX_HALF ) 	uart_printf("\t 100BASE-TX half duplex\n\r");
		if( u32Val & PHY_REG_BSR_10T_FULL ) 	uart_printf("\t 10BASE-T half duplex\n\r");
		if( u32Val & PHY_REG_BSR_10T_HALF ) 	uart_printf("\t 10BASE-T half duplex\n\r");
		if( u32Val & PHY_REG_BSR_100T2_FULL ) 	uart_printf("\t 100BASE-T2 full duplex\n\r");
		if( u32Val & PHY_REG_BSR_100T2_HALF ) 	uart_printf("\t 100BASE-T2 half duplex\n\r");
 
		if( u32Val & PHY_REG_BSR_EXTREG15 ) uart_printf("\t Ext status info in reg 15 (?)\n\r");
 
		uart_printf("\t Auto-negotiation ");
		if( u32Val & PHY_REG_BSR_AUTONEG_ABL )
		{
			uart_printf(" possible, ");
			if( u32Val & PHY_REG_BSR_AUTONEGDONE ) uart_printf(" completed\n\r");
			else uart_printf("NOT completed\n\r");
		}
		else uart_printf("NOT able\n\r");
 
		if( u32Val & PHY_REG_BSR_REM_FAULT ) uart_printf("\t Remote fault condition detected\n\r");
		if( u32Val & PHY_REG_BSR_JABBER_DTCT ) uart_printf("\t Jabber condition detected\n\r");
		if( u32Val & PHY_REG_BSR_EXT_ABLT ) uart_printf("\t Extended Capabilities supported (?)\n\r");
 
	HAL_ETH_ReadPHYRegister(&hgEth, PHY_REG_SSR , &u32Val);
	uart_printf("PHY_REG_SSR:\t%04lX @ %d\n\r", u32Val, PHY_REG_SSR);
 
		uart_printf("\t Auto-negotiation ");
		if( u32Val & PHY_REG_SSR_AUTODONE ) uart_printf("DONE\n\r");
		else uart_printf("NOT done - # ERR\n\r");
		uart_printf("\t Speed indication: ");
		if( u32Val & PHY_REG_SSR_SPD_10M ) 		 uart_printf("10BASE-T ");
		else if( u32Val & PHY_REG_SSR_SPD_100M ) uart_printf("100BASE-TX ");
		else uart_printf("??? BASE-T ");
		if( u32Val & PHY_REG_SSR_DUPL_FULL ) uart_printf("full-duplex\n\r");
		else  uart_printf("half-duplex\n\r");

And here the defines:

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* PHY registers */
#define PHY_REG_BCR				(uint16_t)0			/* PHY Basic Control Register */
#define PHY_REG_BSR				(uint16_t)1			/* PHY Basic Status Register */
#define PHY_REG_SSR				(uint16_t)31		/* PHY Special Status Register */
 
/* PHY_REG_BCR - Basic Control Register bits */
#define PHY_REG_BCR_SOFTRESET		((uint32_t)1 << 15)		/* Soft Reset bit 15 */
#define PHY_REG_BCR_LOOPBACK		((uint32_t)1 << 14)		/* Loopback bit 14 */
#define PHY_REG_BCR_SPSEL100M		((uint32_t)1 << 13)		/* Speed Select bit 13 */
#define PHY_REG_BCR_AUTONEGEN		((uint32_t)1 << 12)		/* Auto-Negotiation Enable bit 12 */
#define PHY_REG_BCR_PWRDWN			((uint32_t)1 << 11)		/* Power Down bit 11 */
#define PHY_REG_BCR_ISOLATE			((uint32_t)1 << 10)		/* Electrical isolation of PHY from the RMII bit 10 */
#define PHY_REG_BCR_RESTARTAN		((uint32_t)1 <<  9)		/* Restart Auto-Negotiate */
#define PHY_REG_BCR_DUPLMODE		((uint32_t)1 <<  8)		/* Duplex Mode bit 8 */
 
/* PHY_REG_BSR - Basic Status Register bits */
#define PHY_REG_BSR_100_T4			((uint32_t)1 << 15)		/* 100BASE-T4 bit 15 */
#define PHY_REG_BSR_100TX_FULL		((uint32_t)1 << 14)		/* 100BASE-TX Full Duplex bit 14 */
#define PHY_REG_BSR_100TX_HALF		((uint32_t)1 << 13)		/* 100BASE-TX Half Duplex bit 13 */
#define PHY_REG_BSR_10T_FULL		((uint32_t)1 << 12)		/* 10BASE-T Full Duplex bit 12 */
#define PHY_REG_BSR_10T_HALF		((uint32_t)1 << 11)		/* 10BASE-T Half Duplex bit 11 */
#define PHY_REG_BSR_100T2_FULL		((uint32_t)1 << 10)		/* 100BASE-T2 Full Duplex bit 10 */
#define PHY_REG_BSR_100T2_HALF		((uint32_t)1 <<  9)		/* 100BASE-T2 Half Duplex bit 9 */
 
#define PHY_REG_BSR_EXTREG15		((uint32_t)1 <<  8)		/* Extended status information in register 15 */
#define PHY_REG_BSR_AUTONEGDONE		((uint32_t)1 <<  5)		/* Auto-negotiate process completed */
#define PHY_REG_BSR_REM_FAULT		((uint32_t)1 <<  4)		/* Remote fault condition detected */
#define PHY_REG_BSR_AUTONEG_ABL		((uint32_t)1 <<  3)		/* Auto-Negotiate Ability */
#define PHY_REG_BSR_LINK_STATUS		((uint32_t)1 <<  2)		/* Link Status */
#define PHY_REG_BSR_JABBER_DTCT		((uint32_t)1 <<  1)		/* Jabber Detect */
#define PHY_REG_BSR_EXT_ABLT		((uint32_t)1 <<  0)		/* Extended Capabilities */
 
/* PHY_REG_SSR - Special Status Register bits */
#define PHY_REG_SSR_AUTODONE	((uint32_t)1 << 12)		/* AUTODONE bit 12 */
#define PHY_REG_SSR_SPD_10M		((uint32_t)1 <<  2)		/* Speed Indication, bits 4:2 */
#define PHY_REG_SSR_SPD_100M	((uint32_t)1 <<  3)		/* Speed Indication, bits 4:2 */
#define PHY_REG_SSR_DUPL_FULL	((uint32_t)1 <<  4)		/* Speed Indication, bits 4:2 */

LCE
Principal

Good luck, it's really complex stuff, combined with lwIP.

Bob S
Principal

Yeah - there is no "extended status" register in the LAN8742A, bit 8 of the basic status reg indicates that (that bit is zero).

BTW - The older CubeMX (ver 6.3 and 6.5, I haven't tried 6.6 or 6.7, nor the new "fixed" Cube ethernet driver) refers to "Externded External PHY Configuration) register at address 0x10. That is actually the PHY Special Control/Status" register at address 31 (0x1f). They also default to wrong values for some of the bit fields in that register. Make sure you have the correct settings there.

Quibi
Associate II

The odd thing is that the 8th bit sometimes returns high.

Also the Physical Ethernet configuration saved to stm32fx_hal_conf which is generated by CubeMX isn't being used at all (I am not sure if this is the case in the previous versions of CubeMX as I am using the latest one) So it does not matter what values I put into CubeMX. Instead it uses the lan8742.h defines (Which I checked and seem to match the datasheet).

Piranha
Chief II

https://community.st.com/s/question/0D50X0000BOtfhnSQB/how-to-make-ethernet-and-lwip-working-on-stm32

Fix everything and it will work! But one cannot do it by clicking CubeMX...