千兆交换机LAN8720A手动协商只能到10M
难搞哦 自动协商连不上网,手动协商只能到10M全双工想问下有没有解决办法。
交换机是锐捷的S2910V2-48GT4SFP-L 千兆交换机
电脑连上测速500-800M带宽
开发环境:
STM32CubeMX(V6.10.0)和 Keil(V5.38.0) ARM版本5.06
用的STM32F429IGT6和LAN8720A
本地测试环境正常100M全双工,生产环境出现10M的情况,用的上面提到的锐捷交换机。
代码:
main中正常调用MX_LWIP_Init(), while(1)主循环中调用MX_LWIP_Process()
其他的设置MAC,IP,掩码,网关都确定没问题。
// STM32CubeMX生成的自协商代码 只有自协商 这个锐捷交换机会有一定概率连不上网
void ethernet_link_check_state_1(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf = {0};
int32_t PHYLinkState = 0;
uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
{
HAL_ETH_Stop(&heth);
netif_set_down(netif);
netif_set_link_down(netif);
}
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
{
switch (PHYLinkState)
{
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
default:
break;
}
if(linkchanged)
{
/* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&heth, &MACConf);
MACConf.DuplexMode = duplex;
MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&heth, &MACConf);
HAL_ETH_Start(&heth);
netif_set_up(netif);
netif_set_link_up(netif);
}
}
}
// 自己在原有基础上改的先自协商 没成功就手动协商 按照100M,10M的先后尝试。只有10M才能成功。强制100M后续没网
void ethernet_link_check_state(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf = {0};
int32_t PHYLinkState = 0;
uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
PHYLinkState = LAN8742_GetLinkState(&LAN8742);
static uint32_t last_time = 0;
static int32_t last_linkstate = 0;
//printf("netif_is_link_up:%u, PHYLinkState:%d\n", netif_is_link_up(netif), PHYLinkState);
if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
{
printf("1.netif_is_link_up:%u, PHYLinkState:%d\n", netif_is_link_up(netif), PHYLinkState);
printf("1.eth stop and set down.\n");
last_linkstate = LAN8742_STATUS_LINK_DOWN;
HAL_ETH_Stop(&heth);
netif_set_down(netif);
netif_set_link_down(netif);
}
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
{
printf("2.netif_is_link_up:%u, PHYLinkState:%d\n", netif_is_link_up(netif), PHYLinkState);
// if (PHYLinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX)
// {
// PHYLinkState = LAN8742_STATUS_100MBITS_FULLDUPLEX;
// }
// else
// if (PHYLinkState == LAN8742_STATUS_10MBITS_HALFDUPLEX)
// {
// PHYLinkState = LAN8742_STATUS_100MBITS_HALFDUPLEX;
// }
switch (PHYLinkState)
{
case LAN8742_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case LAN8742_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
// case LAN8742_STATUS_10MBITS_FULLDUPLEX:
// duplex = ETH_FULLDUPLEX_MODE;
// speed = ETH_SPEED_100M;
// linkchanged = 1;
// break;
// case LAN8742_STATUS_10MBITS_HALFDUPLEX:
// duplex = ETH_HALFDUPLEX_MODE;
// speed = ETH_SPEED_100M;
// linkchanged = 1;
// break;
default:
break;
}
if(linkchanged)
{
printf("2.eth changed.\n");
/* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&heth, &MACConf);
MACConf.DuplexMode = duplex;
MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&heth, &MACConf);
HAL_ETH_Start(&heth);
netif_set_up(netif);
netif_set_link_up(netif);
}
}
else if(!netif_is_link_up(netif) && (HAL_GetTick() - last_time > 5000))
{
// printf("3netif_is_link_up:%u, PHYLinkState:%d\n", netif_is_link_up(netif), PHYLinkState);
if (last_linkstate == LAN8742_STATUS_LINK_DOWN) {
last_time = HAL_GetTick();
printf("3.set eth mode auto ");
int32_t status = LAN8742_StartAutoNego(&LAN8742);
if(status == LAN8742_STATUS_OK) {
printf("successfully.\n");
} else if (status == LAN8742_STATUS_READ_ERROR){
printf("but read bcr failed.\n");
} else if (status == LAN8742_STATUS_WRITE_ERROR){
printf("but write bcr failed.\n");
} else if (status == LAN8742_STATUS_ERROR){
printf("but status err.\n");
}
last_linkstate = LAN8742_STATUS_AUTONEGO_NOTDONE;
} else if (last_linkstate == LAN8742_STATUS_AUTONEGO_NOTDONE && (HAL_GetTick() - last_time < 10000)) {
} else {
last_time = HAL_GetTick();
PHYLinkState = last_linkstate;
PHYLinkState++;
if ( PHYLinkState < LAN8742_STATUS_100MBITS_FULLDUPLEX || PHYLinkState > LAN8742_STATUS_10MBITS_HALFDUPLEX) {
// if ( PHYLinkState < LAN8742_STATUS_100MBITS_FULLDUPLEX || PHYLinkState > LAN8742_STATUS_100MBITS_HALFDUPLEX) {
PHYLinkState = LAN8742_STATUS_100MBITS_FULLDUPLEX;
}
printf("3.set eth mode %d ", PHYLinkState);
int32_t status = LAN8742_SetLinkState(&LAN8742, PHYLinkState);
if(status == LAN8742_STATUS_OK) {
printf("successfully.\n");
} else if (status == LAN8742_STATUS_READ_ERROR){
printf("but read bcr failed.\n");
} else if (status == LAN8742_STATUS_WRITE_ERROR){
printf("but write bcr failed.\n");
} else if (status == LAN8742_STATUS_ERROR){
printf("but status err.\n");
}
last_linkstate = PHYLinkState;
}
HAL_ETH_Stop(&heth);
netif_set_down(netif);
netif_set_link_down(netif);
}
}
硬汉哥 帮忙看下呗
参考1.说是因为寄存器没有配置对,所以HAL框架读取了错误的寄存器地址,所以自动协商失败。
地址:https://community.st.com/t5/stm32-mcus-products/configuring-lan8742-possible-bug-issues-using-cubemx-tool-for/td-p/569142
说明:这个寄存器地址我多确认过了 代码没用到的我甚至给他注释掉了
/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping
* @{
*/
#define LAN8742_BCR ((uint16_t)0x0000U)
#define LAN8742_BSR ((uint16_t)0x0001U)
//#define LAN8742_PHYI1R ((uint16_t)0x0002U)
//#define LAN8742_PHYI2R ((uint16_t)0x0003U)
//#define LAN8742_ANAR ((uint16_t)0x0004U)
//#define LAN8742_ANLPAR ((uint16_t)0x0005U)
//#define LAN8742_ANER ((uint16_t)0x0006U)
////#define LAN8742_ANNPTR ((uint16_t)0x0007U)
////#define LAN8742_ANNPRR ((uint16_t)0x0008U)
////#define LAN8742_MMDACR ((uint16_t)0x000DU)
////#define LAN8742_MMDAADR((uint16_t)0x000EU)
////#define LAN8742_ENCTR ((uint16_t)0x0010U)
//#define LAN8742_MCSR ((uint16_t)0x0011U)
#define LAN8742_SMR ((uint16_t)0x0012U)
////#define LAN8742_TPDCR ((uint16_t)0x0018U)
////#define LAN8742_TCSR ((uint16_t)0x0019U)
//#define LAN8742_SECR ((uint16_t)0x001AU)
//#define LAN8742_SCSIR ((uint16_t)0x001BU)
////#define LAN8742_CLR ((uint16_t)0x001CU)
#define LAN8742_ISFR ((uint16_t)0x001DU)
#define LAN8742_IMR ((uint16_t)0x001EU)
#define LAN8742_PHYSCSR((uint16_t)0x001FU)
参考2.另一个人说他把自动协商关闭了,直接初始化为100兆全双工也行。
low_level_init()函数里面:
heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
heth.Init.Speed = ETH_SPEED_100M;
heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
并且把MX_LWIP_Process()函数中读寄存器相关的代码注释掉了
// HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, ®value);
// regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
// /* Enable Interrupts */
// HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );
// /* Read Register Configuration */
// HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, ®value);
// regvalue |= PHY_MISR_LINK_INT_EN;
// /* Enable Interrupt on change of link status */
// HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue)
地址:https://community.st.com/t5/stm32-mcus-embedded-software/ethernet-lwip-on-stm32f407-board-with-hal-lib/td-p/456812
说明:我这边cubemx生产的结构体heth.Init就没这几个变量。而且他这个也是设置手动协商,我的那边设置手动协商应该也能达到一样的效果,但是不生效
参考3.这个贴子里面大意是从CMSIS中获得正确的LAN8720驱动,而不是用LAN8742的,第二步,修改CubeMX中的bug(最后一个回贴)
地址:https://community.st.com/t5/stm32cubemx-mcus/how-to-add-a-quot-lan8720-quot-driver/td-p/146547
说明:这个正在看,估计改起来比较麻烦。
目前开发都是STM32CubeMX生成用Keil HAL库开发的,发现HAL问题不少,而且都不好找到原因和处理。有的坑
强制配置100M,不做自动协商,是否正常。 eric2013 发表于 2024-3-7 00:32
强制配置100M,不做自动协商,是否正常。
强制100M 连不上网
// 输出了下几个寄存器值的变化
// LAN8742_BCR, LAN8742_BSR, LAN8742_SMR, LAN8742_ISFR, LAN8742_IMR, LAN8742_PHYSCSR
xxx.set eth mode 2 successfully.
reg-0000>>0000000000000000->0010000100000000
reg-0001>>0000000000000000->0111100000001001
reg-0012>>0000000000000000->0110000011100000
reg-001D>>0000000000000000->0000000000010000
reg-001F>>0000000000000000->0000000001011000
3.set eth mode 2 successfully.
3.set eth mode 3 successfully.
reg-0000>>0010000100000000->0010000000000000
reg-001F>>0000000001011000->0000000001001000
3.set eth mode 4 successfully.
reg-0000>>0010000000000000->0000000100000000
reg-001F>>0000000001001000->0000000001010100
reg-001D>>0000000000010000->0000000010000000
reg-0001>>0111100000001001->0111100000001101
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-0001>>0111100000001101->0111100000001001
reg-001D>>0000000010000000->0000000010010000
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000010010000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-0001>>0111100000001101->0111100000001001
reg-001D>>0000000010000000->0000000010010000
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000010010000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-0001>>0111100000001101->0111100000001001
reg-001D>>0000000010000000->0000000010010000
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000010010000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-001D>>0000000010000000->0000000010010000
reg-0001>>0111100000001101->0111100000001001
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000010010000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-001D>>0000000010000000->0000000010010000
reg-0001>>0111100000001101->0111100000001001
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000010010000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
reg-0001>>0111100000001101->0111100000001001
reg-001D>>0000000010000000->0000000010010000
1.netif_is_link_up:1, PHYLinkState:1
1.eth stop and set down.
reg-001D>>0000000010010000->0000000000010000
reg-001D>>0000000000010000->0000000000000000
reg-0001>>0111100000001001->0111100000001101
reg-001D>>0000000000000000->0000000010000000
2.netif_is_link_up:0, PHYLinkState:4
2.eth changed.
LinY 发表于 2024-3-7 10:22
// 输出了下几个寄存器值的变化
// LAN8742_BCR, LAN8742_BSR, LAN8742_SMR, LAN87 ...
不排除估计是有干扰,这样试试,你的8720做外置硬件复位还是GPIO控制的复位,可以先硬件复位下,然后软件命令再复位一次,等待1秒后操作试试。
还有就是设置你的RMII所涉及到GPIO速度等级降低下。 eric2013 发表于 2024-3-7 11:14
不排除估计是有干扰,这样试试,你的8720做外置硬件复位还是GPIO控制的复位,可以先硬件复位下,然后软件 ...
试了 没效果 LinY 发表于 2024-3-7 16:07
试了 没效果
st 貌似有提供 lan4872 的驱动吗 ?
可以参考一下,或者更换 8742 芯片试试看
LinY 发表于 2024-3-7 16:07
试了 没效果
还有个问题,使用路由器或者换个交换机有测试过没。或者找个其它带网络的板子测试。
难道是板子的硬件设计问题或者交换机的问题。想办法锁定下问题方向,排除法。 第一个方案用LAN8742替换LAN8720 测试可以解决问题。
准备试下第二个方案 原来给LAN8720用的是扬兴25MHz无源晶振(X322525MOB4SI),准备换爱普生或扬兴的有源晶振+LAN8720试试。
页:
[1]