Hi Darius,

On Wed, Oct 21, 2015 at 11:22:30AM +0300, Darius Babrauskas wrote:
> 
> (...)
> 
> – there is a transmit error such as too many retries or a transmit 
> under run.
> 
> (...)

I have two patches against the AVR32 MACB driver in my tree, and it 
look like it might fix your issues.

- macb-nonblocking-asf-3.5.1-0000.patch

The MACB driver does not set the correct speed/duplex from MAC to PHY in 
case of speed/duplex link change (i.e. if the remote device is replaced 
or if a damaged cable make a negotiation restart and set the speed from 
100 to 10). Here is my patch against ASF 3.5.1 which fixes this issue as 
well as being non blocking if ETHERNET_CONF_USE_PHY_IT is set, otherwise 
it behaves the same as before. It is working with or without FreeRTOS.

It was discussed on the avrfreaks forum[1].


- 0001-fixed-crash-if-MACB-failed-to-sent-a-frame-a-failed-.patch

Fix a crash if MACB failed to sent a frame, a failed frame does not set 
the USED/OK bit, so the current implementation locked the circular 
buffer


Hope it helps ! :)

Sylvain


[1] http://www.avrfreaks.net/forum/non-blocking-asf-macb-driver
Date: Fri, 22 Feb 2013 14:15:06 +0000
Subject: [PATCH] fixed crash if MACB failed to sent a frame, a failed
 frame does not set the USED/OK bit, so the current implementation locked the
 circular buffer

---
 src/asf/avr32/drivers/macb/macb.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/src/asf/avr32/drivers/macb/macb.c b/src/asf/avr32/drivers/macb/macb.c
index ac07afe..4fe19e3 100644
--- a/src/asf/avr32/drivers/macb/macb.c
+++ b/src/asf/avr32/drivers/macb/macb.c
@@ -572,30 +572,28 @@ void vClearMACBTxBuffer(void)
   // Tx buffer within the frame just transmitted.  This marks all the buffers
   // as available again.
 
-  // The first buffer in the frame should have the bit set automatically. */
-  if( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_TRANSMIT_OK )
-  {
-    // Loop through the other buffers in the frame.
-    while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_LAST_BUFFER ) )
-    {
-      uxNextBufferToClear++;
-
-      if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
-      {
-        uxNextBufferToClear = 0;
-      }
-
-      xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
-    }
+  xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
 
-    // Start with the next buffer the next time a Tx interrupt is called.
+  // Loop through the other buffers in the frame.
+  while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_LAST_BUFFER ) )
+  {
     uxNextBufferToClear++;
 
-    // Do we need to wrap back to the first buffer?
     if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
     {
       uxNextBufferToClear = 0;
     }
+
+    xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
+  }
+
+  // Start with the next buffer the next time a Tx interrupt is called.
+  uxNextBufferToClear++;
+
+  // Do we need to wrap back to the first buffer?
+  if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
+  {
+    uxNextBufferToClear = 0;
   }
 }
 
-- 
2.5.1

Index: src/asf/avr32/drivers/macb/macb.c
===================================================================
--- src/asf/avr32/drivers/macb/macb.c	(revision 307)
+++ src/asf/avr32/drivers/macb/macb.c	(working copy)
@@ -782,11 +782,67 @@
   macb->ncr &= ~AVR32_MACB_NCR_MPE_MASK;
 }
 
+static void prvSetupMACBConfig(volatile avr32_macb_t *macb)
+{
+  volatile unsigned long lpa, config, advertise;
+
+  // read the LPA configuration of the PHY
+  lpa = ulReadMDIO(macb, PHY_LPA);
+
+  // read the MACB config register
+  config = macb->ncfgr;
+
+  // set advertise register
+#if ETHERNET_CONF_AN_ENABLE == 1
+  advertise = ADVERTISE_CSMA | ADVERTISE_ALL;
+#else
+  advertise = ADVERTISE_CSMA;
+  #if ETHERNET_CONF_USE_100MB
+    #if ETHERNET_CONF_USE_FULL_DUPLEX
+      advertise |= ADVERTISE_100FULL;
+    #else
+      advertise |= ADVERTISE_100HALF;
+    #endif
+  #else
+    #if ETHERNET_CONF_USE_FULL_DUPLEX
+      advertise |= ADVERTISE_10FULL;
+    #else
+      advertise |= ADVERTISE_10HALF;
+    #endif
+  #endif
+#endif
+
+  // if 100MB needed
+  if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL))
+  {
+    config |= AVR32_MACB_SPD_MASK;
+  }
+  else
+  {
+    config &= ~(AVR32_MACB_SPD_MASK);
+  }
+
+  // if FULL DUPLEX needed
+  if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL))
+  {
+    config |= AVR32_MACB_FD_MASK;
+  }
+  else
+  {
+    config &= ~(AVR32_MACB_FD_MASK);
+  }
+
+  // write the MACB config register
+  macb->ncfgr = config;
+}
+
 static bool prvProbePHY(volatile avr32_macb_t *macb)
 {
+#if ETHERNET_CONF_USE_PHY_IT == 0
   volatile unsigned long mii_status;
+#endif /* ETHERNET_CONF_USE_PHY_IT == 0 */
   volatile unsigned long config;
-  unsigned long upper, lower, advertise, lpa;
+  unsigned long upper, lower, advertise;
   volatile unsigned long physID;
 
   // Read Phy Identifier register 1 & 2
@@ -832,40 +888,15 @@
     // update ctrl register
     vWriteMDIO(macb, PHY_BMCR, config);
 
+#if ETHERNET_CONF_USE_PHY_IT == 0
     // loop while link status isn't OK
     do {
       mii_status = ulReadMDIO(macb, PHY_BMSR);
     } while (!(mii_status & BMSR_LSTATUS));
 
-    // read the LPA configuration of the PHY
-    lpa = ulReadMDIO(macb, PHY_LPA);
+    prvSetupMACBConfig(macb);
+#endif /* ETHERNET_CONF_USE_PHY_IT == 0 */
 
-    // read the MACB config register
-    config = AVR32_MACB.ncfgr;
-
-    // if 100MB needed
-    if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL))
-    {
-      config |= AVR32_MACB_SPD_MASK;
-    }
-    else
-    {
-      config &= ~(AVR32_MACB_SPD_MASK);
-    }
-
-    // if FULL DUPLEX needed
-    if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL))
-    {
-      config |= AVR32_MACB_FD_MASK;
-    }
-    else
-    {
-      config &= ~(AVR32_MACB_FD_MASK);
-    }
-
-    // write the MACB config register
-    macb->ncfgr = config;
-
     return true;
   }
   return false;
@@ -1045,6 +1076,10 @@
   // dummy read
   ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR);
 
+  if(ulEventStatus & BMSR_LSTATUS) {
+    prvSetupMACBConfig(&AVR32_MACB);
+  }
+
    // clear interrupt flag on GPIO
   gpio_port->ifrc =  1 << (EXTPHY_MACB_INTERRUPT_PIN%32);
 

Attachment: signature.asc
Description: Digital signature

_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to