]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / STM32Fxx / NetworkInterface.c
index b9278c0429f610119232cbb4283452b56f39d4cb..84019d6375d6b32bcbcdf90a7988134bc9335078 100644 (file)
@@ -44,26 +44,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "FreeRTOS_Sockets.h"
 #include "FreeRTOS_IP_Private.h"
 #include "FreeRTOS_DNS.h"
+#include "FreeRTOS_ARP.h"
 #include "NetworkBufferManagement.h"
 #include "NetworkInterface.h"
+#include "phyHandling.h"
 
 /* ST includes. */
-#include "stm32f4xx_hal.h"
-
-#ifndef        BMSR_LINK_STATUS
-       #define BMSR_LINK_STATUS            0x0004UL
-#endif
-
-#ifndef        PHY_LS_HIGH_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
-       receiving packets. */
-       #define PHY_LS_HIGH_CHECK_TIME_MS       15000
+#if defined( STM32F7xx )
+       #include "stm32f7xx_hal.h"
+#elif defined( STM32F4xx )
+       #include "stm32f4xx_hal.h"
+#elif defined( STM32F2xx )
+       #include "stm32f2xx_hal.h"
+#elif !defined( _lint )        /* Lint does not like an #error */
+       #error What part?
 #endif
 
-#ifndef        PHY_LS_LOW_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still low every second. */
-       #define PHY_LS_LOW_CHECK_TIME_MS        1000
-#endif
+#include "stm32fxx_hal_eth.h"
 
 /* Interrupt events to process.  Currently only the Rx event is processed
 although code for other events is included to allow for possible future
@@ -78,77 +75,19 @@ expansion. */
          ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
          ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
 
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_00_BMCR                        0x00    /* Basic Mode Control Register */
-#define PHY_REG_01_BMSR                        0x01    /* Basic Mode Status Register */
-#define PHY_REG_02_PHYSID1             0x02    /* PHYS ID 1 */
-#define PHY_REG_03_PHYSID2             0x03    /* PHYS ID 2 */
-#define PHY_REG_04_ADVERTISE   0x04    /* Advertisement control reg */
-
-#define PHY_ID_LAN8720         0x0007c0f0
-#define PHY_ID_DP83848I                0x20005C90
-
-#ifndef USE_STM324xG_EVAL
-       #define USE_STM324xG_EVAL       1
+#ifndef niEMAC_HANDLER_TASK_PRIORITY
+       #define niEMAC_HANDLER_TASK_PRIORITY    configMAX_PRIORITIES - 1
 #endif
 
-#if( USE_STM324xG_EVAL == 0 )
-       #define EXPECTED_PHY_ID                 PHY_ID_LAN8720
-       #define PHY_REG_1F_PHYSPCS              0x1F    /* 31 RW PHY Special Control Status */
-       /* Use 3 bits in register 31 */
-       #define PHYSPCS_SPEED_MASK              0x0C
-       #define PHYSPCS_SPEED_10                0x04
-       #define PHYSPCS_SPEED_100               0x08
-       #define PHYSPCS_FULL_DUPLEX             0x10
-#else
-       #define EXPECTED_PHY_ID         PHY_ID_DP83848I
+#define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
 
-       #define PHY_REG_10_PHY_SR               0x10    /* PHY status register Offset */
-       #define PHY_REG_19_PHYCR                0x19    /* 25 RW PHY Control Register */
+#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )
+       #warning Consider enabling checksum offloading
 #endif
 
-/* Some defines used internally here to indicate preferences about speed, MDIX
-(wired direct or crossed), and duplex (half or full). */
-#define        PHY_SPEED_10       1
-#define        PHY_SPEED_100      2
-#define        PHY_SPEED_AUTO     (PHY_SPEED_10|PHY_SPEED_100)
-
-#define        PHY_MDIX_DIRECT    1
-#define        PHY_MDIX_CROSSED   2
-#define        PHY_MDIX_AUTO      (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
-
-#define        PHY_DUPLEX_HALF    1
-#define        PHY_DUPLEX_FULL    2
-#define        PHY_DUPLEX_AUTO    (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
-
-#define PHY_AUTONEGO_COMPLETE    ((uint16_t)0x0020)  /*!< Auto-Negotiation process completed   */
-
-/*
- * Description of all capabilities that can be advertised to
- * the peer (usually a switch or router).
- */
-#define ADVERTISE_CSMA                 0x0001          /* Only selector supported. */
-#define ADVERTISE_10HALF               0x0020          /* Try for 10mbps half-duplex. */
-#define ADVERTISE_10FULL               0x0040          /* Try for 10mbps full-duplex. */
-#define ADVERTISE_100HALF              0x0080          /* Try for 100mbps half-duplex. */
-#define ADVERTISE_100FULL              0x0100          /* Try for 100mbps full-duplex. */
-
-#define ADVERTISE_ALL                  ( ADVERTISE_10HALF | ADVERTISE_10FULL | \
-                                                                 ADVERTISE_100HALF | ADVERTISE_100FULL)
-
-/*
- * Value for the 'PHY_REG_00_BMCR', the PHY's Basic Mode Control Register
- */
-#define BMCR_FULLDPLX                  0x0100          /* Full duplex. */
-#define BMCR_ANRESTART                 0x0200          /* Auto negotiation restart. */
-#define BMCR_ANENABLE                  0x1000          /* Enable auto negotiation. */
-#define BMCR_SPEED100                  0x2000          /* Select 100Mbps. */
-#define BMCR_RESET                             0x8000          /* Reset the PHY. */
-
-#define PHYCR_MDIX_EN                  0x8000          /* Enable Auto MDIX. */
-#define PHYCR_MDIX_FORCE               0x4000          /* Force MDIX crossed. */
-
-#define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
+#ifndef niDESCRIPTOR_WAIT_TIME_MS
+       #define niDESCRIPTOR_WAIT_TIME_MS               250uL
+#endif
 
 /*
  * Most users will want a PHY that negotiates about
@@ -191,6 +130,31 @@ FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
        #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
 #endif
 
+/* Two choices must be made: RMII versus MII,
+and the index of the PHY in use ( between 0 and 31 ). */
+#ifndef ipconfigUSE_RMII
+       #ifdef STM32F7xx
+               #define ipconfigUSE_RMII        1
+       #else
+               #define ipconfigUSE_RMII        0
+       #endif /* STM32F7xx */
+#endif /* ipconfigUSE_RMII */
+
+#if( ipconfigUSE_RMII != 0 )
+       #warning Using RMII, make sure if this is correct
+#else
+       #warning Using MII, make sure if this is correct
+#endif
+
+typedef enum
+{
+    eMACInit,   /* Must initialise MAC. */
+    eMACPass,   /* Initialisation was successful. */
+    eMACFailed, /* Initialisation failed. */
+} eMAC_INIT_STATUS_TYPE;
+
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
+
 /*-----------------------------------------------------------*/
 
 /*
@@ -231,43 +195,30 @@ static void prvDMATxDescListInit( void );
  */
 static void prvDMARxDescListInit( void );
 
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       /* After packets have been sent, the network
-       buffers will be released. */
-       static void vClearTXBuffers( void );
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+/* After packets have been sent, the network
+buffers will be released. */
+static void vClearTXBuffers( void );
 
 /*-----------------------------------------------------------*/
 
