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.
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
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- [Repost] "Very Silly" Circuit Problem
- E840-DTU device connection to Alibaba Cloud test
- Interface corresponding to SNVS_TAMPER3 signal
- Looking for a good and available domestic accelerometer
- nRF52832-QFAA Hardware Reference Design
- How to design the MCU+8266 program structure
- 【RPi PICO】Snapshot of the RP2040 chip
- Why does TIM1_CH3N not output PWM after configuring PWM in STM32F103C8T6?
- Please advise on the PinMux code
- Can you recommend a chip that can boost 3.3V to 5V?