Browse Source

[bsp] update Ethernet PHY configuration

tanek liang 7 years ago
parent
commit
f1c6dc1a4d
1 changed files with 101 additions and 37 deletions
  1. 101 37
      bsp/imxrt1052-evk/drivers/drv_eth.c

+ 101 - 37
bsp/imxrt1052-evk/drivers/drv_eth.c

@@ -36,8 +36,6 @@
 
 #define PHY_ADDRESS     0x02u
 
-
-
 /* debug option */
 //#define ETH_RX_DUMP
 //#define ETH_TX_DUMP
@@ -50,7 +48,6 @@
 
 #define MAX_ADDR_LEN 6
 
-
 struct rt_imxrt_eth
 {
 	/* inherit from ethernet device */
@@ -63,6 +60,9 @@ struct rt_imxrt_eth
 
     rt_bool_t tx_is_waiting;
     struct rt_semaphore tx_wait;
+
+    enet_mii_speed_t speed;
+    enet_mii_duplex_t duplex;
 };
 
 ALIGN(ENET_BUFF_ALIGNMENT) enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM] SECTION("NonCacheable");
@@ -351,10 +351,6 @@ static void _enet_config(void)
 {
     enet_config_t config;
     uint32_t sysClock;
-    status_t status;
-    phy_speed_t speed;
-    phy_duplex_t duplex;
-    bool link = false;
 
     /* prepare the buffer configuration. */
     enet_buffer_config_t buffConfig = {
@@ -378,48 +374,26 @@ static void _enet_config(void)
     ENET_GetDefaultConfig(&config);
     config.interrupt = kENET_TxFrameInterrupt | kENET_RxFrameInterrupt;
     //config.interrupt = 0xFFFFFFFF;
+    config.miiSpeed = imxrt_eth_device.speed;
+    config.miiDuplex = imxrt_eth_device.duplex;
 
     /* Set SMI to get PHY link status. */
     sysClock = CLOCK_GetFreq(kCLOCK_AhbClk);
 
-    status = PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, sysClock);
-
-    if (status == kStatus_Success)
-    {
-        PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &link);
-        if (link)
-        {
-            /* Get the actual PHY link speed. */
-            PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base, PHY_ADDRESS, &speed, &duplex);
-            /* Change the MII speed and duplex for actual link status. */
-            config.miiSpeed = (enet_mii_speed_t)speed;
-            config.miiDuplex = (enet_mii_duplex_t)duplex;
-        }
-
-        dbg_log(DBG_LOG, "PHY Auto-negotiation success.\n");
-        eth_device_linkchange(&imxrt_eth_device.parent, RT_TRUE);
-    }
-    else
-    {
-        config.miiSpeed = kENET_MiiSpeed10M;
-        config.miiDuplex = kENET_MiiHalfDuplex;
-
-        dbg_log(DBG_WARNING, "PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\n");
-        eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE);
-    }
-
+    dbg_log(DBG_LOG, "deinit\n");
+    ENET_Deinit(imxrt_eth_device.enet_base);
+    dbg_log(DBG_LOG, "init\n");
     ENET_Init(imxrt_eth_device.enet_base, &imxrt_eth_device.enet_handle, &config, &buffConfig, &imxrt_eth_device.dev_addr[0], sysClock);
+    dbg_log(DBG_LOG, "set call back\n");
     ENET_SetCallback(&imxrt_eth_device.enet_handle, _enet_callback, &imxrt_eth_device);
+    dbg_log(DBG_LOG, "active read\n");
     ENET_ActiveRead(imxrt_eth_device.enet_base);
 }
 
 /* initialize the interface */
 static rt_err_t rt_imxrt_eth_init(rt_device_t dev)
 {
-    _enet_io_init();
-    _enet_clk_init();
-    _enet_phy_reset_by_gpio();
-
+    dbg_log(DBG_LOG, "rt_imxrt_eth_init...\n");
     _enet_config();
 
     return RT_EOK;
@@ -576,10 +550,81 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev)
     return NULL;
 }
 
+static void phy_monitor_thread_entry(void *parameter)
+{
+    
+    phy_speed_t speed;
+    phy_duplex_t duplex;
+    bool link = false;
+    
+    _enet_phy_reset_by_gpio();
+
+    PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, CLOCK_GetFreq(kCLOCK_AhbClk));
+    
+    while (1)
+    {
+        bool new_link = false;
+        status_t status = PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &new_link);
+        
+        if ((status == kStatus_Success) && (link != new_link))
+        {
+            link = new_link;
+            
+            if (link)   // link up
+            {
+                PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base, PHY_ADDRESS, &speed, &duplex);
+                
+                if (kENET_MiiSpeed10M == speed)
+                {
+                    dbg_log(DBG_LOG, "10M\n");
+                }
+                else
+                {
+                    dbg_log(DBG_LOG, "100M\n");
+                }
+                
+                if (kENET_MiiHalfDuplex == duplex)
+                {
+                    dbg_log(DBG_LOG, "half dumplex\n");
+                }
+                else
+                {
+                    dbg_log(DBG_LOG, "full dumplex\n");
+                }
+                
+                if ((imxrt_eth_device.speed != speed) || (imxrt_eth_device.duplex != duplex))
+                {
+                    imxrt_eth_device.speed = (enet_mii_speed_t)speed; 
+                    imxrt_eth_device.duplex = (enet_mii_duplex_t)duplex;
+                    
+                    dbg_log(DBG_LOG, "link up, and update eth mode.\n");
+                    rt_imxrt_eth_init((rt_device_t)&imxrt_eth_device);
+                }
+                else
+                {
+                    dbg_log(DBG_LOG, "link up, eth not need re-config.\n");
+                }
+                dbg_log(DBG_LOG, "link up.\n");
+                eth_device_linkchange(&imxrt_eth_device.parent, RT_TRUE);
+            }
+            else        // link down
+            {
+                dbg_log(DBG_LOG, "link down.\n");
+                eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE);
+            }
+        }
+        
+        rt_thread_delay(RT_TICK_PER_SECOND * 2);
+    }
+}
+
 static int rt_hw_imxrt_eth_init(void)
 {
     rt_err_t state;
 
+    _enet_io_init();
+    _enet_clk_init();
+    
     /* OUI 00-80-E1 STMICROELECTRONICS. */
     imxrt_eth_device.dev_addr[0] = 0x00;
     imxrt_eth_device.dev_addr[1] = 0x80;
@@ -588,6 +633,9 @@ static int rt_hw_imxrt_eth_init(void)
     imxrt_eth_device.dev_addr[3] = 0x12;
     imxrt_eth_device.dev_addr[4] = 0x34;
     imxrt_eth_device.dev_addr[5] = 0x56;
+    
+    imxrt_eth_device.speed = kENET_MiiSpeed100M; 
+    imxrt_eth_device.duplex = kENET_MiiFullDuplex;
 
     imxrt_eth_device.enet_base = ENET;
 
@@ -617,6 +665,22 @@ static int rt_hw_imxrt_eth_init(void)
     {
         dbg_log(DBG_LOG, "eth_device_init faild: %d\r\n", state);
     }
+    
+    eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE);
+    
+    /* start phy monitor */
+    {
+        rt_thread_t tid;
+        tid = rt_thread_create("phy",
+                               phy_monitor_thread_entry,
+                               RT_NULL,
+                               512,
+                               RT_THREAD_PRIORITY_MAX - 2,
+                               2);
+        if (tid != RT_NULL)
+            rt_thread_startup(tid);
+    }
+    
     return state;
 }
 INIT_DEVICE_EXPORT(rt_hw_imxrt_eth_init);