-typedef struct _PhyProperties_t
-{
-       uint8_t speed;
-       uint8_t mdix;
-       uint8_t duplex;
-       uint8_t spare;
-} PhyProperties_t;
-
 /* Bit map of outstanding ETH interrupt events for processing.  Currently only
 the Rx interrupt is handled, although code is included for other events to
 enable future expansion. */
 static volatile uint32_t ulISREvents;
 
-/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
-static uint32_t ulPHYLinkStatus = 0;
-
 #if( ipconfigUSE_LLMNR == 1 )
        static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
 #endif
 
+static EthernetPhy_t xPhyObject;
+
 /* Ethernet handle. */
 static ETH_HandleTypeDef xETH;
 
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       /* xTXDescriptorSemaphore is a counting semaphore with
-       a maximum count of ETH_TXBUFNB, which is the number of
-       DMA TX descriptors. */
-       static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+/* xTXDescriptorSemaphore is a counting semaphore with
+a maximum count of ETH_TXBUFNB, which is the number of
+DMA TX descriptors. */
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
 
 /*
  * Note: it is adviced to define both
@@ -282,30 +233,39 @@ static ETH_HandleTypeDef xETH;
  * TX buffers are allocated in a zero-copy driver.
  */
 /* MAC buffers: ---------------------------------------------------------*/
-__ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ] __ALIGN_END;/* Ethernet Rx MA Descriptor */
-#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
-       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; /* Ethernet Receive Buffer */
-#endif
 
-__ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ] __ALIGN_END;/* Ethernet Tx DMA Descriptor */
-#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
-       __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; /* Ethernet Transmit Buffer */
+/* Put the DMA descriptors in '.first_data'.
+This is important for STM32F7, which has an L1 data cache.
+The first 64KB of the SRAM is not cached.
+See README.TXT in this folder. */
+
+/* Ethernet Rx MA Descriptor */
+__attribute__ ((aligned (32)))
+#if defined(STM32F7xx)
+       __attribute__ ((section(".first_data")))
 #endif
+       ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ];
 
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       /* DMATxDescToClear points to the next TX DMA descriptor
-       that must be cleared by vClearTXBuffers(). */
-       static __IO ETH_DMADescTypeDef  *DMATxDescToClear;
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+       /* Ethernet Receive Buffer */
+       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;
 #endif
 
-/* Value to be written into the 'Basic mode Control Register'. */
-static uint32_t ulBCRvalue;
+/* Ethernet Tx DMA Descriptor */
+__attribute__ ((aligned (32)))
+#if defined(STM32F7xx)
+       __attribute__ ((section(".first_data")))
+#endif
+       ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ];
 
-/* Value to be written into the 'Advertisement Control Register'. */
-static uint32_t ulACRValue;
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+       /* Ethernet Transmit Buffer */
+       __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;
+#endif
 
-/* ucMACAddress as it appears in main.c */
-extern const uint8_t ucMACAddress[ 6 ];
+/* DMATxDescToClear points to the next TX DMA descriptor
+that must be cleared by vClearTXBuffers(). */
+static __IO ETH_DMADescTypeDef  *DMATxDescToClear;
 
 /* Holds the handle of the task used as a deferred interrupt processor.  The
 handle is used so direct notifications can be sent to the task for all EMAC/DMA
@@ -316,28 +276,28 @@ static TaskHandle_t xEMACTaskHandle = NULL;
 const PhyProperties_t xPHYProperties =
 {
        #if( ipconfigETHERNET_AN_ENABLE != 0 )
-               .speed = PHY_SPEED_AUTO,
-               .duplex = PHY_DUPLEX_AUTO,
+               .ucSpeed = PHY_SPEED_AUTO,
+               .ucDuplex = PHY_DUPLEX_AUTO,
        #else
                #if( ipconfigETHERNET_USE_100MB != 0 )
-                       .speed = PHY_SPEED_100,
+                       .ucSpeed = PHY_SPEED_100,
                #else
-                       .speed = PHY_SPEED_10,
+                       .ucSpeed = PHY_SPEED_10,
                #endif
 
                #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
-                       .duplex = PHY_DUPLEX_FULL,
+                       .ucDuplex = PHY_DUPLEX_FULL,
                #else
-                       .duplex = PHY_DUPLEX_HALF,
+                       .ucDuplex = PHY_DUPLEX_HALF,
                #endif
        #endif
 
        #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
-               .mdix = PHY_MDIX_AUTO,
+               .ucMDI_X = PHY_MDIX_AUTO,
        #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
-               .mdix = PHY_MDIX_CROSSED,
+               .ucMDI_X = PHY_MDIX_CROSSED,
        #else
-               .mdix = PHY_MDIX_DIRECT,
+               .ucMDI_X = PHY_MDIX_DIRECT,
        #endif
 };
 
@@ -347,6 +307,8 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
 {
 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 
+       ( void ) heth;
+
        /* Ethernet RX-Complete callback function, elsewhere declared as weak. */
     ulISREvents |= EMAC_IF_RX_EVENT;
        /* Wakeup the prvEMACHandlerTask. */
