Details: STM32CubeMX v4.22.1, firmware library for the STM32F7xxx family v1.8.0.
Created project for SW4STM32 using (nearly) default pin configuration for the Nucleo-144 with STM32F767ZI (rev Z).
If it matters, the project is configured to generate files for AC6 (sw4stm32).
The code generated in "Src/main.c" has some problems:
- USART3 is initialized after the Ethernet MAC or USB devices (minor problem)
- The generated function "MX_ETH_Init()" calls "HAL_ETH_Init()". If "HAL_ETH_Init()" returns status other than "HAL_OK", "MX_ETH_Init()" calls "_Error_Handler()", which (of course) does not return.
- If there is no Ethernet link present when "HAL_ETH_Init()" is called, it returns the status "HAL_TIMEOUT", and does so without fully configuring the PHY for auto-negotiation per the configuration passed in.
- Because USART3 has not yet been initialized, attempts to print failure over USART3 fail for things like the Ethernet and USB initialization.
#1, #2, and #4 are just annoying. It would be less of a problem if the code for those things was not in the "immutable" sections of the code generated by STM32CubeMX -- every time the project is updated, any changes to the order of driver initialization or the result of the initialization gets overwritten because those changes don't appear between "/* USER CODE BEGIN xxx */" and "/* USER CODE END xxx */" markers. The new vs. old file have to be manually merged, which is somewhat error prone. I can live with it, just don't like it.
Issue #3 is the real problem, and it's in the HAL driver code for the STM32F7xx MAC ("stm32f7xx_hal_eth.c"). Througout the code in "HAL_ETH_Init()", there are loops that look like the following:
tickstart = HAL_GetTick();
HAL_ETH_ReadPHYRegister(eth, PHY_BSR, &phyreg);
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_LINKED_STATE)
err = ETH_ERROR;
heth->State = HAL_ETH_STATE_READY;
} while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));
This is being done for operations where the current link status should not matter. Initializing the Ethernet driver should not require that a link can be established at that time. There are callbacks and other means of notifying user software when a link is established, but configuring the PHY itself should not expect a link to exist.
A timeout reading/writing one of the PHY registers is an error that can cause the driver init to fail, but please, not the Ethernet link itself.
The only workaround I can come up with is to edit the driver code, since I cannot guarentee that I will have a link at start-up (and can pretty much guarentee that it won't 90% of the time).
I've attached my STM32CubeMX project file for anyone who wants to reproduce the problem.