Solution to the network failure when hot-plugging the network cable of STM32 transplantation LWIP

Publisher:美丽花朵Latest update time:2018-04-22 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Development Background:

1. Main chip - STM32F207VCT6;

2. TCP/IP protocol stack - LWIP, transplanted based on ST routines;

3. Operating system - none (bare metal);

Anomalies:

1. Power on the device without inserting the network cable, and then insert the network cable, and the ping will fail; (If the network cable is inserted before powering on, the network is normal);

2. When the network is normal, the PC changes the transmission mode (for example, from the original 100M full-duplex to 10M full-duplex), causing the network to be unavailable;


Cause Analysis:

1. For the first abnormal situation, it is because the network cable is not plugged in when power is turned on, resulting in the failure of ETH initialization. Even if the network cable is plugged in again, there is no logic supplement for re-initialization in the program, resulting in network abnormality;

2. For the second case, the ETH initialization is completed and the negotiation with the PC is successful when the power is turned on, and the network is normal at this time. However, when the PC changes the transmission mode, the program fails to perform the re-negotiation and MAC initialization work, resulting in network abnormality;


Solution:

First of all, we need to clarify the key point of the above problem. All the abnormalities are caused by the plugging and unplugging of the network cable (changing the connection transmission mode on the PC is equivalent to unplugging and replugging the network cable). Therefore, the main program must have a detection of the current network connection and disconnection or use the interrupt pin of the PHY chip;

Secondly, whether using polling or PHY interrupt configuration pins, the fundamental principle is the same, that is, to sense the connection and disconnection of the network. The following is the query method used:


void Eth_Link_ITHandler(struct netif *netif)

{

/* Check whether the link interrupt has occurred or not */

if(((ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_MISR)) & PHY_LINK_STATUS) != 0){/*Detect plug-in interrupt*/

uint16_t status = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR);

if(status & (PHY_AutoNego_Complete | PHY_Linked_Status)){/*Network cable connection detected*/

if(EthInitStatus == 0){/*Unsuccessful initialization before*/

/*Reinit PHY*/

ETH_Reinit();

}

else{/*It has been successfully initialized before*/

/*set link up for re link callbalk function*/

netif_set_link_up(netif);

}

}

else{/*Network cable disconnected*/\

/*set link down for re link callbalk function*/

netif_set_link_down(netif);

}

}

}

Note: Put the detection function into the main loop. The marked part in the program is the key point to solve the problem of hot plugging of network cables.

1. The condition for executing the part marked in red is that the network cable is detected to be inserted and the ETH part has not been successfully initialized before (that is, it has been powered on but the network cable has not been inserted). At this time, ETH needs to be reinitialized to solve the first situation of the abnormal phenomenon. The specific execution content is:

/**

* @brief : first time power on but init failed, do again

* @param : None

*

* @retval : None

* @author : xuk

*/

void ETH_Reinit(void){

/* Configure Ethernet */

EthInitStatus =ETH_Init(Ð_InitStructure, DP83848_PHY_ADDRESS);

}

Among them, ETH_InitStructure has been set as a global structure;

2. The execution condition of the blue part is that ETH has been successfully initialized, but the network cable has been unplugged or plugged in. At this time, it is necessary to re-negotiate and initialize MAC every time a network connection is detected. The specific execution process is described as follows:

A. When this condition is detected, first call:

netif_set_link_up(netif);

netif_set_link_down(netif);

B. Trace back to the definitions of the two functions, as follows:

#if LWIP_NETIF_LINK_CALLBACK

/**

* Called by a driver when its link goes up

*/

void netif_set_link_up(struct netif *netif )

{

netif->flags |= NETIF_FLAG_LINK_UP;

#if LWIP_DHCP

if (netif->dhcp) {

dhcp_network_changed(netif);

}

#endif /* LWIP_DHCP */

#if LWIP_AUTOIP

if (netif->autoip) {

autoip_network_changed(netif);

}

#endif /* LWIP_AUTOIP */

if (netif->flags & NETIF_FLAG_UP) {

#if LWIP_ARP

/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */

if (netif->flags & NETIF_FLAG_ETHARP) {

etharp_gratuitous(netif);

}

#endif /* LWIP_ARP */

#if LWIP_IGMP

/* resend IGMP memberships */

if (netif->flags & NETIF_FLAG_IGMP) {

igmp_report_groups( netif);

}

#endif /* LWIP_IGMP */

}

NETIF_LINK_CALLBACK(netif);

}

/**

* Called by a driver when its link goes down

*/

void netif_set_link_down(struct netif *netif )

{

netif->flags &= ~NETIF_FLAG_LINK_UP;

NETIF_LINK_CALLBACK(netif);

}

/**

* Ask if a link is up

*/

u8_t netif_is_link_up(struct netif *netif)

