]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
Sync FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP with the version in GitHub at (23665258ca...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / STM32Fxx / NetworkInterface.c
index d95165a0441cf45158b5bafa2ecc89ba5abe2535..6fad9216e8aaa5c2f40902cafd5db637f4116d6b 100644 (file)
@@ -4,28 +4,28 @@
  */\r
 \r
 /*\r
- * FreeRTOS+TCP V2.0.11\r
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
- * this software and associated documentation files (the "Software"), to deal in\r
- * the Software without restriction, including without limitation the rights to\r
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
- * the Software, and to permit persons to whom the Software is furnished to do so,\r
- * subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included in all\r
- * copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- *\r
http://aws.amazon.com/freertos\r
http://www.FreeRTOS.org\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
 */\r
 \r
 /* Standard includes. */\r
 #include "FreeRTOS_Sockets.h"\r
 #include "FreeRTOS_IP_Private.h"\r
 #include "FreeRTOS_DNS.h"\r
+#include "FreeRTOS_ARP.h"\r
 #include "NetworkBufferManagement.h"\r
 #include "NetworkInterface.h"\r
 #include "phyHandling.h"\r
 \r
-#define __STM32_HAL_LEGACY   1\r
-\r
 /* ST includes. */\r
 #if defined( STM32F7xx )\r
        #include "stm32f7xx_hal.h"\r
@@ -57,7 +56,7 @@
        #include "stm32f4xx_hal.h"\r
 #elif defined( STM32F2xx )\r
        #include "stm32f2xx_hal.h"\r
-#else\r
+#elif !defined( _lint )        /* Lint does not like an #error */\r
        #error What part?\r
 #endif\r
 \r
@@ -82,6 +81,14 @@ expansion. */
 \r
 #define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */\r
 \r
+#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )\r
+       #warning Consider enabling checksum offloading\r
+#endif\r
+\r
+#ifndef niDESCRIPTOR_WAIT_TIME_MS\r
+       #define niDESCRIPTOR_WAIT_TIME_MS               250uL\r
+#endif\r
+\r
 /*\r
  * Most users will want a PHY that negotiates about\r
  * the connection properties: speed, dmix and duplex.\r
@@ -139,6 +146,15 @@ and the index of the PHY in use ( between 0 and 31 ). */
        #warning Using MII, make sure if this is correct\r
 #endif\r
 \r
+typedef enum\r
+{\r
+    eMACInit,   /* Must initialise MAC. */\r
+    eMACPass,   /* Initialisation was successful. */\r
+    eMACFailed, /* Initialisation failed. */\r
+} eMAC_INIT_STATUS_TYPE;\r
+\r
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -179,9 +195,9 @@ static void prvDMATxDescListInit( void );
  */\r
 static void prvDMARxDescListInit( void );\r
 \r
-       /* After packets have been sent, the network\r
-       buffers will be released. */\r
-       static void vClearTXBuffers( void );\r
+/* After packets have been sent, the network\r
+buffers will be released. */\r
+static void vClearTXBuffers( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -199,10 +215,10 @@ static EthernetPhy_t xPhyObject;
 /* Ethernet handle. */\r
 static ETH_HandleTypeDef xETH;\r
 \r
-       /* xTXDescriptorSemaphore is a counting semaphore with\r
-       a maximum count of ETH_TXBUFNB, which is the number of\r
-       DMA TX descriptors. */\r
-       static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of ETH_TXBUFNB, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
 \r
 /*\r
  * Note: it is adviced to define both\r
@@ -242,11 +258,9 @@ __attribute__ ((section(".first_data")))
        __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;\r
 #endif\r
 \r
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
-       /* DMATxDescToClear points to the next TX DMA descriptor\r
-       that must be cleared by vClearTXBuffers(). */\r
-       static __IO ETH_DMADescTypeDef  *DMATxDescToClear;\r
-#endif\r
+/* DMATxDescToClear points to the next TX DMA descriptor\r
+that must be cleared by vClearTXBuffers(). */\r
+static __IO ETH_DMADescTypeDef  *DMATxDescToClear;\r
 \r
 /* Holds the handle of the task used as a deferred interrupt processor.  The\r
 handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
@@ -267,9 +281,9 @@ const PhyProperties_t xPHYProperties =
                #endif\r
 \r
                #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
-                       .duplex = PHY_DUPLEX_FULL,\r
+                       .ucDuplex = PHY_DUPLEX_FULL,\r
                #else\r
-                       .duplex = PHY_DUPLEX_HALF,\r
+                       .ucDuplex = PHY_DUPLEX_HALF,\r
                #endif\r
        #endif\r
 \r
@@ -288,6 +302,8 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
 {\r
 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
 \r
+       ( void ) heth;\r
+\r
        /* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
     ulISREvents |= EMAC_IF_RX_EVENT;\r
        /* Wakeup the prvEMACHandlerTask. */\r
@@ -299,43 +315,44 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-       void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
-       {\r
-       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
-\r
-               /* This call-back is only useful in case packets are being sent\r
-               zero-copy.  Once they're sent, the buffers will be released\r
-               by the function vClearTXBuffers(). */\r
-               ulISREvents |= EMAC_IF_TX_EVENT;\r
-               /* Wakeup the prvEMACHandlerTask. */\r
-               if( xEMACTaskHandle != NULL )\r
-               {\r
-                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
-                       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
-               }\r
+void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
 \r
+       ( void ) heth;\r
+\r
+       /* This call-back is only useful in case packets are being sent\r
+       zero-copy.  Once they're sent, the buffers will be released\r
+       by the function vClearTXBuffers(). */\r
+       ulISREvents |= EMAC_IF_TX_EVENT;\r
+       /* Wakeup the prvEMACHandlerTask. */\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
        }\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
-       static void vClearTXBuffers()\r
-       {\r
-       __IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;\r
+static void vClearTXBuffers()\r
+{\r
+__IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;\r
 size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
        NetworkBufferDescriptor_t *pxNetworkBuffer;\r
        uint8_t *ucPayLoad;\r
 #endif\r
 \r
-               /* This function is called after a TX-completion interrupt.\r
-               It will release each Network Buffer used in xNetworkInterfaceOutput().\r
-               'uxCount' represents the number of descriptors given to DMA for transmission.\r
-               After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
-               while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
+       /* This function is called after a TX-completion interrupt.\r
+       It will release each Network Buffer used in xNetworkInterfaceOutput().\r
+       'uxCount' represents the number of descriptors given to DMA for transmission.\r
+       After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
+       while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
+       {\r
+               if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
                {\r
-                       if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
-                       {\r
-                               break;\r
-                       }\r
+                       break;\r
+               }\r
                #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
                {\r
                        ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
@@ -352,13 +369,13 @@ size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescr
                }\r
                #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
 \r
-                       DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
+               DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
 \r
-                       uxCount--;\r
-                       /* Tell the counting semaphore that one more TX descriptor is available. */\r
-                       xSemaphoreGive( xTXDescriptorSemaphore );\r
-               }\r
+               uxCount--;\r
+               /* Tell the counting semaphore that one more TX descriptor is available. */\r
+               xSemaphoreGive( xTXDescriptorSemaphore );\r
        }\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
 BaseType_t xNetworkInterfaceInitialise( void )\r
@@ -366,91 +383,117 @@ BaseType_t xNetworkInterfaceInitialise( void )
 HAL_StatusTypeDef hal_eth_init_status;\r
 BaseType_t xResult;\r
 \r
-       if( xEMACTaskHandle == NULL )\r
+    if( xMacInitStatus == eMACInit )\r
        {\r
-                       if( xTXDescriptorSemaphore == NULL )\r
-                       {\r
-                               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
-                               configASSERT( xTXDescriptorSemaphore );\r
-                       }\r
-\r
-               /* Initialise ETH */\r
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       xMacInitStatus = eMACFailed;\r
+               }\r
+               else\r
+               {\r
+                       /* Initialise ETH */\r
 \r
-               xETH.Instance = ETH;\r
-               xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
-               xETH.Init.Speed = ETH_SPEED_100M;\r
-               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
-               /* Value of PhyAddress doesn't matter, will be probed for. */\r
-               xETH.Init.PhyAddress = 0;\r
+                       xETH.Instance = ETH;\r
+                       xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
+                       xETH.Init.Speed = ETH_SPEED_100M;\r
+                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+                       /* Value of PhyAddress doesn't matter, will be probed for. */\r
+                       xETH.Init.PhyAddress = 0;\r
 \r
-               xETH.Init.MACAddr = ( uint8_t *)FreeRTOS_GetMACAddress();\r
-               xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
+                       xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress();\r
+                       xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
 \r
-               /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
-               both the IP and the protocol checksums will be calculated\r
-               by the peripheral. */\r
-               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
+                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+                       {\r
+                               /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
+                               both the IP and the protocol checksums will be calculated\r
+                               by the peripheral. */\r
+                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
+                       }\r
+                       #else\r
+                       {\r
+                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;\r
+                       }\r
+                       #endif\r
 \r
-               #if( ipconfigUSE_RMII != 0 )\r
-               {\r
-                       xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
-               }\r
-               #else\r
-               {\r
-               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
-               }\r
-               #endif /* ipconfigUSE_RMII */\r
+                       #if( ipconfigUSE_RMII != 0 )\r
+                       {\r
+                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
+                       }\r
+                       #else\r
+                       {\r
+                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
+                       }\r
+                       #endif /* ipconfigUSE_RMII */\r
 \r
-               hal_eth_init_status = HAL_ETH_Init( &xETH );\r
+                       hal_eth_init_status = HAL_ETH_Init( &xETH );\r
 \r
-               /* Only for inspection by debugger. */\r
-               ( void ) hal_eth_init_status;\r
+                       /* Only for inspection by debugger. */\r
+                       ( void ) hal_eth_init_status;\r
 \r
-               /* Set the TxDesc and RxDesc pointers. */\r
-               xETH.TxDesc = DMATxDscrTab;\r
-               xETH.RxDesc = DMARxDscrTab;\r
+                       /* Set the TxDesc and RxDesc pointers. */\r
+                       xETH.TxDesc = DMATxDscrTab;\r
+                       xETH.RxDesc = DMARxDscrTab;\r
 \r
-               /* Make sure that all unused fields are cleared. */\r
-               memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
-               memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
+                       /* Make sure that all unused fields are cleared. */\r
+                       memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
+                       memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
 \r
                        /* Initialize Tx Descriptors list: Chain Mode */\r
                        DMATxDescToClear = DMATxDscrTab;\r
 \r
-               /* Initialise TX-descriptors. */\r
-               prvDMATxDescListInit();\r
+                       /* Initialise TX-descriptors. */\r
+                       prvDMATxDescListInit();\r
 \r
-               /* Initialise RX-descriptors. */\r
-               prvDMARxDescListInit();\r
+                       /* Initialise RX-descriptors. */\r
+                       prvDMARxDescListInit();\r
 \r
-               #if( ipconfigUSE_LLMNR != 0 )\r
-               {\r
-                       /* Program the LLMNR address at index 1. */\r
-                       prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
-               }\r
-               #endif\r
+                       #if( ipconfigUSE_LLMNR != 0 )\r
+                       {\r
+                               /* Program the LLMNR address at index 1. */\r
+                               prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
+                       }\r
+                       #endif\r
 \r
-               /* Force a negotiation with the Switch or Router and wait for LS. */\r
-               prvEthernetUpdateConfig( pdTRUE );\r
+                       /* Force a negotiation with the Switch or Router and wait for LS. */\r
+                       prvEthernetUpdateConfig( pdTRUE );\r
 \r
-               /* The deferred interrupt handler task is created at the highest\r
-               possible priority to ensure the interrupt handler can return directly\r
-               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
-               notify the task when there is something to process. */\r
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );\r
+                       /* The deferred interrupt handler task is created at the highest\r
+                       possible priority to ensure the interrupt handler can return directly\r
+                       to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
+                       notify the task when there is something to process. */\r
+                       if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS )\r
+                       {\r
+                               /* The xTXDescriptorSemaphore and the task are created successfully. */\r
+                               xMacInitStatus = eMACPass;\r
+                       }\r
+                       else\r
+                       {\r
+                               xMacInitStatus = eMACFailed;\r
+                       }\r
+               }\r
        } /* if( xEMACTaskHandle == NULL ) */\r
 \r