@@ -358,46 +320,46 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 }
 /*-----------------------------------------------------------*/
 
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
-       {
-       BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-               /* This call-back is only useful in case packets are being sent
-               zero-copy.  Once they're sent, the buffers will be released
-               by the function vClearTXBuffers(). */
-               ulISREvents |= EMAC_IF_TX_EVENT;
-               /* Wakeup the prvEMACHandlerTask. */
-               if( xEMACTaskHandle != NULL )
-               {
-                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
-                       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-               }
+void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
+{
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 
-       }
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+       ( void ) heth;
 
+       /* This call-back is only useful in case packets are being sent
+       zero-copy.  Once they're sent, the buffers will be released
+       by the function vClearTXBuffers(). */
+       ulISREvents |= EMAC_IF_TX_EVENT;
+       /* Wakeup the prvEMACHandlerTask. */
+       if( xEMACTaskHandle != NULL )
+       {
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+       }
+}
 /*-----------------------------------------------------------*/
 
+static void vClearTXBuffers()
+{
+__IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;
+size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       static void vClearTXBuffers()
-       {
-       __IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;
        NetworkBufferDescriptor_t *pxNetworkBuffer;
        uint8_t *ucPayLoad;
-       size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
+#endif
 
-               /* This function is called after a TX-completion interrupt.
-               It will release each Network Buffer used in xNetworkInterfaceOutput().
-               'uxCount' represents the number of descriptors given to DMA for transmission.
-               After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
-               while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
+       /* This function is called after a TX-completion interrupt.
+       It will release each Network Buffer used in xNetworkInterfaceOutput().
+       'uxCount' represents the number of descriptors given to DMA for transmission.
+       After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
+       while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
+       {
+               if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
+               {
+                       break;
+               }
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
                {
-                       if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
-                       {
-                               break;
-                       }
-
                        ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
 
                        if( ucPayLoad != NULL )
@@ -409,15 +371,16 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
                                }
                                DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
                        }
+               }
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */
 
-                       DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
+               DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
 
-                       uxCount--;
-                       /* Tell the counting semaphore that one more TX descriptor is available. */
-                       xSemaphoreGive( xTXDescriptorSemaphore );
-               }
+               uxCount--;
+               /* Tell the counting semaphore that one more TX descriptor is available. */
+               xSemaphoreGive( xTXDescriptorSemaphore );
        }
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+}
 /*-----------------------------------------------------------*/
 
 BaseType_t xNetworkInterfaceInitialise( void )
@@ -425,90 +388,117 @@ BaseType_t xNetworkInterfaceInitialise( void )
 HAL_StatusTypeDef hal_eth_init_status;
 BaseType_t xResult;
 