{

return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0;

}

/**

* Set callback to be called when link is brought up/down

*/

voidnetif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))

{

if (netif) {

netif->link_callback = link_callback;

}

}

#endif /* LWIP_NETIF_LINK_CALLBACK */

Note: I: From the above, if you want these two functions to compile effectively, you must define the macro LWIP_NETIF_LINK_CALLBACK to 1, please set it yourself;

II: The function netif_set_link_callback is used to specify the callback function when the network connection changes;

III: Let me explain the main idea in detail. When Eth_Link_ITHandler detects the network cable being unplugged, it calls netif_set_link_up(netif) and netif_set_link_down(netif) respectively. The call of these two functions will trigger the execution of netif_set_link_callback, thereby executing the specified callback function for network connection or disconnection.

IV: Use netif_set_link_callback to specify the callback function for network connection changes when LWIP is initialized. It can be placed in the following locations:


void LwIP_Init(void){

......

......

......

......

/*set the link up or link down callback function - xuk*/

netif_set_link_callback(&netif,eth_re_link);

}


The specific content of the callback function eth_re_link is as follows, which implements re-negotiation and MAC initialization after network plugging and unplugging:

/**

* @brief : process the relink of eth

* @param : netif - - specify the ETH netif

*

* @retval : none

* @author : xuk

*/

voideth_re_link(struct netif *netif){

__IO uint32_t tickstart = 0;

uint32_t regvalue = 0, tmpreg = 0;

if(netif_is_link_up(netif)){/*link up process*/

if(ETH_InitStructure.ETH_AutoNegotiation == ETH_AutoNegotiation_Enable){/*AutoNegotiation_Enable*/

/* Enable Auto-Negotiation */

ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_BCR, PHY_AutoNegotiation);

/* Wait until the auto-negotiation will be completed */

do

{

tickstart++;

} while (!(ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR) & PHY_AutoNego_Complete) && (tickstart < (uint32_t)PHY_READ_TO));

/* Return ERROR in case of timeout */

if(tickstart == PHY_READ_TO)

{

// return ETH_ERROR;

}

/* Reset Timeout counter */

tickstart = 0;

/* Read the result of the auto-negotiation */

regvalue = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_SR);

/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */

if((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)

{

/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */

ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;

}

else

{

/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */

ETH_InitStructure.ETH_Mode = ETH_Mode_HalfDuplex;

}

/* Configure the MAC with the speed fixed by the auto-negotiation process */

if(regvalue & PHY_SPEED_STATUS)

{

/* Set Ethernet speed to 10M following the auto-negotiation */

ETH_InitStructure.ETH_Speed = ETH_Speed_10M;

}

else

{

/* Set Ethernet speed to 100M following the auto-negotiation */

ETH_InitStructure.ETH_Speed = ETH_Speed_100M;

}

}

else{/*AutoNegotiation_Disable*/

if(!ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_BCR, ((uint16_t)(ETH_InitStructure.ETH_Mode >> 3) |

(uint16_t)(ETH_InitStructure.ETH_Speed >> 1))))

{

/* Return ERROR in case of write timeout */

// return ETH_ERROR;

}

/* Delay to assure PHY configuration */

// _eth_delay_(PHY_CONFIG_DELAY);

}

/*------------------------ ETHERNET MACCR Configuration --------------------*/

/* Get the ETHERNET MACCR value */

tmpreg = ETH->MACCR;

/* Clear WD, PCE, PS, TE and RE bits */

tmpreg &= MACCR_CLEAR_MASK;

/* Set the WD bit according to ETH_Watchdog value */

/* Set the JD: bit according to ETH_Jabber value */

/* Set the IFG bit according to ETH_InterFrameGap value */

/* Set the DCRS bit according to ETH_CarrierSense value */

/* Set the FES bit according to ETH_Speed value */

/* Set the DO bit according to ETH_ReceiveOwn value */

/* Set the LM bit according to ETH_LoopbackMode value */

/* Set the DM bit according to ETH_Mode value */

/* Set the IPCO bit according to ETH_ChecksumOffload value */

/* Set the DR bit according to ETH_RetryTransmission value */

/* Set the ACS bit according to ETH_AutomaticPadCRCStrip value */

/* Set the BL bit according to ETH_BackOffLimit value */

/* Set the DC bit according to ETH_DeferralCheck value */

tmpreg |= (uint32_t)(ETH_InitStructure.ETH_Watchdog |

ETH_InitStructure.ETH_Jabber |

ETH_InitStructure.ETH_InterFrameGap |

ETH_InitStructure.ETH_CarrierSense |

ETH_InitStructure.ETH_Speed |

ETH_InitStructure.ETH_ReceiveOwn |

ETH_InitStructure.ETH_LoopbackMode |

ETH_InitStructure.ETH_Mode |

ETH_InitStructure.ETH_ChecksumOffload |

ETH_InitStructure.ETH_RetryTransmission |

ETH_InitStructure.ETH_AutomaticPadCRCStrip |

ETH_InitStructure.ETH_BackOffLimit |

ETH_InitStructure.ETH_DeferralCheck);

