@国产以太网PHY芯片SR8021由gd32f450移植到gd32f470
国产以太网PHY芯片SR8021由gd32f450移植到gd32f470
由于有国产化要求,需要将以太网及主控芯片全部换成国产,参考例程是基于GD32F450的,在移植过程中遇到一些容易忽略的地方,导致程序一致卡在gd32fxx_enet.c中enet_phy_config()的位置,有类似情况的小伙伴,可以参考一下。
故障排查
虽然将GD32F450上的代码全部知道GD32F470平台后,一直卡在卡在gd32fxx_enet.c中enet_phy_config(),经过排查发现GD32的官方库文件也需要修改,分别为gd32f4xx_enet.h和gd32f4xx_enet.c。
需要修改的地方
GD32F470的例程基于GD32F4xx_Demo_Suites_V2.6.1版本;
针对gd32f4xx_enet.h的修改:
在头文件69行的位置修改如下内容:
1.添加宏定义“#define SR8201F 2”;
2.修改宏定义PHY_TYPE为SR8201F,“#define PHY_TYPE SR8201F”;
3.修改宏定义PHY_ADDRESS为3,“#define PHY_ADDRESS ((uint16_t)0x3U)”;
#ifndef _PHY_H_
#define DP83848 0
#define LAN8700 1
#define SR8201F 2
#define PHY_TYPE SR8201F
#define PHY_ADDRESS ((uint16_t)0x3U) /*!< phy address determined by the hardware */
在头文件88行位置添加如下内容:
#if(PHY_TYPE == LAN8700)
#define PHY_SR 31U /*!< tranceiver status register */
#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */
#elif(PHY_TYPE == DP83848)
#define PHY_SR 16U /*!< tranceiver status register */
#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */
#elif(PHY_TYPE == SR8201F)
#define PHY_SR PHY_REG_BCR /*!< tranceiver status register */
#define PHY_SPEED_STATUS ((uint16_t)0x2000) /*!< configured information of speed: 10Mbit/s */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0100) /*!< configured information of duplex: full-duplex */
#endif /* PHY_TYPE */
针对gd32f4xx_enet.c的修改:
1.修改函数ErrStatus enet_init(enet_mediamode_enum 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));
/* return ERROR due to timeout */
if(PHY_READ_TO == timeout) {
return enet_state;
}
/* reset timeout counter */
timeout = 0U;
/* enable auto-negotiation */
phy_value = PHY_AUTONEGOTIATION;
phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
if(!phy_state) {
/* return ERROR due to write timeout */
return enet_state;
}
/* wait for the PHY_AUTONEGO_COMPLETE bit be set */
do {
enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
phy_value &= PHY_AUTONEGO_COMPLETE;
timeout++;
} while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO));
/* return ERROR due to timeout */
if(PHY_READ_TO == timeout) {
return enet_state;
}
/* reset timeout counter */
timeout = 0U;
/* read the result of the auto-negotiation */
//enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value);
enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
/* configure the duplex mode of MAC following the auto-negotiation result */
if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)) {
media_temp = ENET_MODE_FULLDUPLEX;
} else {
media_temp = ENET_MODE_HALFDUPLEX;
}
/* configure the communication speed of MAC following the auto-negotiation result */
#if(PHY_TYPE == SR8201F)
if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){
media_temp |= ENET_SPEEDMODE_100M;
}else{
media_temp |= ENET_SPEEDMODE_10M;
}
#elif
if((uint16_t)RESET !=(phy_value & PHY_SPEED_STATUS)){
media_temp |= ENET_SPEEDMODE_10M;
}else{
media_temp |= ENET_SPEEDMODE_100M;
}
#endif
} else {
phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3);
phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1);
phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
if(!phy_state) {
/* return ERROR due to write timeout */
return enet_state;
}
/* PHY configuration need some time */
_ENET_DELAY_(PHY_CONFIGDELAY);
}
2.修改static void enet_default_init(void),修改内容如下图所示:
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;
ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES;
/* 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_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \
| 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;
}
修改以上内容后,程序可以正确运行
希望以上内容对你有所帮助,欢迎相互学习!!!