-       if( xEMACTaskHandle == NULL )
+    if( xMacInitStatus == eMACInit )
        {
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
+               if( xTXDescriptorSemaphore == NULL )
                {
-                       if( xTXDescriptorSemaphore == NULL )
-                       {
-                               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
-                               configASSERT( xTXDescriptorSemaphore );
-                       }
+                       xMacInitStatus = eMACFailed;
                }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
+               else
+               {
+                       /* Initialise ETH */
 
-               /* Initialise ETH */
+                       xETH.Instance = ETH;
+                       xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
+                       xETH.Init.Speed = ETH_SPEED_100M;
+                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+                       /* Value of PhyAddress doesn't matter, will be probed for. */
+                       xETH.Init.PhyAddress = 0;
 
-               xETH.Instance = ETH;
-               xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
-               xETH.Init.Speed = ETH_SPEED_100M;
-               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
-               xETH.Init.PhyAddress = 1;
+                       xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress();
+                       xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
 
-               xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;
-               xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
+                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+                       {
+                               /* using the ETH_CHECKSUM_BY_HARDWARE option:
+                               both the IP and the protocol checksums will be calculated
+                               by the peripheral. */
+                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+                       }
+                       #else
+                       {
+                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
+                       }
+                       #endif
 
-               /* using the ETH_CHECKSUM_BY_HARDWARE option:
-               both the IP and the protocol checksums will be calculated
-               by the peripheral. */
-               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+                       #if( ipconfigUSE_RMII != 0 )
+                       {
+                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
+                       }
+                       #else
+                       {
+                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
+                       }
+                       #endif /* ipconfigUSE_RMII */
 
-               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
-               hal_eth_init_status = HAL_ETH_Init( &xETH );
+                       hal_eth_init_status = HAL_ETH_Init( &xETH );
 
-               /* Only for inspection by debugger. */
-               ( void ) hal_eth_init_status;
+                       /* Only for inspection by debugger. */
+                       ( void ) hal_eth_init_status;
 
-               /* Set the TxDesc and RxDesc pointers. */
-               xETH.TxDesc = DMATxDscrTab;
-               xETH.RxDesc = DMARxDscrTab;
+                       /* Set the TxDesc and RxDesc pointers. */
+                       xETH.TxDesc = DMATxDscrTab;
+                       xETH.RxDesc = DMARxDscrTab;
 
-               /* Make sure that all unused fields are cleared. */
-               memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
-               memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
+                       /* Make sure that all unused fields are cleared. */
+                       memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
+                       memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
 
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
                        /* Initialize Tx Descriptors list: Chain Mode */
                        DMATxDescToClear = DMATxDscrTab;
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
 
-               /* Initialise TX-descriptors. */
-               prvDMATxDescListInit();
+                       /* Initialise TX-descriptors. */
+                       prvDMATxDescListInit();
 
-               /* Initialise RX-descriptors. */
-               prvDMARxDescListInit();
+                       /* Initialise RX-descriptors. */
+                       prvDMARxDescListInit();
 
-               #if( ipconfigUSE_LLMNR != 0 )
-               {
-                       /* Program the LLMNR address at index 1. */
-                       prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
-               }
-               #endif
+                       #if( ipconfigUSE_LLMNR != 0 )
+                       {
+                               /* Program the LLMNR address at index 1. */
+                               prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
+                       }
+                       #endif
 
-               /* Force a negotiation with the Switch or Router and wait for LS. */
-               prvEthernetUpdateConfig( pdTRUE );
+                       /* Force a negotiation with the Switch or Router and wait for LS. */
+                       prvEthernetUpdateConfig( pdTRUE );
 
-               /* The deferred interrupt handler task is created at the highest
-               possible priority to ensure the interrupt handler can return directly
-               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can
-               notify the task when there is something to process. */
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
+                       /* The deferred interrupt handler task is created at the highest
+                       possible priority to ensure the interrupt handler can return directly
+                       to it.  The task's handle is stored in xEMACTaskHandle so interrupts can
+                       notify the task when there is something to process. */
+                       if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS )
+                       {
+                               /* The xTXDescriptorSemaphore and the task are created successfully. */
+                               xMacInitStatus = eMACPass;
+                       }
+                       else
+                       {
+                               xMacInitStatus = eMACFailed;
+                       }
+               }
        } /* if( xEMACTaskHandle == NULL ) */
 
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+       if( xMacInitStatus != eMACPass )
        {
-               xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
-               xResult = pdPASS;
-               FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
+               /* EMAC initialisation failed, return pdFAIL. */
+               xResult = pdFAIL;
        }
        else
        {
-               /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
-               and it will keep on checking the PHY and set ulPHYLinkStatus when necessary. */
-               xResult = pdFAIL;
-               FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
+               if( xPhyObject.ulLinkStatusMask != 0uL )
+               {
+                       xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
+                       xResult = pdPASS;
+                       FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
+               }
+               else
+               {
+                       /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
+                       and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
+                       xResult = pdFAIL;
+               }
        }
        /* When returning non-zero, the stack will become active and
     start DHCP (in configured) */
@@ -542,6 +532,10 @@ BaseType_t xIndex;
                        /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
                        pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
                }
+               else
+               {
+                       pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL );
+               }
 
                /* Initialize the next descriptor with the Next Descriptor Polling Enable */
                if( xIndex < ETH_TXBUFNB - 1 )
@@ -625,6 +619,8 @@ static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8
 {
 uint32_t ulTempReg;
 
+       ( void ) heth;
+
        /* Calculate the selected MAC address high register. */
        ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
 
@@ -647,46 +643,38 @@ __IO ETH_DMADescTypeDef *pxDmaTxDesc;
 /* Do not wait too long for a free TX DMA buffer. */
 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
 
-       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+       /* Open a do {} while ( 0 ) loop to be able to call break. */
+       do
        {
-       ProtocolPacket_t *pxPacket;
+               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+               {
+               ProtocolPacket_t *pxPacket;
 
-               /* If the peripheral must calculate the checksum, it wants
-               the protocol checksum to have a value of zero. */
-               pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
+                       /* If the peripheral must calculate the checksum, it wants
+                       the protocol checksum to have a value of zero. */
+                       pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
 
-               if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
-               {
-                       pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
+                       if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+                       {
+                               pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
+                       }
                }
-       }
-       #endif
-
-       /* Open a do {} while ( 0 ) loop to be able to call break. */
-       do
-       {
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+               #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
+               if( xPhyObject.ulLinkStatusMask != 0 )
                {
-                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+                       if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
                        {
-                               if( xTXDescriptorSemaphore == NULL )
-                               {
-                                       break;
-                               }
-                               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
-                               {
-                                       /* Time-out waiting for a free TX descriptor. */
-                                       break;
-                               }
+                               /* Time-out waiting for a free TX descriptor. */
+                               break;
                        }
-                       #endif /* ipconfigZERO_COPY_TX_DRIVER */
 
                        /* This function does the actual transmission of the packet. The packet is
                        contained in 'pxDescriptor' that is passed to the function. */
                        pxDmaTxDesc = xETH.TxDesc;
 
                        /* Is this buffer available? */
-                       if( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 )
+                       configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );
+
                        {
                                /* Is this buffer available? */
                                /* Get bytes in current buffer. */
@@ -701,32 +689,54 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
                                {
                                        /* Copy the bytes. */
                                        memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
-                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL;
                                }
                                #else
                                {
+                                       configASSERT( bReleaseAfterSend != 0 );
+
                                        /* Move the buffer. */
                                        pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
-                                       /* Ask to set the IPv4 checksum.
-                                       Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
-                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
                                        /* The Network Buffer has been passed to DMA, no need to release it. */
                                        bReleaseAfterSend = pdFALSE_UNSIGNED;
                                }
                                #endif /* ipconfigZERO_COPY_TX_DRIVER */
 
+                               /* Ask to set the IPv4 checksum.
+                               Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
+                               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+                               {
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
+                               }
+                               #else
+                               {
+                                       pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC );
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_IC;
+                               }
+                               #endif
+                               
+
                                /* Prepare transmit descriptors to give to DMA. */
 
                                /* Set LAST and FIRST segment */
                                pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
                                /* Set frame size */
                                pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
+
+                               #if( NETWORK_BUFFERS_CACHED     != 0 )
+                               {
+                               BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );
+                               uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );
+                                       cache_clean_invalidate_by_addr( pulBuffer, xlength );
+                               }
+                               #endif
+
                                /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
                                pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
 
                                /* Point to next descriptor */
                                xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
-       
+                               /* Ensure completion of memory access */
+                               __DSB();
                                /* Resume DMA transmission*/
                                xETH.Instance->DMATPDR = 0;
                                iptraceNETWORK_INTERFACE_TRANSMIT();
@@ -801,20 +811,24 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
 
                if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
                {
-                       uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
+               uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort );
+               uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort );
 
-                       if( ( xPortHasUDPSocket( port ) == pdFALSE )
+                       if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )
                        #if ipconfigUSE_LLMNR == 1
-                               && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
+                               && ( usDestinationPort != ipLLMNR_PORT )
+                               && ( usSourcePort != ipLLMNR_PORT )
                        #endif
                        #if ipconfigUSE_NBNS == 1
-                               && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
+                               && ( usDestinationPort != ipNBNS_PORT )
+                               && ( usSourcePort != ipNBNS_PORT )
                        #endif
                        #if ipconfigUSE_DNS == 1
-                               && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
+                               && ( usSourcePort != ipDNS_PORT )
                        #endif
                                ) {
                                /* Drop this packet, not for this device. */
+                               FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) );
                                return pdFALSE;
                        }
                }