/* Write to ETHERNET MACCR */

ETH->MACCR = (uint32_t)tmpreg;

/*----------------------- ETHERNET MACFFR Configuration --------------------*/

/* Set the RA bit according to ETH_ReceiveAll value */

/* Set the SAF and SAIF bits according to ETH_SourceAddrFilter value */

/* Set the PCF bit according to ETH_PassControlFrames value */

/* Set the DBF bit according to ETH_BroadcastFramesReception value */

/* Set the DAIF bit according to ETH_DestinationAddrFilter value */

/* Set the PR bit according to ETH_PromiscuousMode value */

/* Set the PM, HMC and HPF bits according to ETH_MulticastFramesFilter value */

/* Set the HUC and HPF bits according to ETH_UnicastFramesFilter value */

/* Write to ETHERNET MACFFR */

ETH->MACFFR = (uint32_t)(ETH_InitStructure.ETH_ReceiveAll |

ETH_InitStructure.ETH_SourceAddrFilter |

ETH_InitStructure.ETH_PassControlFrames |

ETH_InitStructure.ETH_BroadcastFramesReception |

ETH_InitStructure.ETH_DestinationAddrFilter |

ETH_InitStructure.ETH_PromiscuousMode |

ETH_InitStructure.ETH_MulticastFramesFilter |

ETH_InitStructure.ETH_UnicastFramesFilter);

/*---------------- ETHERNET MACHTHR and MACHTLR Configuration ---------------*/

/* Write to ETHERNET MACHTHR */

ETH->MACHTHR = (uint32_t)ETH_InitStructure.ETH_HashTableHigh;

/* Write to ETHERNET MACHTLR */

ETH->MACHTLR = (uint32_t)ETH_InitStructure.ETH_HashTableLow;

/*----------------------- ETHERNET MACFCR Configuration --------------------*/

/* Get the ETHERNET MACFCR value */

tmpreg = ETH->MACFCR;

/* Clear xx bits */

tmpreg &= MACFCR_CLEAR_MASK;

/* Set the PT bit according to ETH_PauseTime value */

/* Set the DZPQ bit according to ETH_ZeroQuantaPause value */

/* Set the PLT bit according to ETH_PauseLowThreshold value */

/* Set the UP bit according to ETH_UnicastPauseFrameDetect value */

/* Set the RFE bit according to ETH_ReceiveFlowControl value */

/* Set the TFE bit according to ETH_TransmitFlowControl value */

tmpreg |= (uint32_t)((ETH_InitStructure.ETH_PauseTime << 16) |

ETH_InitStructure.ETH_ZeroQuantaPause |

ETH_InitStructure.ETH_PauseLowThreshold |

ETH_InitStructure.ETH_UnicastPauseFrameDetect |

ETH_InitStructure.ETH_ReceiveFlowControl |

ETH_InitStructure.ETH_TransmitFlowControl);

/* Write to ETHERNET MACFCR */

ETH->MACFCR = (uint32_t)tmpreg;

/*----------------------- ETHERNET MACVLANTR Configuration -----------------*/

/* Set the ETV bit according to ETH_VLANTagComparison value */

/* Set the VL bit according to ETH_VLANTagIdentifier value */

ETH->MACVLANTR = (uint32_t)(ETH_InitStructure.ETH_VLANTagComparison |

ETH_InitStructure.ETH_VLANTagIdentifier);

/*-------------------------------- DMA Config ------------------------------*/

/*----------------------- ETHERNET DMAOMR Configuration --------------------*/

/* Get the ETHERNET DMAOMR value */

tmpreg = ETH->DMAOMR;

/* Clear xx bits */

tmpreg &= DMAOMR_CLEAR_MASK;

/* Set the DT bit according to ETH_DropTCPIPChecksumErrorFrame value */

/* Set the RSF bit according to ETH_ReceiveStoreForward value */

/* Set the DFF bit according to ETH_FlushReceivedFrame value */

/* Set the TSF bit according to ETH_TransmitStoreForward value */

/* Set the TTC bit according to ETH_TransmitThresholdControl value */

/* Set the FEF bit according to ETH_ForwardErrorFrames value */

/* Set the FUF bit according to ETH_ForwardUndersizedGoodFrames value */

/* Set the RTC bit according to ETH_ReceiveThresholdControl value */

/* Set the OSF bit according to ETH_SecondFrameOperate value */

