開發背景:
1、主芯片—STM32F207VCT6;
3、操作系統—無(裸機);
異常現象:
1、網線不插入的情況下先給設備上電,之后再插入網線無法ping通;(如果上電前網線插入,網絡正常);
2、網絡已經正常的情況下,電腦PC端修改傳輸模式(比如從原來的100M全雙工修改為10M全雙工)導致網絡不通;
原因分析:
1、針對第一種異常情況,是由于上電時網線未插入,導致ETH初始化部分未能成功完成,之后即使再插入網線,程序中沒有再次進行初始化的邏輯補充,從而導致網絡異常;
2、針對第二種情況,情況是上電時完成了ETH的初始化并與PC協商成功,此時網絡正常。但當PC端修改傳輸模式后,程序中未能執行再次協商與MAC的初始化工作,導致網絡異常;
解決方法:
首先,要明確上述問題的關鍵點所在,所有的異常均是網線的拔插導致(PC端修改連接傳輸方式時也相當于網線的拔掉重插),因此主程序中必須要有對當前網絡連接與斷開的檢測或者利用PHY芯片的中斷引腳;
其次,無論利用輪詢或是PHY中斷配置引腳,根本的原理都是一樣的,就是感知到網絡的連接與斷開,下面給出采用的查詢方式:
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){/*檢測插拔中斷*/
uint16_t status = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR);
if(status & (PHY_AutoNego_Complete | PHY_Linked_Status)){/*檢測到網線連接*/
if(EthInitStatus == 0){/*之前未成功初始化過*/
/*Reinit PHY*/
ETH_Reinit();
}
else{/*之前已經成功初始化*/
/*set link up for re link callbalk function*/
netif_set_link_up(netif);
}
}
else{/*網線斷開*/\
/*set link down for re link callbalk function*/
netif_set_link_down(netif);
}
}
}
備注說明:將該檢測函數放入主循環,程序中標注的部分為解決網線熱拔插問題的關鍵點。
1、標注紅色的部分執行的條件是檢測到網線插入且之前ETH部分未成功初始化過(即之前一直處在上電但網線未插入)的情況,此時需要對ETH重新初始化,從而解決異常現象的第一種情況,具體執行內容為:
/**
* @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);
}
其中ETH_InitStructure已設為全局結構體;
2、標注藍色部分的執行條件是已經成功初始化過ETH,但之后出現了網線的拔插情況,此時需要在每次檢測到網絡連接時重新進行自協商并初始化MAC,具體的執行流程如下介紹:
A、檢測到該條件時,首先調用:
netif_set_link_up(netif);
netif_set_link_down(netif);
B、追溯兩個函數的定義處,如下:
#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 */
注意:I:從上述看出,若要這兩個函數有效編譯,則必須定義宏LWIP_NETIF_LINK_CALLBACK 為1,請自行設置;
II:函數netif_set_link_callback的作用是指定網絡連接發生改變時的回調函數;
III:詳細的講一下主要思路,Eth_Link_ITHandler執行中檢測到網線拔插時分別調用netif_set_link_up(netif)、netif_set_link_down(netif);這兩個函數的調用會引發netif_set_link_callback的執行,從而執行指定的網絡連接或斷開的回調函數;
Ⅳ:通過netif_set_link_callback該函數在LWIP初始化的時候指定網絡連接變化的回調函數,可放置如下位置:
void LwIP_Init(void){
......
......
......
......
/*set the link up or link down callback function - xuk*/
netif_set_link_callback(&netif,eth_re_link);
}
其中,回調函數eth_re_link的具體內容如下,實現網絡拔插后的重新自協商與MAC初始化:
/**
* @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*/
}
}
至此,對于STM32F207(裸機)- LWIP網線熱插入網絡不通遇到的問題以及解決辦法介紹完畢。
上一篇:STM32F4 LAN8720以及LWIP的移植調試記錄 (3)
下一篇:stm32CubeMX上lwip的配置問題
推薦閱讀
史海拾趣
隨著全球市場的不斷擴大,Akahane意識到單打獨斗難以為繼,于是積極尋求與國際同行的合作。通過與歐美知名電子企業建立戰略合作關系,Akahane不僅獲得了先進的技術支持,還成功打入國際市場,進一步提升了品牌影響力。同時,公司還積極參與國際電子行業的交流活動,學習借鑒先進的管理經驗和市場策略,為公司的長遠發展奠定了堅實基礎。
70年代,全球電子產品熱潮興起,金山工業決定進軍這一領域。公司推出了堿性和氧化的銀鈕型電池,這些產品廣泛應用于電子手表、計算機等小型電子設備中。這一戰略轉型不僅豐富了超霸電池的產品線,也進一步提升了其在電子行業的知名度。隨著技術的不斷積累,超霸電池逐漸在市場中占據了一席之地。
隨著技術的不斷進步,EBG RESISTORS LLC公司不斷投入研發,致力于推動電阻器技術的創新。在XXXX年,公司成功研發出一種新型高精度電阻器,具有更高的穩定性和更低的溫度系數。這一創新產品迅速在市場上獲得了廣泛應用,極大地提升了公司的市場競爭力。
DURABLE公司成立于20世紀90年代初,最初是一家專注于電子材料研發的小型科技公司。在創始人李博士的帶領下,DURABLE不斷投入研發資金,積極探索新材料在電子行業的應用。經過數年的努力,公司成功開發出一種具有超高耐用性和穩定性的新型電子材料,這一創新為DURABLE贏得了業界的廣泛認可。隨著技術的不斷成熟,DURABLE的產品逐漸應用于智能手機、平板電腦等高端電子產品中,公司的市場份額也逐年攀升。
HI Microwave深知質量是企業生存和發展的根本。因此,公司從原材料采購到成品出廠的每一個環節都嚴格把關,確保產品質量符合國際標準和客戶要求。同時,公司還建立了完善的售后服務體系,為客戶提供及時、專業的技術支持和解決方案。這種以客戶為中心的服務理念贏得了客戶的信任和忠誠,也為公司的持續發展奠定了堅實的基礎。
嵌入式技術已經無處不在,從隨身攜帶的mp3、語言復讀機、手機、PDA到家庭之中的智能電視、智能冰箱、機頂盒,再到工業生產、娛樂中的機器人,無不采用嵌入式技術。各大跨國公司及國內家電巨頭如INTEL、TI、SONY、三星、TCL、聯想和康佳等都面臨著嵌 ...… 查看全部問答∨ |
|
*****ARM程序在RAM中執行跳轉出錯,懇請指教***** 各位前輩,小弟在用友善的supervivi下程序到SDRAM中執行的時候,發現如下問題: 我寫了一個測試程序: B SYSINIT B Handler ...… 查看全部問答∨ |
Flash Programmer下提示arm2410開發板連不PC 電腦連不上開發板,Flash Programmer提示如下: Target Communications Error:PC to Target Cable disconneted 我是一個新手,自學嵌入式,放棄原來的java開發,學了4個月的C和linux, 第一次用Realarm2410開發板, 系統windowsxpsp2克隆版 ...… 查看全部問答∨ |
看到這篇文章寫得比較好,就轉載過來了。 時序是設計出來的 我的boss有在華為及峻龍工作的背景,自然就給我們講了一些華為及altera做邏輯的一些東西,而我們的項目規范,也基本上是按華為的那一套去做。在工作這幾個月中,給我感觸最深的是 ...… 查看全部問答∨ |
|
經過幾年在國內工作的經驗積累,有沒有想過要到國外最先進的市場一試身手?各位工程師小伙伴,新加坡可以為你提供諸多充滿誘惑的新機會!另外,新加坡作為全球首選的宜居之地,更可以為你實現工作生活的長期合理規劃。 目前,幾大世界級電子領軍 ...… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 顛覆iToF技術,安森美如何突破30米深度感知極限?
- 利用驗證框架 JAIST揭示開源自動駕駛系統的安全漏洞
- 現代汽車集團擬采用VR模擬器替代道路測試 提升未來車型的競爭力
- 研究人員開發光驅動致動器 可用于驅動水下機器人
- 吉利將發射“千里浩瀚”衛星,實現輔助駕駛系統與衛星功能深度融合
- 以鴻道工業操作系統為核心 打造工業智能機器人新生態
- UNIST研發出新表面處理技術 延長下一代鋰金屬電池的壽命
- 車載SerDes芯片行業的"DeepSeek"時刻——瑞發科HSMT SerDes閃耀2025上海車展
- 豐田顛覆傳統,固態電池明年就能量產,最受傷的將是中國?
- 基于恩智浦與onsemi的駕駛員監控系統方案