@@ -824,20 +838,59 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
 }
 /*-----------------------------------------------------------*/
 
+static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )
+{
+IPStackEvent_t xRxEvent;
+
+       xRxEvent.eEventType = eNetworkRxEvent;
+       xRxEvent.pvData = ( void * ) pxDescriptor;
+
+       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
+       {
+               /* The buffer could not be sent to the stack so must be released again.
+               This is a deferred handler taskr, not a real interrupt, so it is ok to
+               use the task level function here. */
+               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
+               {
+                       do
+                       {
+                               NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;
+                               vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+                               pxDescriptor = pxNext;
+                       } while( pxDescriptor != NULL );
+               }
+               #else
+               {
+                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+               }
+               #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */
+               iptraceETHERNET_RX_EVENT_LOST();
+               FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );
+       }
+       else
+       {
+               iptraceNETWORK_INTERFACE_RECEIVE();
+       }
+}
+
 static BaseType_t prvNetworkInterfaceInput( void )
 {
 NetworkBufferDescriptor_t *pxCurDescriptor;
 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
-BaseType_t xReceivedLength, xAccepted;
+#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
+       NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;
+       NetworkBufferDescriptor_t *pxLastDescriptor = NULL;
+#endif
+BaseType_t xReceivedLength = 0;
 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;
-xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS );
 uint8_t *pucBuffer;
 
        pxDMARxDescriptor = xETH.RxDesc;
 
-       if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
+       while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u )
        {
+       BaseType_t xAccepted = pdTRUE;
                /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
                xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
 
@@ -847,18 +900,13 @@ uint8_t *pucBuffer;
                /* Chained Mode */    
                /* Selects the next DMA Rx descriptor list for next buffer to read */ 
                xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
-       }
-       else
-       {
-               xReceivedLength = 0;
-       }
 
-       /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
-       /* In order to make the code easier and faster, only packets in a single buffer
-       will be accepted.  This can be done by making the buffers large enough to
-       hold a complete Ethernet packet (1536 bytes). */
-       if( xReceivedLength > 0ul && xReceivedLength < ETH_RX_BUF_SIZE ) 
-       {
+               /* In order to make the code easier and faster, only packets in a single buffer
+               will be accepted.  This can be done by making the buffers large enough to
+               hold a complete Ethernet packet (1536 bytes).
+               Therefore, two sanity checks: */
+               configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );
+
                if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
                {
                        /* Not an Ethernet frame-type or a checmsum error. */
@@ -904,20 +952,28 @@ uint8_t *pucBuffer;
                if( xAccepted != pdFALSE )
                {
                        pxCurDescriptor->xDataLength = xReceivedLength;
-                       xRxEvent.pvData = ( void * ) pxCurDescriptor;
-
-                       /* Pass the data to the TCP/IP task for processing. */
-                       if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
+                       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
                        {
-                               /* Could not send the descriptor into the TCP/IP stack, it
-                               must be released. */
-                               vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
-                               iptraceETHERNET_RX_EVENT_LOST();
+                               pxCurDescriptor->pxNextBuffer = NULL;
+
+                               if( pxFirstDescriptor == NULL )
+                               {
+                                       // Becomes the first message
+                                       pxFirstDescriptor = pxCurDescriptor;
+                               }
+                               else if( pxLastDescriptor != NULL )
+                               {
+                                       // Add to the tail
+                                       pxLastDescriptor->pxNextBuffer = pxCurDescriptor;
+                               }
+
+                               pxLastDescriptor = pxCurDescriptor;
                        }
-                       else
+                       #else
                        {
-                               iptraceNETWORK_INTERFACE_RECEIVE();
+                               prvPassEthMessages( pxCurDescriptor );
                        }
+                       #endif
                }
 
                /* Release descriptors to DMA */
@@ -940,6 +996,8 @@ uint8_t *pucBuffer;
                pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  
                pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
 
+               /* Ensure completion of memory access */
+               __DSB();
                /* When Rx Buffer unavailable flag is set clear it and resume
                reception. */
                if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
@@ -950,311 +1008,138 @@ uint8_t *pucBuffer;
                        /* Resume DMA reception. */
                        xETH.Instance->DMARPDR = 0;
                }