-       if( xPhyObject.ulLinkStatusMask != 0 )\r
+       if( xMacInitStatus != eMACPass )\r
        {\r
-               xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
-               xResult = pdPASS;\r
-               FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
+               /* EMAC initialisation failed, return pdFAIL. */\r
+               xResult = pdFAIL;\r
        }\r
        else\r
        {\r
-               /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
-               and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
-               xResult = pdFAIL;\r
+               if( xPhyObject.ulLinkStatusMask != 0uL )\r
+               {\r
+                       xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
+                       xResult = pdPASS;\r
+                       FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
+               }\r
+               else\r
+               {\r
+                       /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
+                       and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
+                       xResult = pdFAIL;\r
+               }\r
        }\r
        /* When returning non-zero, the stack will become active and\r
     start DHCP (in configured) */\r
@@ -484,6 +527,10 @@ BaseType_t xIndex;
                        /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
                        pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
                }\r
+               else\r
+               {\r
+                       pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL );\r
+               }\r
 \r
                /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
                if( xIndex < ETH_TXBUFNB - 1 )\r
@@ -567,6 +614,8 @@ static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8
 {\r
 uint32_t ulTempReg;\r
 \r
+       ( void ) heth;\r
+\r
        /* Calculate the selected MAC address high register. */\r
        ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
 \r
@@ -592,21 +641,23 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
        /* Open a do {} while ( 0 ) loop to be able to call break. */\r
        do\r
        {\r
+               if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )\r
+               {\r
+                       /* The packet has been sent back to the IP-task.\r
+                       The IP-task will further handle it.\r
+                       Do not release the descriptor. */\r
+                       bReleaseAfterSend = pdFALSE;\r
+                       break;\r
+               }\r
                #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
                {\r
                ProtocolPacket_t *pxPacket;\r
 \r
-                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
-                       {\r
-                               configASSERT( bReleaseAfterSend != 0 );\r
-                       }\r
-                       #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
-\r
                        /* If the peripheral must calculate the checksum, it wants\r
                        the protocol checksum to have a value of zero. */\r
                        pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
 \r
-                       if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )\r
+                       if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )\r
                        {\r
                                pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
                        }\r
