Skip to content

Commit a29fd11

Browse files
authored
Merge pull request #3034 from xfan1024/stm32-ethernet
优化STM32以太网驱动
2 parents 381f176 + 65afdf0 commit a29fd11

File tree

2 files changed

+113
-114
lines changed

2 files changed

+113
-114
lines changed

bsp/stm32/libraries/HAL_Drivers/drv_eth.c

Lines changed: 87 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
* Date Author Notes
88
* 2018-11-19 SummerGift first version
99
* 2018-12-25 zylx fix some bugs
10-
* 2019-06-10 SummerGift optimize PHY state detection process
10+
* 2019-06-10 SummerGift optimize PHY state detection process
11+
* 2019-09-03 xiaofan optimize link change detection process
1112
*/
1213

1314
#include "board.h"
@@ -390,47 +391,94 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
390391
LOG_E("eth err");
391392
}
392393

393-
#ifdef PHY_USING_INTERRUPT_MODE
394-
static void eth_phy_isr(void *args)
394+
enum {
395+
PHY_LINK = (1 << 0),
396+
PHY_100M = (1 << 1),
397+
PHY_FULL_DUPLEX = (1 << 2),
398+
};
399+
400+
static void phy_linkchange()
395401
{
396-
rt_uint32_t status = 0;
397-
static rt_uint8_t link_status = 1;
402+
static rt_uint8_t phy_speed = 0;
403+
rt_uint8_t phy_speed_new = 0;
404+
rt_uint32_t status;
398405

399-
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_INTERRUPT_FLAG_REG, (uint32_t *)&status);
400-
LOG_D("phy interrupt status reg is 0x%X", status);
401406
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
402407
LOG_D("phy basic status reg is 0x%X", status);
403408

404-
if (status & PHY_LINKED_STATUS_MASK)
409+
if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
405410
{
406-
if (link_status == 0)
411+
rt_uint32_t SR;
412+
413+
phy_speed_new |= PHY_LINK;
414+
415+
SR = HAL_ETH_ReadPHYRegister(&EthHandle, PHY_Status_REG, (uint32_t *)&SR);
416+
LOG_D("phy control status reg is 0x%X", SR);
417+
418+
if (PHY_Status_SPEED_100M(SR))
419+
{
420+
phy_speed_new |= PHY_100M;
421+
}
422+
423+
if (PHY_Status_FULL_DUPLEX(SR))
424+
{
425+
phy_speed_new |= PHY_FULL_DUPLEX;
426+
}
427+
}
428+
429+
if (phy_speed != phy_speed_new) {
430+
phy_speed = phy_speed_new;
431+
if (phy_speed & PHY_LINK)
407432
{
408-
link_status = 1;
409433
LOG_D("link up");
434+
if (phy_speed & PHY_100M)
435+
{
436+
LOG_D("100Mbps");
437+
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
438+
}
439+
else
440+
{
441+
stm32_eth_device.ETH_Speed = ETH_SPEED_10M;
442+
LOG_D("10Mbps");
443+
}
444+
445+
if (phy_speed & PHY_FULL_DUPLEX)
446+
{
447+
LOG_D("full-duplex");
448+
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
449+
}
450+
else
451+
{
452+
LOG_D("half-duplex");
453+
stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
454+
}
455+
410456
/* send link up. */
411457
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
412458
}
413-
}
414-
else
415-
{
416-
if (link_status == 1)
459+
else
417460
{
418-
link_status = 0;
419461
LOG_I("link down");
420-
/* send link down. */
421462
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
422463
}
423464
}
424465
}
466+
467+
#ifdef PHY_USING_INTERRUPT_MODE
468+
static void eth_phy_isr(void *args)
469+
{
470+
rt_uint32_t status = 0;
471+
472+
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_INTERRUPT_FLAG_REG, (uint32_t *)&status);
473+
LOG_D("phy interrupt status reg is 0x%X", status);
474+
475+
phy_linkchange();
476+
}
425477
#endif /* PHY_USING_INTERRUPT_MODE */
426478