+               pxDMARxDescriptor = xETH.RxDesc;
        }
 
-       return ( xReceivedLength > 0 );
-}
-/*-----------------------------------------------------------*/
-
-void vMACBProbePhy( void )
-{
-uint32_t ulConfig, ulAdvertise, ulLower, ulUpper, ulMACPhyID, ulValue;
-TimeOut_t xPhyTime;
-TickType_t xRemTime = 0;
-#if( EXPECTED_PHY_ID == PHY_ID_DP83848I )
-       uint32_t ulPhyControl;
-#endif
-
-       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_03_PHYSID2, &ulLower);
-       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_02_PHYSID1, &ulUpper);
-
-       ulMACPhyID = ( ( ulUpper << 16 ) & 0xFFFF0000 ) | ( ulLower & 0xFFF0 );
-
-       /* The expected ID for the 'LAN8720' is 0x0007c0f0. */
-       /* The expected ID for the 'DP83848I' is 0x20005C90. */
-
-       FreeRTOS_printf( ( "PHY ID %lX (%s)\n", ulMACPhyID,
-               ( ulMACPhyID == EXPECTED_PHY_ID ) ? "OK" : "Unknown" ) );
-
-       /* Remove compiler warning if FreeRTOS_printf() is not defined. */
-       ( void ) ulMACPhyID;
-
-    /* Set advertise register. */
-       if( ( xPHYProperties.speed == PHY_SPEED_AUTO ) && ( xPHYProperties.duplex == PHY_DUPLEX_AUTO ) )
+       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
        {
-               ulAdvertise = ADVERTISE_CSMA | ADVERTISE_ALL;
-               /* Reset auto-negotiation capability. */
-       }
-       else
-       {
-               ulAdvertise = ADVERTISE_CSMA;
-
-               if( xPHYProperties.speed == PHY_SPEED_AUTO )
-               {
-                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
-                       {
-                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_100FULL;
-                       }
-                       else
-                       {
-                               ulAdvertise |= ADVERTISE_10HALF | ADVERTISE_100HALF;
-                       }
-               }
-               else if( xPHYProperties.duplex == PHY_DUPLEX_AUTO )
+               if( pxFirstDescriptor != NULL )
                {
-                       if( xPHYProperties.speed == PHY_SPEED_10 )
-                       {
-                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_10HALF;
-                       }
-                       else
-                       {
-                               ulAdvertise |= ADVERTISE_100FULL | ADVERTISE_100HALF;
-                       }
-               }
-               else if( xPHYProperties.speed == PHY_SPEED_100 )
-               {
-                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
-                       {
-                               ulAdvertise |= ADVERTISE_100FULL;
-                       }
-                       else
-                       {
-                               ulAdvertise |= ADVERTISE_100HALF;
-                       }
-               }
-               else
-               {
-                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
-                       {
-                               ulAdvertise |= ADVERTISE_10FULL;
-                       }
-                       else
-                       {
-                               ulAdvertise |= ADVERTISE_10HALF;
-                       }
+                       prvPassEthMessages( pxFirstDescriptor );
                }
        }
+       #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */
 
-       /* Read Control register. */
-       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
-
-       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig | BMCR_RESET );
-       xRemTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL );
-       vTaskSetTimeOutState( &xPhyTime );
+       return ( xReceivedLength > 0 );
+}
+/*-----------------------------------------------------------*/
 
-       for( ; ; )
-       {
-               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulValue );
-               if( ( ulValue & BMCR_RESET ) == 0 )
-               {
-                       FreeRTOS_printf( ( "BMCR_RESET ready\n" ) );
-                       break;
-               }
-               if( xTaskCheckForTimeOut( &xPhyTime, &xRemTime ) != pdFALSE )
-               {
-                       FreeRTOS_printf( ( "BMCR_RESET timed out\n" ) );
-                       break;
-               }
-       }
-       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig & ~BMCR_RESET );
 
-       vTaskDelay( pdMS_TO_TICKS( 50ul ) );
+BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
+{
+uint16_t usPrevAddress = xETH.Init.PhyAddress;
+BaseType_t xResult;
+HAL_StatusTypeDef xHALResult;
 
-    /* Write advertise register. */
-       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulAdvertise );
+       xETH.Init.PhyAddress = xAddress;
+       xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );
+       xETH.Init.PhyAddress = usPrevAddress;
 
-       /*
-                       AN_EN        AN1         AN0       Forced Mode
-                         0           0           0        10BASE-T, Half-Duplex
-                         0           0           1        10BASE-T, Full-Duplex
-                         0           1           0        100BASE-TX, Half-Duplex
-                         0           1           1        100BASE-TX, Full-Duplex
-                       AN_EN        AN1         AN0       Advertised Mode
-                         1           0           0        10BASE-T, Half/Full-Duplex
-                         1           0           1        100BASE-TX, Half/Full-Duplex
-                         1           1           0        10BASE-T Half-Duplex
-                                                                                          100BASE-TX, Half-Duplex
-                         1           1           1        10BASE-T, Half/Full-Duplex
-                                                                                          100BASE-TX, Half/Full-Duplex
-       */
-
-    /* Read Control register. */
-       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
-
-       ulConfig &= ~( BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX );
-
-       /* HT 12/9/14: always set AN-restart and AN-enable, even though the choices
-       are limited. */
-       ulConfig |= (BMCR_ANRESTART | BMCR_ANENABLE);
-
-       if( xPHYProperties.speed == PHY_SPEED_100 )
+       if( xHALResult == HAL_OK )
        {
-               ulConfig |= BMCR_SPEED100;
+               xResult = 0;
        }