@@ -644,6 +695,8 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
                                }\r
                                #else\r
                                {\r
+                                       configASSERT( bReleaseAfterSend != 0 );\r
+\r
                                        /* Move the buffer. */\r
                                        pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;\r
                                        /* The Network Buffer has been passed to DMA, no need to release it. */\r
@@ -653,7 +706,17 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
 \r
                                /* Ask to set the IPv4 checksum.\r
                                Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */\r
-                               pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
+                               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+                               {\r
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
+                               }\r
+                               #else\r
+                               {\r
+                                       pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC );\r
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_IC;\r
+                               }\r
+                               #endif\r
+                               \r
 \r
                                /* Prepare transmit descriptors to give to DMA. */\r
 \r
@@ -751,20 +814,24 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
 \r
                if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
                {\r
-                       uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;\r
+               uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort );\r
+               uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort );\r
 \r
-                       if( ( xPortHasUDPSocket( port ) == pdFALSE )\r
+                       if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )\r
                        #if ipconfigUSE_LLMNR == 1\r
-                               && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )\r
+                               && ( usDestinationPort != ipLLMNR_PORT )\r
+                               && ( usSourcePort != ipLLMNR_PORT )\r
                        #endif\r
                        #if ipconfigUSE_NBNS == 1\r
