2026-06-02 3:03 AM - edited 2026-06-02 4:02 AM
Hi,
I working with nucleo-h563zi.
I try to use MDIO as Clause 45, copy HAL_ETH_WritePHYRegister, HAL_ETH_ReadPHYRegister and change it's to fit for Clause 45.
#define ETH_MACMDIOAR_MOC_ADD_Pos (2U)
#define ETH_MACMDIOAR_MOC_ADD_Msk (0x0UL << ETH_MACMDIOAR_MOC_ADD_Pos) /*!< 0x00000000 */
#define ETH_MACMDIOAR_MOC_ADD ETH_MACMDIOAR_MOC_ADD_Msk /* Write */
#define ETH_MACMDIOAR_MOC_WR_Pos (2U)
#define ETH_MACMDIOAR_MOC_WR_Msk (0x1UL << ETH_MACMDIOAR_MOC_WR_Pos) /*!< 0x00000004 */
#define ETH_MACMDIOAR_MOC_WR ETH_MACMDIOAR_MOC_WR_Msk /* Write */
#define ETH_MACMDIOAR_MOC_RD_ADD_Pos (2U)
#define ETH_MACMDIOAR_MOC_RD_ADD_Msk (0x2UL << ETH_MACMDIOAR_MOC_RD_ADD_Pos) /*!< 0x00000008 */
#define ETH_MACMDIOAR_MOC_RD_ADD ETH_MACMDIOAR_MOC_RD_ADD_Msk /* read + addres */
#define ETH_MACMDIOAR_MOC_RD_Pos (2U)
#define ETH_MACMDIOAR_MOC_RD_Msk (0x3UL << ETH_MACMDIOAR_MOC_RD_Pos) /*!< 0x0000000C */
#define ETH_MACMDIOAR_MOC_RD ETH_MACMDIOAR_MOC_RD_Msk /* Read */
/**
* @brief Reads a PHY register using Clause-45 MDIO.
* @PAram heth: pointer to ETH handle
* @PAram PHYAddr: PHY port address (0-31)
* @PAram PHYReg: combined device/register address (devad in [20:16], reg in [15:0])
* @PAram pRegValue: pointer to store the 16-bit read value
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ETH_ReadPHYRegister_Clause45(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg,
uint32_t *pRegValue)
{
uint32_t tickstart;
uint32_t tmpreg;
if (pRegValue == NULL || heth == NULL) {
return HAL_ERROR;
}
uint32_t devaddr = (PHYReg >> 16U) & 0x1FU; /* device address (DEVAD) */
uint32_t regaddr = PHYReg & 0xFFFFU; /* register address */
/* Check for the Busy flag */
if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET)
{
return HAL_ERROR;
}
/* Write register address into MACMDIODR RA field for Clause-45 */
WRITE_REG(heth->Instance->MACMDIODR, (regaddr << 16U));
/* Get the MACMDIOAR value */
WRITE_REG(tmpreg, heth->Instance->MACMDIOAR);
/* Prepare the MDIO Address Register value
- Set the PHY device address
- Set the device type (RDA field = devaddr for C45)
- Set the read mode
- Set C45E bit
- Set the MII Busy bit */
MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21));
MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (devaddr << 16));
MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD_ADD);
SET_BIT(tmpreg, ETH_MACMDIOAR_C45E);
SET_BIT(tmpreg, ETH_MACMDIOAR_MB);
/* Write the result value into the MDIO Address register */
WRITE_REG(heth->Instance->MACMDIOAR, tmpreg);
tickstart = HAL_GetTick();
/* Wait for the Busy flag */
while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U)
{
if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT))
{
return HAL_ERROR;
}
}
/* Get MACMDIODR value */
WRITE_REG(*pRegValue, heth->Instance->MACMDIODR);
printf("HAL_ETH_ReadPHYRegister_Clause45: val=0x%08lX\n\r", *pRegValue);
return HAL_OK;
}
/**
* @brief Writes a PHY register using Clause-45 MDIO.
* @PAram heth: pointer to ETH handle
* @PAram PHYAddr: PHY port address (0-31)
* @PAram PHYReg: combined device/register address (devad in [20:16], reg in [15:0])
* @PAram RegValue: 16-bit value to write
* @retval HAL status
*/
HAL_StatusTypeDef HAL_ETH_WritePHYRegister_Clause45(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg,
uint32_t RegValue)
{
uint32_t tickstart;
uint32_t tmpreg;
if (heth == NULL) {
return HAL_ERROR;
}
uint32_t devaddr = (PHYReg >> 16U) & 0x1FU; /* device address */
uint32_t regaddr = PHYReg & 0xFFFFU; /* register address */
/* Check for the Busy flag */
if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET)
{
return HAL_ERROR;
}
/* Get the MACMDIOAR value */
WRITE_REG(tmpreg, heth->Instance->MACMDIOAR);
/* Prepare the MDIO Address Register value */
MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21));
MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (devaddr << 16));
MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR);
SET_BIT(tmpreg, ETH_MACMDIOAR_C45E);
SET_BIT(tmpreg, ETH_MACMDIOAR_MB);
/* Give the value to the MII data register (RA + MD for C45) */
WRITE_REG(heth->Instance->MACMDIODR, (regaddr << 16U) | (uint16_t)RegValue);
/* Write the result value into the MII Address register */
WRITE_REG(heth->Instance->MACMDIOAR, tmpreg);
tickstart = HAL_GetTick();
/* Wait for the Busy flag */
while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U)
{
if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT))
{
return HAL_ERROR;
}
}
return HAL_OK;
} Write function working well, but read function don't get any data in heth->Instance->MACMDIODR.
This is the print that i get "HAL_ETH_ReadPHYRegister_Clause45: val=0x00070000" ,
but its need to be "HAL_ETH_ReadPHYRegister_Clause45: val=0x00070100"
Can see in the photo below
This photo is from logic that connected in PA2(MDIO),PC1(MDC)
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.