cancel
Showing results for 
Search instead for 
Did you mean: 

Set ethernet MAC Config in STM32H573 DK

jishnu1234
Associate II

Hi

Im trying to set the speed for ethernet to 10Mbps, using

HAL_ETH_SetMACConfig()
static void MX_ETH_Init(void)
{

  /* USER CODE BEGIN ETH_Init 0 */

  /* USER CODE END ETH_Init 0 */

   static uint8_t MACAddr[6];

  /* USER CODE BEGIN ETH_Init 1 */

  /* USER CODE END ETH_Init 1 */
  heth.Instance = ETH;
  MACAddr[0] = 0x00;
  MACAddr[1] = 0x80;
  MACAddr[2] = 0xE1;
  MACAddr[3] = 0x00;
  MACAddr[4] = 0x00;
  MACAddr[5] = 0x00;
  heth.Init.MACAddr = &MACAddr[0];
  heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
  heth.Init.TxDesc = DMATxDscrTab;
  heth.Init.RxDesc = DMARxDscrTab;
  heth.Init.RxBuffLen = 1536;

  /* USER CODE BEGIN MACADDRESS */

  /* USER CODE END MACADDRESS */

  if (HAL_ETH_Init(&heth) != HAL_OK)
  {
    Error_Handler();
  }

  memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfigTypeDef));
  TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
  /* USER CODE BEGIN ETH_Init 2 */
  if (HAL_ETH_GetMACConfig(&heth, &MacConfig) != HAL_OK) {
    Error_Handler();
  }

  MacConfig.Speed = ETH_SPEED_10M;
  MacConfig.DuplexMode = ETH_FULLDUPLEX_MODE; // Set duplex mode to full duplex
  if (HAL_ETH_SetMACConfig(&heth, &MacConfig) != HAL_OK) {
    Error_Handler();
  }

  /* USER CODE END ETH_Init 2 */
}

This does not seem to set the speed to 10Mbps.

jishnu1234_0-1728395467984.png

Is there anything I'm missing?



1 ACCEPTED SOLUTION

Accepted Solutions
jishnu1234
Associate II

I was able to get the speed to 10Mbps by modifying
static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) in nx_stm32_eth_driver.c

if (nx_eth_phy_init() != ETH_PHY_STATUS_OK)
  {
    driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    return;
  }
  // set to 10 mbps
  if (nx_eth_phy_set_link_state(LAN8742_STATUS_10MBITS_FULLDUPLEX) !=
      LAN8742_STATUS_OK) {
    return;
  }
  // wait till link is up
  while (nx_eth_phy_get_link_state() <= ETH_PHY_STATUS_LINK_DOWN) {
    ;
  }
  // get state to check
  PHYLinkState = nx_eth_phy_get_link_state();

Is this the best way to do this? Is the ethernet driver supposed to be modified by others?

View solution in original post

8 REPLIES 8
STea
ST Employee

Hello  @jishnu1234 ,


make sure you have the correct pc configuration:

1.Configure TCP/IPv4 address as 192.168.1.1 at wired ethernet adapter property

2.Open Device Manager>Network adapters>Ethernet Adapter(ex."Intel(R) Ethernet Connection (4) I219-LM")

3.Select "Advanced" tab and select "Speed & Duplex" from drop down menu of "Property"

4.Select "10 Mbps Full Duplex" from drop down menu of "Value 

and check the return value of PHYLinkState = LAN8742_GetLinkState(&LAN8742); making sure that your configuration is properly set also check if thee auto-negotiation feature is enabled.
you should have something similar to this:

 /* Set PHY IO functions */
  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  LAN8742_Init(&LAN8742);

  if (hal_eth_init_status == HAL_OK)
  {
    PHYLinkState = LAN8742_GetLinkState(&LAN8742);

    /* Get link state */
    if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN)
    {
      netif_set_link_down(netif);
      netif_set_down(netif);
    }
    else
    {
      switch (PHYLinkState)
      {
      case LAN8742_STATUS_100MBITS_FULLDUPLEX:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      case LAN8742_STATUS_100MBITS_HALFDUPLEX:
        duplex = ETH_HALFDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      case LAN8742_STATUS_10MBITS_FULLDUPLEX:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_10M;
        break;
      case LAN8742_STATUS_10MBITS_HALFDUPLEX:
        duplex = ETH_HALFDUPLEX_MODE;
        speed = ETH_SPEED_10M;
        break;
      default:
        duplex = ETH_FULLDUPLEX_MODE;
        speed = ETH_SPEED_100M;
        break;
      }

    /* Get MAC Config MAC */
    HAL_ETH_GetMACConfig(&heth, &MACConf);
    MACConf.DuplexMode = duplex;
    MACConf.Speed = speed;
    HAL_ETH_SetMACConfig(&heth, &MACConf);

    HAL_ETH_Start_IT(&heth);

Regards

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi

Thanks for the reply. Why should the NIC on the PC be set to 10Mbps? Shouldn't the device auto negotiate by itself to 10Mbps after MACConfig is set? Maybe I'm wrong but wouldn't this situation work:

Ethernet NIC on PC (Auto Negotiate) <-> STM32H5 (10Mbps full duplex)

Shouldn't this cause the NIC to set speed automatically as 10Mbps instead of manually setting it in the NIC ?

 

LCE
Principal

I think you must tell the PHY to turn off auto-negotiation and set it to 10 / FD (and the STM32 MAC).

Check the PHY datasheet, I think auto-negotiation is on by default.

Guillaume K
ST Employee

Hi

The component responsible for the link speed is the external PHY (LAN8742 on most ST boards).

The STM32 Ethernet MAC is just configured afterwards, depending from what speed was selected in the PHY.

It seems that by default the LAN8742 is configured for auto negotiation.

I guess if you want to force a specific speed you could configure the PHY to disable auto negotiation and select 10Mbps. Using BSP component functions LAN8742_SetLinkState().

I found nx_eth_phy_set_link_state()  which sets the speed. But not sure where to call it from. Calling it in _nx_driver_enable() sets the link down for some reason. Is there no way to set this in CubeMX ?

jishnu1234
Associate II

I was able to get the speed to 10Mbps by modifying
static VOID _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr) in nx_stm32_eth_driver.c

if (nx_eth_phy_init() != ETH_PHY_STATUS_OK)
  {
    driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    return;
  }
  // set to 10 mbps
  if (nx_eth_phy_set_link_state(LAN8742_STATUS_10MBITS_FULLDUPLEX) !=
      LAN8742_STATUS_OK) {
    return;
  }
  // wait till link is up
  while (nx_eth_phy_get_link_state() <= ETH_PHY_STATUS_LINK_DOWN) {
    ;
  }
  // get state to check
  PHYLinkState = nx_eth_phy_get_link_state();

Is this the best way to do this? Is the ethernet driver supposed to be modified by others?

LCE
Principal

Is the ethernet driver supposed to be modified by others?

The HAL drivers usually have lots of options - but not all. So why not?

Just be careful with any Cube / HAL updates...

STea
ST Employee

Hello @LCE & @jishnu1234 ,

the nx_stm32_eth_driver.c is not part of The HAL cube environment but is a port specific file for Netxduo and it is based on a generic template that can be modified according to the needs so no problems with Updates on this side.

Regards

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.