-                               && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )\r
+                               && ( usDestinationPort != ipNBNS_PORT )\r
+                               && ( usSourcePort != ipNBNS_PORT )\r
                        #endif\r
                        #if ipconfigUSE_DNS == 1\r
-                               && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )\r
+                               && ( usSourcePort != ipDNS_PORT )\r
                        #endif\r
                                ) {\r
                                /* Drop this packet, not for this device. */\r
+                               /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */\r
                                return pdFALSE;\r
                        }\r
                }\r
@@ -774,20 +841,59 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )\r
+{\r
+IPStackEvent_t xRxEvent;\r
+\r
+       xRxEvent.eEventType = eNetworkRxEvent;\r
+       xRxEvent.pvData = ( void * ) pxDescriptor;\r
+\r
+       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )\r
+       {\r
+               /* The buffer could not be sent to the stack so must be released again.\r
+               This is a deferred handler taskr, not a real interrupt, so it is ok to\r
+               use the task level function here. */\r
+               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+               {\r
+                       do\r
+                       {\r
+                               NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;\r
+                               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+                               pxDescriptor = pxNext;\r
+                       } while( pxDescriptor != NULL );\r
+               }\r
+               #else\r
+               {\r
+                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+               }\r
+               #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+               iptraceETHERNET_RX_EVENT_LOST();\r
+               FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );\r
+       }\r
+       else\r
+       {\r
+               iptraceNETWORK_INTERFACE_RECEIVE();\r
+       }\r
+}\r
+\r
 static BaseType_t prvNetworkInterfaceInput( void )\r
 {\r
 NetworkBufferDescriptor_t *pxCurDescriptor;\r
 NetworkBufferDescriptor_t *pxNewDescriptor = NULL;\r
-BaseType_t xReceivedLength, xAccepted;\r
+#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+       NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;\r
+       NetworkBufferDescriptor_t *pxLastDescriptor = NULL;\r
+#endif\r
+BaseType_t xReceivedLength = 0;\r
 __IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
-xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS );\r
 uint8_t *pucBuffer;\r
 \r
        pxDMARxDescriptor = xETH.RxDesc;\r
 \r