-       else if( xPHYProperties.speed == PHY_SPEED_10 )
+       else
        {
-               ulConfig &= ~BMCR_SPEED100;
+               xResult = -1;
        }
+       return xResult;
+}
+/*-----------------------------------------------------------*/
 
-       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
-       {
-               ulConfig |= BMCR_FULLDPLX;
-       }
-       else if( xPHYProperties.duplex == PHY_DUPLEX_HALF )
-       {
-               ulConfig &= ~BMCR_FULLDPLX;
-       }
+BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
+{
+uint16_t usPrevAddress = xETH.Init.PhyAddress;
+BaseType_t xResult;
+HAL_StatusTypeDef xHALResult;
+
+       xETH.Init.PhyAddress = xAddress;
+       xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );
+       xETH.Init.PhyAddress = usPrevAddress;
 
-       #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
+       if( xHALResult == HAL_OK )
        {
+               xResult = 0;
        }
-       #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
+       else
        {
-               /* Read PHY Control register. */
-               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_19_PHYCR, &ulPhyControl );
-
-               /* Clear bits which might get set: */
-               ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );
-
-               if( xPHYProperties.mdix == PHY_MDIX_AUTO )
-               {
-                       ulPhyControl |= PHYCR_MDIX_EN;
-               }
-               else if( xPHYProperties.mdix == PHY_MDIX_CROSSED )
-               {
-                       /* Force direct link = Use crossed RJ45 cable. */
-                       ulPhyControl &= ~PHYCR_MDIX_FORCE;
-               }
-               else
-               {
-                       /* Force crossed link = Use direct RJ45 cable. */
-                       ulPhyControl |= PHYCR_MDIX_FORCE;
-               }
-               /* update PHY Control Register. */
-               HAL_ETH_WritePHYRegister( &xETH, PHY_REG_19_PHYCR, ulPhyControl );
+               xResult = -1;
        }
-       #endif
-       FreeRTOS_printf( ( "+TCP: advertise: %lX config %lX\n", ulAdvertise, ulConfig ) );
+       return xResult;
+}
+/*-----------------------------------------------------------*/
 
-       /* Now the two values to global values for later use. */
-       ulBCRvalue = ulConfig;
-       ulACRValue = ulAdvertise;
+void vMACBProbePhy( void )
+{
+       vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
+       xPhyDiscover( &xPhyObject );
+       xPhyConfigure( &xPhyObject, &xPHYProperties );
 }
 /*-----------------------------------------------------------*/
 
 static void prvEthernetUpdateConfig( BaseType_t xForce )
 {
-__IO uint32_t ulTimeout = 0;
-uint32_t ulRegValue = 0;
-
-       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS %d Force %d\n",
-               ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ,
-               xForce ) );
+       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
+               xPhyObject.ulLinkStatusMask,
+               ( int )xForce ) );
 
-       if( ( xForce != pdFALSE ) || ( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) )
+       if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
        {
                /* Restart the auto-negotiation. */
                if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
                {
-                       /* Enable Auto-Negotiation. */
-                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue | BMCR_ANRESTART );
-                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulACRValue);
+                       xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
 
-                       /* Wait until the auto-negotiation will be completed */
-                       do
+                       /* Configure the MAC with the Duplex Mode fixed by the
+                       auto-negotiation process. */
+                       if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
                        {
-                               ulTimeout++;
-                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue );
-                       } while( ( ( ulRegValue & PHY_AUTONEGO_COMPLETE) == 0 ) && ( ulTimeout < PHY_READ_TO ) );
-
-                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue & ~BMCR_ANRESTART );
-
-                       if( ulTimeout < PHY_READ_TO )
+                               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+                       }
+                       else
                        {
-                               /* Reset Timeout counter. */
-                               ulTimeout = 0;
-
-                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue);
-                               if( ( ulRegValue & BMSR_LINK_STATUS ) != 0 )
-                               {
-                                       ulPHYLinkStatus |= BMSR_LINK_STATUS;
-                               }
-                               else
-                               {
-                                       ulPHYLinkStatus &= ~( BMSR_LINK_STATUS );
-                               }
-
-                               #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
-                               {
-                               /* 31 RW PHY Special Control Status */
-                               uint32_t ulControlStatus;
-
-                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_1F_PHYSPCS, &ulControlStatus);
-                                       ulRegValue = 0;
-                                       if( ( ulControlStatus & PHYSPCS_FULL_DUPLEX ) != 0 )
-                                       {
-                                               ulRegValue |= PHY_DUPLEX_STATUS;
-                                       }
-                                       if( ( ulControlStatus & PHYSPCS_SPEED_MASK ) == PHYSPCS_SPEED_10 )
-                                       {
-                                               ulRegValue |= PHY_SPEED_STATUS;
-                                       }
-
-                               }
-                               #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
-                               {
-                                       /* Read the result of the auto-negotiation. */
-                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_10_PHY_SR, &ulRegValue);
-                               }
-                               #endif
-                               FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n",
-                                       ulRegValue,
-                                       (ulRegValue & PHY_DUPLEX_STATUS) ? "full" : "half",
-                                       (ulRegValue & PHY_SPEED_STATUS) ? 10 : 100,
-                                       ((ulPHYLinkStatus |= BMSR_LINK_STATUS) != 0) ? "high" : "low" ) );
-
-                               /* Configure the MAC with the Duplex Mode fixed by the
-                               auto-negotiation process. */
-                               if( ( ulRegValue & PHY_DUPLEX_STATUS ) != ( uint32_t ) RESET )
-                               {
-                                       /* Set Ethernet duplex mode to Full-duplex following the
-                                       auto-negotiation. */
-                                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
-                               }
-                               else
-                               {
-                                       /* Set Ethernet duplex mode to Half-duplex following the
-                                       auto-negotiation. */
-                                       xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
-                               }
+                               xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
+                       }
 
