cancel
Showing results for 
Search instead for 
Did you mean: 

Ethernet lwip on STM32F407 board with HAL lib.

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

Hello.

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:

/public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/Ethernet%20configuration%20on%20STM32F407%20Discovery%20board&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=170

, 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 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/* Enable SYSCFG clock */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* 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);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2, GPIO_PIN_RESET); 
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2, GPIO_PIN_SET); 
HAL_Delay(100);
/* Enable ETHERNET clock */
__HAL_RCC_ETH_CLK_ENABLE();
}

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 */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#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)
{
HAL_Init(); 
/* Configure the system clock to 168 MHz */
SystemClock_Config();
/* Initialize the LwIP stack */
lwip_init();
/* Configure the Network interface */
Netif_Config(); 
/* udp client connect */
udp_echoclient_connect();
udp_echoclient_send();
/* Notify user about the network interface config */
User_notification(&gnetif);
/* Infinite loop */
while (1)
{ 
/* Read a received packet from the Ethernet buffers and send it 
to the lwIP for handling */
ethernetif_input(&gnetif);
/* Handle timeouts */
sys_check_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
7 REPLIES 7
thomfischer
Senior
Posted on June 08, 2016 at 20:10

Hello,

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

akosodry
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;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2,GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2,GPIO_PIN_SET);
HAL_Delay(10);

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.
akosodry
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

stm32fxx_hal_conf.h

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,

hal_conf.h

ethernetif.c

stm32f4xx_it.c

systemclock_config

________________

Attachments :

dis_bb_config.txt : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzvJ&d=%2Fa%2F0X0000000bSR%2F5TSLAmx0AB20F7v77UzUTSYYXFrldOPZMqk5AOzxVB4&asPdf=false
akosodry
Associate II
Posted on June 14, 2016 at 21:50

Hello,

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.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_Delay(50);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
HAL_Delay(50);

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.
hamrgh
Associate II
Posted on September 19, 2016 at 00:35

hi 

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 !

thanks