-       if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )\r
+       while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u )\r
        {\r
+       BaseType_t xAccepted = pdTRUE;\r
                /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */\r
                xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;\r
 \r
@@ -797,19 +903,9 @@ uint8_t *pucBuffer;
                /* Chained Mode */    \r
                /* Selects the next DMA Rx descriptor list for next buffer to read */ \r
                xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;\r
-       }\r
-       else\r
-       {\r
-               xReceivedLength = 0;\r
-       }\r
 \r
-       /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */\r
-\r
-       /* get received frame */\r
-       if( xReceivedLength > 0ul )\r
-       {\r
-        /* In order to make the code easier and faster, only packets in a single buffer\r
-        will be accepted.  This can be done by making the buffers large enough to\r
+               /* In order to make the code easier and faster, only packets in a single buffer\r
+               will be accepted.  This can be done by making the buffers large enough to\r
                hold a complete Ethernet packet (1536 bytes).\r
                Therefore, two sanity checks: */\r
                configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
@@ -859,20 +955,28 @@ uint8_t *pucBuffer;
                if( xAccepted != pdFALSE )\r
                {\r
                        pxCurDescriptor->xDataLength = xReceivedLength;\r
-                       xRxEvent.pvData = ( void * ) pxCurDescriptor;\r
-\r
-                       /* Pass the data to the TCP/IP task for processing. */\r
-                       if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+                       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
                        {\r
-                               /* Could not send the descriptor into the TCP/IP stack, it\r
-                               must be released. */\r
-                               vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );\r
-                               iptraceETHERNET_RX_EVENT_LOST();\r
+                               pxCurDescriptor->pxNextBuffer = NULL;\r
+\r
+                               if( pxFirstDescriptor == NULL )\r
+                               {\r
+                                       // Becomes the first message\r
+                                       pxFirstDescriptor = pxCurDescriptor;\r
+                               }\r
+                               else if( pxLastDescriptor != NULL )\r
+                               {\r
+                                       // Add to the tail\r
+                                       pxLastDescriptor->pxNextBuffer = pxCurDescriptor;\r
+                               }\r
+\r
+                               pxLastDescriptor = pxCurDescriptor;\r
                        }\r
-                       else\r
+                       #else\r
                        {\r
-                               iptraceNETWORK_INTERFACE_RECEIVE();\r
+                               prvPassEthMessages( pxCurDescriptor );\r
                        }\r
+                       #endif\r
                }\r
 \r
                /* Release descriptors to DMA */\r
@@ -907,15 +1011,25 @@ uint8_t *pucBuffer;
                        /* Resume DMA reception. */\r
                        xETH.Instance->DMARPDR = 0;\r
                }\r
+               pxDMARxDescriptor = xETH.RxDesc;\r
        }\r
 \r
+       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+       {\r
+               if( pxFirstDescriptor != NULL )\r
+               {\r
+                       prvPassEthMessages( pxFirstDescriptor );\r
+               }\r
+       }\r
+       #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+\r
        return ( xReceivedLength > 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 \r
 BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )\r