-                               /* Configure the MAC with the speed fixed by the
-                               auto-negotiation process. */
-                               if( ( ulRegValue & PHY_SPEED_STATUS) != 0 )
-                               {
-                                       /* Set Ethernet speed to 10M following the
-                                       auto-negotiation. */
-                                       xETH.Init.Speed = ETH_SPEED_10M;
-                               }
-                               else
-                               {
-                                       /* Set Ethernet speed to 100M following the
-                                       auto-negotiation. */
-                                       xETH.Init.Speed = ETH_SPEED_100M;
-                               }
-                       }       /* if( ulTimeout < PHY_READ_TO ) */
+                       /* Configure the MAC with the speed fixed by the
+                       auto-negotiation process. */
+                       if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
+                       {
+                               xETH.Init.Speed = ETH_SPEED_10M;
+                       }
+                       else
+                       {
+                               xETH.Init.Speed = ETH_SPEED_100M;
+                       }
                }
                else /* AutoNegotiation Disable */
                {
-               uint16_t usValue;
-
                        /* Check parameters */
                        assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
                        assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
 
-                       /* Set MAC Speed and Duplex Mode to PHY */
-                       usValue = ( uint16_t ) ( xETH.Init.DuplexMode >> 3 ) | ( uint16_t ) ( xETH.Init.Speed >> 1 );
-                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, usValue );
+                       if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )
+                       {
+                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
+                       }
+                       else
+                       {
+                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
+                       }
+
+                       if( xETH.Init.Speed == ETH_SPEED_10M )
+                       {
+                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
+                       }
+                       else
+                       {
+                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
+                       }
+
+                       xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
+
+                       /* Use predefined (fixed) configuration. */
+                       xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
                }
 
                /* ETHERNET MAC Re-Configuration */
@@ -1275,7 +1160,7 @@ BaseType_t xGetPhyLinkStatus( void )
 {
 BaseType_t xReturn;
 
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+       if( xPhyObject.ulLinkStatusMask != 0 )
        {
                xReturn = pdPASS;
        }
@@ -1288,27 +1173,43 @@ BaseType_t xReturn;
 }
 /*-----------------------------------------------------------*/
 
+/* Uncomment this in case BufferAllocation_1.c is used. */
+
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
+{
+static
+#if defined(STM32F7xx)
+       __attribute__ ((section(".first_data")))
+#endif
+       uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
+uint8_t *ucRAMBuffer = ucNetworkPackets;
+uint32_t ul;
+
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
+       {
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
+               ucRAMBuffer += ETH_MAX_PACKET_SIZE;
+       }
+}
+/*-----------------------------------------------------------*/
+
 static void prvEMACHandlerTask( void *pvParameters )
 {
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
 UBaseType_t uxLastMinBufferCount = 0;
 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
 UBaseType_t uxLastMinQueueSpace = 0;
 #endif
 UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
+BaseType_t xResult;
 const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
 
        /* Remove compiler warnings about unused parameters. */
        ( void ) pvParameters;
 
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
        for( ;; )
        {
+               xResult = 0;
                uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
                if( uxLastMinBufferCount != uxCurrentCount )
                {
@@ -1319,7 +1220,6 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                                uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
                }
 
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
                if( xTXDescriptorSemaphore != NULL )
                {
                static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
@@ -1332,7 +1232,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                        }
 
                }
-               #endif
+
                #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
                {
                        uxCurrentCount = uxGetMinimumIPQueueSpace();
@@ -1357,24 +1257,14 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                        ulISREvents &= ~EMAC_IF_RX_EVENT;
 
                        xResult = prvNetworkInterfaceInput();
-                       if( xResult > 0 )
-                       {
-                               while( prvNetworkInterfaceInput() > 0 )
-                               {
-                               }
-                       }
                }
 
                if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
                {
                        /* Code to release TX buffers if zero-copy is used. */
                        ulISREvents &= ~EMAC_IF_TX_EVENT;
-                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-                       {
-                               /* Check if DMA packets have been delivered. */
-                               vClearTXBuffers();
-                       }
-                       #endif
+                       /* Check if DMA packets have been delivered. */
+                       vClearTXBuffers();
                }
 
                if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
@@ -1382,34 +1272,10 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                        /* Future extension: logging about errors that occurred. */
                        ulISREvents &= ~EMAC_IF_ERR_EVENT;
                }
-
-               if( xResult > 0 )
+               if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
                {
-                       /* A packet was received. No need to check for the PHY status now,
-                       but set a timer to check it later on. */
-                       vTaskSetTimeOutState( &xPhyTime );
-                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       xResult = 0;
-               }
-               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
-               {
-                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &xStatus );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
-                       {
-                               ulPHYLinkStatus = xStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
-                               prvEthernetUpdateConfig( pdFALSE );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
+                       /* Something has changed to a Link Status, need re-check. */
+                       prvEthernetUpdateConfig( pdFALSE );
                }
        }
 }
@@ -1419,3 +1285,4 @@ void ETH_IRQHandler( void )
 {
        HAL_ETH_IRQHandler( &xETH );
 }
+