cancel
Showing results for 
Search instead for 
Did you mean: 

How to configure external Ethernet PHY?

_AdamNtrx
Associate III

I have a custom board that uses STM32F746VGT6 MCU and 1894K-33LF Ethernet IC. I have an old STM32CubeIDE project that allows to configure Ethernet parameters (such as duplex mode, speed, autonegotiation) from internal MX configurator. Generating new code with MX changes the libraries to newer version that differ significantly in how Ethernet and PHY are initialised. Also it's not possible to configure as many Ethernet parameters as before.

 

How to configure external Ethernet PHY with newer libraries?

1 ACCEPTED SOLUTION

Accepted Solutions
_AdamNtrx
Associate III

So I figured this out. To communicate with PHY device, one needs to use

HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t *pRegValue)

and

HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t RegValue)

functions. The PHY address in ICS1894-33 I am using depends on the state of P0, P1, P2 and P3 pins during reset or power-up. I have high state on P0 and low on P1, P2 and P3 and therefore my PHY address is 0b001. This means that to read my PHY device's registers I need to use code:

	  uint32_t phyRegs[32]={0x0000};
	  for (uint8_t i=0; i<32; i++) {
		if ( HAL_ETH_ReadPHYRegister(&heth, 0b0001, i, phyRegs+i) != HAL_OK) {
			asm("NOP");
		}
	  }

 
Since the ICS1894-33's pins are connected on my PCB in such a way that autonegotiation enabled, my initialisation process in low_level_init() in ethernetif.c file looks like this:

/* USER CODE BEGIN low_level_init Code 1 for User BSP */

    HAL_ETH_MspInit(&heth);
    HAL_ETH_Start(&heth);
	netif_set_up(netif);
	netif_set_link_up(netif);

/* USER CODE END low_level_init Code 1 for User BSP */

 

There is a bug in STM32CubeIDE that prevents HAL_ETH_MspInit() from being generated when BSP module in LwIP tab in STM32CubeMX is not selected. I had to select it, generate code, copy HAL_ETH_MspInit() function, then uncheck the BSP module in LwIP tab and paste the copied code.

View solution in original post

3 REPLIES 3
Pavel A.
Super User

There are many external PHYs (some of them are even multi-port bridges or switches) so it is not reasonable to configure a PHY in the GUI. Just replace the generated PHY code to your own. "Drivers" for some PHYs are on the github:

https://github.com/STMicroelectronics/stm32-lan8742

https://github.com/STMicroelectronics/stm32-rtl8211

Here you can find more help for adapting you project to a custom PHY.

 

_AdamNtrx
Associate III

So I figured this out. To communicate with PHY device, one needs to use

HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t *pRegValue)

and

HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, uint32_t RegValue)

functions. The PHY address in ICS1894-33 I am using depends on the state of P0, P1, P2 and P3 pins during reset or power-up. I have high state on P0 and low on P1, P2 and P3 and therefore my PHY address is 0b001. This means that to read my PHY device's registers I need to use code:

	  uint32_t phyRegs[32]={0x0000};
	  for (uint8_t i=0; i<32; i++) {
		if ( HAL_ETH_ReadPHYRegister(&heth, 0b0001, i, phyRegs+i) != HAL_OK) {
			asm("NOP");
		}
	  }

 
Since the ICS1894-33's pins are connected on my PCB in such a way that autonegotiation enabled, my initialisation process in low_level_init() in ethernetif.c file looks like this:

/* USER CODE BEGIN low_level_init Code 1 for User BSP */

    HAL_ETH_MspInit(&heth);
    HAL_ETH_Start(&heth);
	netif_set_up(netif);
	netif_set_link_up(netif);

/* USER CODE END low_level_init Code 1 for User BSP */

 

There is a bug in STM32CubeIDE that prevents HAL_ETH_MspInit() from being generated when BSP module in LwIP tab in STM32CubeMX is not selected. I had to select it, generate code, copy HAL_ETH_MspInit() function, then uncheck the BSP module in LwIP tab and paste the copied code.

Pavel A.
Super User

Do you call netif_set_link_up(netif)  unconditionally? What if the cable is not connected? Do you want to support 10 Mbps cabling?

IIRC HAL_ETH_Start should be called only when you know the concrete link parameters (speed, duplex). When the parameters change, ETH should be restarted. With DHCP there will be two loops (or state machines): 

1 Link state: disconnected -> wait for change -> detect speed & duplex -> call  HAL_ETH_Start, call netif_set_link_up -> wait for change...

2. DHCP, considering the link state (cannot send requests and expect replies when link down. Drop assigned address & acquire again when the link goes up...).