427-
static uint8_t phy_speed = 0;
428-
#define PHY_LINK_MASK (1<<0)
429479
static void phy_monitor_thread_entry(void *parameter)
430480
{
431481
uint8_t phy_addr = 0xFF;
432-
uint8_t phy_speed_new = 0;
433-
rt_uint32_t status = 0;
434482
uint8_t detected_count = 0;
435483

436484
while(phy_addr == 0xFF)
@@ -468,102 +516,29 @@ static void phy_monitor_thread_entry(void *parameter)
468516

469517
while (1)
470518
{
471-
phy_speed_new = 0;
519+
phy_linkchange();
472520

473-
if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status) == HAL_OK)
474-
{
475-
LOG_D("PHY BASIC STATUS REG:0x%04X", status);
476-
477-
if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
478-
{
479-
rt_uint32_t SR;
480-
481-
phy_speed_new = PHY_LINK_MASK;
482-
483-
if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_Status_REG, (uint32_t *)&SR) == HAL_OK)
484-
{
485-
LOG_D("PHY Control/Status REG:0x%04X ", SR);
486-
487-
if (SR & PHY_100M_MASK)
488-
{
489-
phy_speed_new |= PHY_100M_MASK;
490-
}
491-
else if (SR & PHY_10M_MASK)
492-
{
493-
phy_speed_new |= PHY_10M_MASK;
494-
}
495-
496-
if (SR & PHY_FULL_DUPLEX_MASK)
497-
{
498-
phy_speed_new |= PHY_FULL_DUPLEX_MASK;
499-
}
500-
}
501-
else
502-
{
503-
LOG_D("PHY PHY_Status_REG read error.");
504-
rt_thread_mdelay(100);
505-
continue;
506-
}
507-
}
508-
}
509-
else
521+
if (stm32_eth_device.parent.netif->flags & NETIF_FLAG_LINK_UP)
510522
{
511-
LOG_D("PHY_BASIC_STATUS_REG read error.");
512-
rt_thread_mdelay(100);
513-
continue;
514-
}
515-
516-
/* linkchange */
517-
if (phy_speed_new != phy_speed)
518-
{
519-
if (phy_speed_new & PHY_LINK_MASK)
520-
{
521-
LOG_D("link up ");
522-
523-
if (phy_speed_new & PHY_100M_MASK)
524-
{
525-
LOG_D("100Mbps");
526-
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
527-
}
528-
else
529-
{
530-
stm32_eth_device.ETH_Speed = ETH_SPEED_10M;
531-
LOG_D("10Mbps");
532-
}
533-
534-
if (phy_speed_new & PHY_FULL_DUPLEX_MASK)
535-
{
536-
LOG_D("full-duplex");
537-
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
538-
}
539-
else
540-
{
541-
LOG_D("half-duplex");
542-
stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
543-
}
544-
545-
/* send link up. */
546-
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
547-
548523
#ifdef PHY_USING_INTERRUPT_MODE
549-
/* configuration intterrupt pin */
550-
rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
551-
rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
552-
rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);
553-
554-
/* enable phy interrupt */
555-
HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MSAK_REG, PHY_INT_MASK);
556-
557-
break;
524+
/* configuration intterrupt pin */
525+
rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
526+
rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
527+
rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);
528+
529+
/* enable phy interrupt */
530+
HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
531+
#if defined(PHY_INTERRUPT_CTRL_REG)
532+
HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
558533
#endif
559-
} /* link up. */
560-
else
561-
{
562-
LOG_I("link down");
563-
/* send link down. */
564-
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
565-
}
566-
phy_speed = phy_speed_new;
534+
break;
535+
#endif
536+
} /* link up. */
537+
else
538+
{
539+
LOG_I("link down");
540+
/* send link down. */
541+
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
567542
}
568543

569544
rt_thread_delay(RT_TICK_PER_SECOND);

bsp/stm32/libraries/HAL_Drivers/drv_eth.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
/* The PHY interrupt source flag register. */
4040
#define PHY_INTERRUPT_FLAG_REG 0x1DU
4141
/* The PHY interrupt mask register. */
42-
#define PHY_INTERRUPT_MSAK_REG 0x1EU
42+
#define PHY_INTERRUPT_MASK_REG 0x1EU
4343
#define PHY_LINK_DOWN_MASK (1<<4)
4444
#define PHY_AUTO_NEGO_COMPLETE_MASK (1<<6)
4545

@@ -48,21 +48,45 @@
4848
#define PHY_10M_MASK (1<<2)
4949
#define PHY_100M_MASK (1<<3)
5050
#define PHY_FULL_DUPLEX_MASK (1<<4)
51+
#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK)
52+
#define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK)
53+
#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK)
5154
#endif /* PHY_USING_LAN8720A */
5255

5356
#ifdef PHY_USING_DM9161CEP
5457
#define PHY_Status_REG 0x11U
5558
#define PHY_10M_MASK ((1<<12) || (1<<13))
5659
#define PHY_100M_MASK ((1<<14) || (1<<15))
5760
#define PHY_FULL_DUPLEX_MASK ((1<<15) || (1<<13))
61+
#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK)
62+
#define PHY_Status_SPEED_100M(sr) ((sr) & PHY_100M_MASK)
63+
#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK)
5864
/* The PHY interrupt source flag register. */
5965
#define PHY_INTERRUPT_FLAG_REG 0x15U
6066
/* The PHY interrupt mask register. */
61-
#define PHY_INTERRUPT_MSAK_REG 0x15U
67+
#define PHY_INTERRUPT_MASK_REG 0x15U
6268
#define PHY_LINK_CHANGE_FLAG (1<<2)
6369
#define PHY_LINK_CHANGE_MASK (1<<9)
6470
#define PHY_INT_MASK 0
6571

6672
#endif /* PHY_USING_DM9161CEP */
6773

74+
#ifdef PHY_USING_DP83848C
75+
#define PHY_Status_REG 0x10U
76+
#define PHY_10M_MASK (1<<1)
77+
#define PHY_FULL_DUPLEX_MASK (1<<2)
78+
#define PHY_Status_SPEED_10M(sr) ((sr) & PHY_10M_MASK)
79+
#define PHY_Status_SPEED_100M(sr) (!PHY_Status_SPEED_10M(sr))
80+
#define PHY_Status_FULL_DUPLEX(sr) ((sr) & PHY_FULL_DUPLEX_MASK)
81+
/* The PHY interrupt source flag register. */
82+
#define PHY_INTERRUPT_FLAG_REG 0x12U
83+
#define PHY_LINK_CHANGE_FLAG (1<<13)
84+
/* The PHY interrupt control register. */
85+
#define PHY_INTERRUPT_CTRL_REG 0x11U
86+
#define PHY_INTERRUPT_EN ((1<<0)|(1<<1))
87+
/* The PHY interrupt mask register. */
88+
#define PHY_INTERRUPT_MASK_REG 0x12U
89+
#define PHY_INT_MASK (1<<5)
90+
#endif /* PHY_USING_DP83848C */
91+
6892
#endif /* __DRV_ETH_H__ */

0 commit comments

Comments
 (0)