At least I found the cause of the late collision error:
It's the HAL / Cube setting up of the LAN8742, rather the reading of the PHY settings.
I used the "old" STM32F7 Cubae HAL stuff for setting this up - the last part remaining where I use HAL / Cube for ethernet...
It's reading back the wrong PHY register, and then sets its own duplex mode wrongly in MACCR.
Aaaaaarrrghhh....!
I found that because www told me that the most probable cause for the late collision error is that one side has the wrong duplex mode set.
Then I found that someone in another forum complained about the wrong register reading in HAL / Cube for LAN8742.
Here's the wrong and corrected version from stm32f7xx_hal_eth.c :
I hope that and the code above might help other people.
#define PHY_REGNEW_SSR (uint16_t)31 /* PHY Special Status Register */
#define PHY_REGNEW_SSR_SPD_100M ((uint32_t)1 << 3) /* Speed Indication, bits 4:2 */
#define PHY_REGNEW_SSR_DUPL_FULL ((uint32_t)1 << 4) /* Speed Indication, bits 4:2 */
#if( 0 )
/* 2022-10-01
* HAL reading back wrong register for status of LAN8742!
*/
/* WRONG */
/* Read the result of the auto-negotiation */
if((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK)
{
/* In case of write timeout */
err = ETH_ERROR;
/* Config MAC and DMA */
ETH_MACDMAConfig(heth, err);
/* Set the ETH peripheral state to READY */
heth->State = HAL_ETH_STATE_READY;
/* Return HAL_ERROR */
return HAL_ERROR;
}
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
if((phyreg & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
{
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
}
else
{
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
(heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX;
}
/* Configure the MAC with the speed fixed by the auto-negotiation process */
if((phyreg & PHY_SPEED_STATUS) == PHY_SPEED_STATUS)
{
/* Set Ethernet speed to 10M following the auto-negotiation */
(heth->Init).Speed = ETH_SPEED_10M;
}
else
{
/* Set Ethernet speed to 100M following the auto-negotiation */
(heth->Init).Speed = ETH_SPEED_100M;
}
#else
/* CORRECT */
/* Read the result of the auto-negotiation */
if( HAL_ETH_ReadPHYRegister(heth, PHY_REGNEW_SSR, &phyreg) != HAL_OK )
{
/* In case of write timeout */
err = ETH_ERROR;
/* Config MAC and DMA */
ETH_MACDMAConfig(heth, err);
/* Set the ETH peripheral state to READY */
heth->State = HAL_ETH_STATE_READY;
/* Return HAL_ERROR */
return HAL_ERROR;
}
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
if( phyreg & PHY_REGNEW_SSR_DUPL_FULL )
{
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
}
else
{
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
(heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX;
}
/* Configure the MAC with the speed fixed by the auto-negotiation process */
if( phyreg & PHY_REGNEW_SSR_SPD_100M )
{
/* Set Ethernet speed to 100M following the auto-negotiation */
(heth->Init).Speed = ETH_SPEED_100M;
}
else
{
/* Set Ethernet speed to 10M following the auto-negotiation */
(heth->Init).Speed = ETH_SPEED_10M;
}
#endif