Showing results for 
Search instead for 
Did you mean: 

Ethernet lwip on STM32F407 board with HAL lib.

Associate II
Posted on June 08, 2016 at 12:25


I want to make an UDP communication using mySTM32F407 based board, where the PC forms the server side. I checked most of the posts related to the Ethernet+F407 topic, but could not find any comments that could have lead me in the right direction. The most relevant discussion is this one:


, however there the standard peripheral library was finally chosen which solved the problem. In the following i mention all the steps i made. 0)STM32F4xx_Ethernet_Example\udp_echo_client project works fine, i tested using the echotool.exe software provided in theSTM32F4DIS-BB zip package. The problem is that it is based on the SPL, but so far i was working with HAL therefore i would not like to switch back to the old one. 1) i downloaded the latestSTM32Cube package, and tried to modify theSTM324xG_EVAL\LwIP_UDP_Echo_Client project using the parameters applied in theSTM32F4DIS-BB example, these are 2)Project options were changed to 407VGTx, 8Mhz, ST-Link Debugger 3) in the main.h file i modified (IP of the PC: 0.18) a. #define DEST_IP_ADDR3 18 b. #define GW_ADDR3 18 4) in the ethernetif.c file i modified the completeHAL_ETH_MspInit function to

void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clocks */
/* Enable SYSCFG clock */
/* Ethernet pins configuration ************************************************/
ETH_RMII_REF_CLK-------> PA1 - ok
ETH_MDIO --------------> PA2 - ok
ETH_RMII_CRS_DV -------> PA7 - ok
ETH_MDC ---------------> PC1 - ok
ETH_RMII_RXD0 -------> PC4 - ok
ETH_RMII_RXD1 -------> PC5 - ok
ETH_RMII_TX_EN -------> PB11 - ok
ETH_RMII_TXD0 -------> PB12 - ok
ETH_RMII_TXD1 -------> PB13 - ok
ETH_RST_PIN -------> PE2 - ok
/* Configure PA1, PA2 , PA7 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL; 
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PB11,PB12 and PB13 */
GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure the PHY RST pin */
GPIO_InitStructure.Pin = GPIO_PIN_2;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP; 
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Enable ETHERNET clock */

5) I modified the following in the low_level_init function: EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; EthHandle.Init.PhyAddress = 0x01; 6) I also updated thestm32f4xx_hal_conf.h file according to thestm32f4x7_eth_conf.h ofSTM32F4DIS-BB project, however the most of them were left unchanged since in the former STL based project those were not used (such as for example the PHY_AUTONEGOTIATION). Here i also observed that thePHY_RESET_DELAY andPHY_CONFIG_DELAY values are quite big, later i changed back these to the original values.

/* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */
#define MAC_ADDR0 2
#define MAC_ADDR1 0
#define MAC_ADDR2 0
#define MAC_ADDR3 0
#define MAC_ADDR4 0
#define MAC_ADDR5 0
/* Definition of the Ethernet driver buffers size and count */ 
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */
/* DP83848 PHY Address*/ 
#define DP83848_PHY_ADDRESS 0x01
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ 
#define PHY_RESET_DELAY ((uint32_t)0x000FFFFF) 
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00FFFFFF)
#define PHY_READ_TO ((uint32_t)0x0000FFFF)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFF)
/* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register - ok */ 
#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register - ok */
#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset - ok */
#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode - ok*/
#define PHY_FULLDUPLEX_100M (18)
#define PHY_HALFDUPLEX_100M (8)
#define PHY_FULLDUPLEX_10M (14)
#define PHY_HALFDUPLEX_10M (4)
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)31) /* Value for DP83848 PHY */
#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */
#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */
#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */
#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x001C)
#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */
#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */
#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020U) /*!< Enable Interrupt on change of link status */
#define PHY_LINK_INTERRUPT ((uint16_t)0x2000U) /*!< PHY link status interrupt mask */

7) In the main.c file i changed the clock configuration toRCC_OscInitStruct.PLL.PLLM = 8; since 8MHz oscillator is used. I also commented out theBSP_Config() andHAL_GPIO_EXTI_Callback functions. Therefore the main looks like this