-               {\r
+{\r
 uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
 BaseType_t xResult;\r
 HAL_StatusTypeDef xHALResult;\r
@@ -933,11 +1047,11 @@ HAL_StatusTypeDef xHALResult;
                xResult = -1;\r
        }\r
        return xResult;\r
-       }\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
 BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )\r
-       {\r
+{\r
 uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
 BaseType_t xResult;\r
 HAL_StatusTypeDef xHALResult;\r
@@ -947,15 +1061,15 @@ HAL_StatusTypeDef xHALResult;
        xETH.Init.PhyAddress = usPrevAddress;\r
 \r
        if( xHALResult == HAL_OK )\r
-               {\r
+       {\r
                xResult = 0;\r
-               }\r
-               else\r
-               {\r
+       }\r
+       else\r
+       {\r
                xResult = -1;\r
-               }\r
-       return xResult;\r
        }\r
+       return xResult;\r
+}\r
 /*-----------------------------------------------------------*/\r
 \r
 void vMACBProbePhy( void )\r
@@ -979,27 +1093,27 @@ static void prvEthernetUpdateConfig( BaseType_t xForce )
                {\r
                        xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
 \r
-                               /* Configure the MAC with the Duplex Mode fixed by the\r
-                               auto-negotiation process. */\r
+                       /* Configure the MAC with the Duplex Mode fixed by the\r
+                       auto-negotiation process. */\r
                        if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )\r
-                               {\r
-                                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
-                               }\r
-                               else\r
-                               {\r
-                                       xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
-                               }\r
+                       {\r
+                               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+                       }\r
+                       else\r
+                       {\r
+                               xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
+                       }\r
 \r
-                               /* Configure the MAC with the speed fixed by the\r
-                               auto-negotiation process. */\r
+                       /* Configure the MAC with the speed fixed by the\r
+                       auto-negotiation process. */\r
                        if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )\r
-                               {\r
-                                       xETH.Init.Speed = ETH_SPEED_10M;\r
-                               }\r
-                               else\r
-                               {\r
-                                       xETH.Init.Speed = ETH_SPEED_100M;\r
-                               }\r
+                       {\r
+                               xETH.Init.Speed = ETH_SPEED_10M;\r
+                       }\r
+                       else\r
+                       {\r
+                               xETH.Init.Speed = ETH_SPEED_100M;\r
+                       }\r
                }\r
                else /* AutoNegotiation Disable */\r
                {\r
@@ -1064,11 +1178,9 @@ BaseType_t xReturn;
 \r
 /* Uncomment this in case BufferAllocation_1.c is used. */\r
 \r
-#define niBUFFER_1_PACKET_SIZE         1536\r
-\r
 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
 {\r
-static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
 uint8_t *ucRAMBuffer = ucNetworkPackets;\r
 uint32_t ul;\r
 \r
@@ -1076,7 +1188,7 @@ uint32_t ul;
        {\r
                pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
                *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
-               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+               ucRAMBuffer += ETH_MAX_PACKET_SIZE;\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -1144,21 +1256,15 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                        ulISREvents &= ~EMAC_IF_RX_EVENT;\r
 \r
                        xResult = prvNetworkInterfaceInput();\r
-                       if( xResult > 0 )\r
-                       {\r
-                               while( prvNetworkInterfaceInput() > 0 )\r
-                               {\r
-                               }\r
-                       }\r
                }\r
 \r
                if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
                {\r
                        /* Code to release TX buffers if zero-copy is used. */\r
                        ulISREvents &= ~EMAC_IF_TX_EVENT;\r
-                               /* Check if DMA packets have been delivered. */\r
-                               vClearTXBuffers();\r
-                       }\r
+                       /* Check if DMA packets have been delivered. */\r
+                       vClearTXBuffers();\r
+               }\r
 \r
                if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
                {\r
@@ -1166,10 +1272,10 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
                        ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
                }\r
                if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )\r
-                       {\r
+               {\r
                        /* Something has changed to a Link Status, need re-check. */\r
-                               prvEthernetUpdateConfig( pdFALSE );\r
-                       }\r
+                       prvEthernetUpdateConfig( pdFALSE );\r
+               }\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r