gd32f30x_enet.c的网卡初始化时上电时网线未插入会卡住很长时间,导致ETH初始化部分未能成功完成并且在执行enet_init() 时由于网线没接上,会在while((RESET == phy_value) && (timeout < PHY_READ_TO))卡住很长时间,之后即使再插入网线,程序中没有再次进行初始化的逻辑补充,从而导致网络异常。
//修改后的代码
void enet_system_setup(void)
{
nvic_configuration();
/* configure the GPIO ports for ethernet pins */
enet_gpio_config();
/* configure the ethernet MAC/DMA */
enet_mac_dma_config();
#if 0
if(0 == enet_init_status){
while(1){
}
}
#endif
enet_interrupt_enable(ENET_DMA_INT_NIE);
enet_interrupt_enable(ENET_DMA_INT_RIE);
}
/*!
\brief configures the ethernet interface
\param[in] none
\param[out] none
\retval none
*/
static void enet_mac_dma_config(void)
{
ErrStatus reval_state = ERROR;
/* enable ethernet clock */
rcu_periph_clock_enable(RCU_ENET);
rcu_periph_clock_enable(RCU_ENETTX);
rcu_periph_clock_enable(RCU_ENETRX);
/* reset ethernet on AHB bus */
enet_deinit();
reval_state = enet_software_reset();
if(ERROR == reval_state){
while(1){
}
}
/* configure the parameters which are usually less cared for enet initialization */
// enet_initpara_config(HALFDUPLEX_OPTION, ENET_CARRIERSENSE_ENABLE|ENET_RECEIVEOWN_ENABLE|ENET_RETRYTRANSMISSION_DISABLE|ENET_BACKOFFLIMIT_10|ENET_DEFERRALCHECK_DISABLE);
// enet_initpara_config(DMA_OPTION, ENET_FLUSH_RXFRAME_ENABLE|ENET_SECONDFRAME_OPT_ENABLE|ENET_NORMAL_DESCRIPTOR);
enet_head_init_usr();
#if 0
#ifdef CHECKSUM_BY_HARDWARE
enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);
#else
enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS);
#endif /* CHECKSUM_BY_HARDWARE */
#endif
}
/*!
\brief insert a delay time
\param[in] ncount: specifies the delay time length
\param[out] none
\param[out] none
*/
static void enet_delay(uint32_t ncount)
{
__IO uint32_t delay_time = 0U;
for(delay_time = ncount; delay_time != 0U; delay_time--){
}
}
/*!
\brief initialize ENET peripheral with generally concerned parameters, call it by enet_init()
\param[in] none
\param[out] none
\retval none
*/
static void enet_default_init(void)
{
uint32_t reg_value = 0U;
/* MAC */
/* configure ENET_MAC_CFG register */
reg_value = ENET_MAC_CFG;
reg_value &= MAC_CFG_MASK;
reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \
| ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \
| ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \
| ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \
| ENET_DEFERRALCHECK_DISABLE \
| ENET_TYPEFRAME_CRC_DROP_DISABLE \
| ENET_AUTO_PADCRC_DROP_DISABLE \
| ENET_CHECKSUMOFFLOAD_DISABLE;
ENET_MAC_CFG = reg_value;
/* configure ENET_MAC_FRMF register */
ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \
|ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \
|ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \
|ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE;
/* configure ENET_MAC_HLH, ENET_MAC_HLL register */
ENET_MAC_HLH = 0x0U;
ENET_MAC_HLL = 0x0U;
/* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */
reg_value = ENET_MAC_FCTL;
reg_value &= MAC_FCTL_MASK;
reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \
|ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \
|ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE;
ENET_MAC_FCTL = reg_value;
/* configure ENET_MAC_VLT register */
ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0);
/* DMA */
/* configure ENET_DMA_CTL register */
reg_value = ENET_DMA_CTL;
reg_value &= DMA_CTL_MASK;
reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \
|ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \
|ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \
|ENET_SECONDFRAME_OPT_DISABLE;
ENET_DMA_CTL = reg_value;
/* configure ENET_DMA_BCTL register */
reg_value = ENET_DMA_BCTL;
reg_value &= DMA_BCTL_MASK;
reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \
|ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \
|ENET_FIXED_BURST_ENABLE |ENET_MIXED_BURST_DISABLE \
|ENET_NORMAL_DESCRIPTOR;
ENET_DMA_BCTL = reg_value;
}
void enet_head_init_usr(void)
{
/* PHY interface configuration, configure SMI clock and reset PHY chip */
if(ERROR == enet_phy_config()){
_ENET_DELAY_(PHY_RESETDELAY);
if(ERROR == enet_phy_config()){
// return enet_state;
}
}
/* initialize ENET peripheral with generally concerned parameters */
enet_default_init();
}
//enet_init() 如果网线没接上,会在while((RESET == phy_value) && (timeout < PHY_READ_TO));卡住很长时间
ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept)
{
uint32_t reg_value=0U, reg_temp = 0U, temp = 0U;
uint32_t media_temp = 0U;
uint32_t timeout = 0U;
uint16_t phy_value = 0U;
ErrStatus phy_state= ERROR, enet_state = ERROR;
/* PHY interface configuration, configure SMI clock and reset PHY chip */
if(ERROR == enet_phy_config()){
_ENET_DELAY_(PHY_RESETDELAY);
if(ERROR == enet_phy_config()){
return enet_state;
}
}
/* initialize ENET peripheral with generally concerned parameters */
enet_default_init();
/* 1st, configure mediamode */
media_temp = (uint32_t)mediamode;
/* if is PHY auto negotiation */
if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){
/* wait for PHY_LINKED_STATUS bit be set */
do{
enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
phy_value &= PHY_LINKED_STATUS;
timeout++;
}while((RESET == phy_value) && (timeout < PHY_READ_TO)); //#1 卡住很长时间
/* return ERROR due to timeout */
if(PHY_READ_TO == timeout){
return enet_state;
}
/* reset timeout counter */
timeout = 0U;
//在另外的线程中增加监控网线接入后重新会网卡初始化
enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);