int main(void)
/* Configure the system clock to 168 MHz */
/* Initialize the LwIP stack */
/* Configure the Network interface */
/* udp client connect */
/* Notify user about the network interface config */
/* Infinite loop */
while (1)
/* Read a received packet from the Ethernet buffers and send it 
to the lwIP for handling */
/* Handle timeouts */

Compiled and loaded it, started the echootool with /p udp /s commands,however i wasunable to get the communication between the PC and the board. Here is the schematic i used to interface the MCU: 0690X00000605OzQAI.png Any tips? Is there anyone who could help me? Anyone who faced the same problem? Thank you in advance. Best regards, �?kos #cube #discovery #stm32f4 #lwip #dis-bb
Posted on June 08, 2016 at 20:10


PIN10 PHYAD0 is unconnected and has internal PULLDOWN, so I think your PHYADD is 0.

Associate II
Posted on June 08, 2016 at 22:24

Hello Thomas,

thanks for the feedback. I changed the value, but still i doesn't work ...

any other tips?

Amr Elsayed
Associate II
Posted on June 09, 2016 at 03:20

Hi , I had the same problem , I just solved it

I have the same hardware with LAN8720 phy IC and it didn't work with HAL , it was working good with STL. However I disabled the autonegotiation and now the problem is solved instead of

//heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;

I added those three lines in the low_level_init()

heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
heth.Init.Speed = ETH_SPEED_100M;
heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;

also added those lines at the end of the HAL_ETH_MspInit() as you did.

GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

and now the problem is solved , it seems that HAL doesn't support the autonegitiation for the LAN8720 , and the negotiation code is wrote for the ''DP83848'' which probably the PHY IC on the new nucleo boards, as I noticed that it read and write wrong values from wrong registers , I don't really know , also I debugged the STL code I found that after negotiation it continue to the default values (full duplex , 100M)not that values from the LAN8720, So I did the same and the problem is solved. I really hope any expert tell us what's the real problem , is the HAL_eth is wrote only for DP83848 or we have wrong configurations ?!! taking in consideration that I took the configurations from STM32cubeMX configuration tool , but it doesn't solve the problem , it only solved when I disabled the autonegotiation. Note : gw_addr is the address of the gateway in your network , because I read part of your code and it have the ip_addr the same as gw_addr.
Associate II
Posted on June 09, 2016 at 11:21

Hello amrlsayed,

thank you for your response. I changed the lines you mentioned, but still it doesn't work. Could you please share with me your configuration lines related to the Ethernet peripheral configuration partin the


file? Thank you in advance. Best regards.
Amr Elsayed
Associate II
Posted on June 09, 2016 at 21:11

sorry for the late reply I attached the configurations of 3 files in the same txt file,






Attachments :

dis_bb_config.txt :
Associate II
Posted on June 14, 2016 at 21:50


thank you for your feedback. Finally, i could manage to make the Ethernet work. I created a plain project using the CubeMX with the following properties: DHCP disabled->static ip is defined auto negotiation enabled MX_LWIP_Process() shall be added in the while(1) interrupt registers are commented out:

// HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, ®value);
// regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
// /* Enable Interrupts */
// HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );
// /* Read Register Configuration */
// HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, ®value);
// regvalue |= PHY_MISR_LINK_INT_EN;
// /* Enable Interrupt on change of link status */
// HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue)

HW reset is added in theHAL_ETH_MspInit

GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

I also added theudp_echoclient.c andudp_echoclient.h files in the project in order to test the udp communication. Through theudp_echoclient_connect(); andudp_client_send(); functions i was able to communicate with the GUI (running on the PC), however theudp_receive_callback is not called when a package sent from the GUI, even tho with

udp_recv(upcb, udp_receive_callback, NULL)

function i defined the receive callback in theudp_echoclient_connect(void) function. Any tips? Best regards.
Associate II
Posted on September 19, 2016 at 00:35


each file must be change in keil ? 

would you insert your project created in keil in zip file?

( all of created by Cube and keil files that edited to LAN8720 )

i work with LAN8720 and I Have very problem in registry init and i confused !