tmpreg |= (uint32_t)(ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame |

ETH_InitStructure.ETH_ReceiveStoreForward |

ETH_InitStructure.ETH_FlushReceivedFrame |

ETH_InitStructure.ETH_TransmitStoreForward |

ETH_InitStructure.ETH_TransmitThresholdControl |

ETH_InitStructure.ETH_ForwardErrorFrames |

ETH_InitStructure.ETH_ForwardUndersizedGoodFrames |

ETH_InitStructure.ETH_ReceiveThresholdControl |

ETH_InitStructure.ETH_SecondFrameOperate);

/* Write to ETHERNET DMAOMR */

ETH->DMAOMR = (uint32_t)tmpreg;

/*----------------------- ETHERNET DMABMR Configuration --------------------*/

/* Set the AAL bit according to ETH_AddressAlignedBeats value */

/* Set the FB bit according to ETH_FixedBurst value */

/* Set the RPBL and 4*PBL bits according to ETH_RxDMABurstLength value */

/* Set the PBL and 4*PBL bits according to ETH_TxDMABurstLength value */

/* Set the DSL bit according to ETH_DesciptorSkipLength value */

/* Set the PR and DA bits according to ETH_DMAArbitration value */

ETH->DMABMR = (uint32_t)(ETH_InitStructure.ETH_AddressAlignedBeats |

ETH_InitStructure.ETH_FixedBurst |

ETH_InitStructure.ETH_RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */

ETH_InitStructure.ETH_TxDMABurstLength |

(ETH_InitStructure.ETH_DescriptorSkipLength << 2) |

ETH_InitStructure.ETH_DMAArbitration |

ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */

#ifdef USE_ENHANCED_DMA_DESCRIPTORS

/* Enable the Enhanced DMA descriptors */

ETH->DMABMR |= ETH_DMABMR_EDE;

#endif /* USE_ENHANCED_DMA_DESCRIPTORS */

/* Return Ethernet configuration success */

// return ETH_SUCCESS;

// ETH_Start();

}

else{/*link down process*/

}

}

So far, the problems and solutions for STM32F207 (bare metal) - LWIP network cable hot insertion network failure have been introduced.


Keywords:STM32 Reference address:Solution to the network failure when hot-plugging the network cable of STM32 transplantation LWIP

Previous article:STM32F4 LAN8720 and LWIP porting and debugging records (3)
Next article:Configuration problem of lwip on stm32CubeMX

Recommended ReadingLatest update time:2024-11-16 15:53

Design of portable BMP picture decoding system based on STM32 processor
In the application process of modern portable devices, it is often necessary to display some pictures in the system. Among various picture formats, BMP is the most representative one. BMP is an image file format that is independent of hardware devices and is widely used. It uses a bit-mapped storage format. In addi
[Security Electronics]
Design of portable BMP picture decoding system based on STM32 processor
STM32 system clock monitoring and switching
In the company's project some time ago, it was required to use the STM32 processor to automatically switch to the internal crystal oscillator when the external crystal oscillator is abnormal. After searching for a lot of information on the Internet, I finally found an official seminar PPT on the Internet that briefly
[Microcontroller]
STM32 system clock monitoring and switching
stm32 driving LCD
(1) How to write a header file   Example: //  header file file.h                 #ifndef  FILE_H                            //FILE_H  can be written arbitrarily, it is just a label to prevent the header file from being repeatedly defined                 #define  FILE_H                            //It should be the
[Microcontroller]
The data before stm32 power off is stored in flash
FLASh must be erased before writing. The following function is an analysis case. void FLASH_WriteByte(u32 addr ,u16 flashdata1) { FLASH_Status FLASHstatus = FLASH_COMPLETE; FLASH_Unlock();//Unlock FLASH programming and erasing controller // FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//Cl
[Microcontroller]
STM32 uses systick to accurately delay nms
/***************************************************************************** * File Name          : systick_delay.h * Author             : shifu * Version            :  * Date               : 09/20/2008 * Description        :  ********************************************************************************/ /*
[Microcontroller]
STM32 serial port receives dust sensor data
This article mainly records the data collection and simple processing of dust sensors by STM32. Materials:  1. Zhengdian Atom Mini Development Board STM32f103RC  2. ZH03A Laser Dust Sensor    3. USB TO TTL line (download line for burning 51 microcontroller) to connect the computer and serial port 2 on the development
[Microcontroller]
STM32 serial port receives dust sensor data
STM32 serial port routine
[Microcontroller]
STM32 serial port routine
stm32 general timer and PWM
General timer (the following takes general timer 3, channel 3 as an example): Step 1: Enable the clock RCC- APB1ENR: 1 bit //Turn on timer 3 clock enable Step 2: Set the timer frequency division and load count value (with a cycle of 1ms) TIM3- PSC = 7199; //The system clock is 72M. After (7199+1) division, the timer c
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号