]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c
Added back some TCP/IP stack port layer files.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / STM32F7xx / NetworkInterface.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32F7xx/NetworkInterface.c
new file mode 100644 (file)
index 0000000..7de2902
--- /dev/null
@@ -0,0 +1,1193 @@
+/*\r
+ * Some constants, hardware definitions and comments taken from ST's HAL driver\r
+ * library, COPYRIGHT(c) 2015 STMicroelectronics.\r
+ */\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://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "phyHandling.h"\r
+\r
+/* ST includes. */\r
+#ifdef STM32F7xx\r
+       #include "stm32f7xx_hal.h"\r
+#else\r
+       #include "stm32f4xx_hal.h"\r
+#endif\r
+\r
+/* Interrupt events to process.  Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT        1UL\r
+#define EMAC_IF_TX_EVENT        2UL\r
+#define EMAC_IF_ERR_EVENT       4UL\r
+#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETH_DMA_ALL_INTS \\r
+       ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \\r
+         ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \\r
+         ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )\r
+\r
+\r
+\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
+/*\r
+ * Most users will want a PHY that negotiates about\r
+ * the connection properties: speed, dmix and duplex.\r
+ * On some rare cases, you want to select what is being\r
+ * advertised, properties like MDIX and duplex.\r
+ */\r
+\r
+#if !defined( ipconfigETHERNET_AN_ENABLE )\r
+       /* Enable auto-negotiation */\r
+       #define ipconfigETHERNET_AN_ENABLE                              1\r
+#endif\r
+\r
+#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )\r
+       #define ipconfigETHERNET_AUTO_CROSS_ENABLE              1\r
+#endif\r
+\r
+#if( ipconfigETHERNET_AN_ENABLE == 0 )\r
+       /*\r
+        * The following three defines are only used in case there\r
+        * is no auto-negotiation.\r
+        */\r
+       #if !defined( ipconfigETHERNET_CROSSED_LINK )\r
+               #define ipconfigETHERNET_CROSSED_LINK                   1\r
+       #endif\r
+\r
+       #if !defined( ipconfigETHERNET_USE_100MB )\r
+               #define ipconfigETHERNET_USE_100MB                              1\r
+       #endif\r
+\r
+       #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )\r
+               #define ipconfigETHERNET_USE_FULL_DUPLEX                1\r
+       #endif\r
+#endif /* ipconfigETHERNET_AN_ENABLE == 0 */\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/* Two choices must be made: RMII versus MII,\r
+and the index of the PHY in use ( between 0 and 31 ). */\r
+#ifndef ipconfigUSE_RMII\r
+       #ifdef STM32F7xx\r
+               #define ipconfigUSE_RMII        1\r
+       #else\r
+               #define ipconfigUSE_RMII        0\r
+       #endif /* STM32F7xx */\r
+#endif /* ipconfigUSE_RMII */\r
+\r
+#ifndef ipconfigPHY_INDEX\r
+       #ifdef STM32F7xx\r
+               #define ipconfigPHY_INDEX       0\r
+       #else\r
+               #define ipconfigPHY_INDEX       1\r
+       #endif /* STM32F7xx */\r
+#endif /* ipconfigPHY_INDEX */\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Force a negotiation with the Switch or Router and wait for LS.\r
+ */\r
+static void prvEthernetUpdateConfig( BaseType_t xForce );\r
+\r
+/*\r
+ * See if there is a new packet and forward it to the IP-task.\r
+ */\r
+static BaseType_t prvNetworkInterfaceInput( void );\r
+\r
+#if( ipconfigUSE_LLMNR != 0 )\r
+       /*\r
+        * For LLMNR, an extra MAC-address must be configured to\r
+        * be able to receive the multicast messages.\r
+        */\r
+       static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);\r
+#endif\r
+\r
+/*\r
+ * Check if a given packet should be accepted.\r
+ */\r
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );\r
+\r
+/*\r
+ * Initialise the TX descriptors.\r
+ */\r
+static void prvDMATxDescListInit( void );\r
+\r
+/*\r
+ * Initialise the RX descriptors.\r
+ */\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
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+static EthernetPhy_t xPhyObject;\r
+\r
+/* 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
+\r
+/*\r
+ * Note: it is adviced to define both\r
+ *\r
+ *     #define  ipconfigZERO_COPY_RX_DRIVER   1\r
+ *     #define  ipconfigZERO_COPY_TX_DRIVER   1\r
+ *\r
+ * The method using memcpy is slower and probaly uses more RAM memory.\r
+ * The possibility is left in the code just for comparison.\r
+ *\r
+ * It is adviced to define ETH_TXBUFNB at least 4. Note that no\r
+ * TX buffers are allocated in a zero-copy driver.\r
+ */\r
+/* MAC buffers: ---------------------------------------------------------*/\r
+\r
+/* Put the DMA descriptors in '.first_data'.\r
+This is important for STM32F7, which has an L1 data cache.\r
+The first 64KB of the SRAM is not cached. */\r
+\r
+/* Ethernet Rx MA Descriptor */\r
+__attribute__ ((aligned (32)))\r
+__attribute__ ((section(".first_data")))\r
+       ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ];\r
+\r
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
+       /* Ethernet Receive Buffer */\r
+       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;\r
+#endif\r
+\r
+/* Ethernet Tx DMA Descriptor */\r
+__attribute__ ((aligned (32)))\r
+__attribute__ ((section(".first_data")))\r
+       ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ];\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       /* Ethernet Transmit Buffer */\r
+       __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
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\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
+related interrupts. */\r
+static TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/* For local use only: describe the PHY's properties: */\r
+const PhyProperties_t xPHYProperties =\r
+{\r
+       #if( ipconfigETHERNET_AN_ENABLE != 0 )\r
+               .ucSpeed = PHY_SPEED_AUTO,\r
+               .ucDuplex = PHY_DUPLEX_AUTO,\r
+       #else\r
+               #if( ipconfigETHERNET_USE_100MB != 0 )\r
+                       .ucSpeed = PHY_SPEED_100,\r
+               #else\r
+                       .ucSpeed = PHY_SPEED_10,\r
+               #endif\r
+\r
+               #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
+                       .duplex = PHY_DUPLEX_FULL,\r
+               #else\r
+                       .duplex = PHY_DUPLEX_HALF,\r
+               #endif\r
+       #endif\r
+\r
+       #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )\r
+               .ucMDI_X = PHY_MDIX_AUTO,\r
+       #elif( ipconfigETHERNET_CROSSED_LINK != 0 )\r
+               .ucMDI_X = PHY_MDIX_CROSSED,\r
+       #else\r
+               .ucMDI_X = PHY_MDIX_DIRECT,\r
+       #endif\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
+    ulISREvents |= EMAC_IF_RX_EVENT;\r
+       /* Wakeup the prvEMACHandlerTask. */\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+       }\r
+}\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
+\r
+}\r
+/*-----------------------------------------------------------*/\r
+\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
+       {\r
+               if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
+               {\r
+                       break;\r
+               }\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
+\r
+                       if( ucPayLoad != NULL )\r
+                       {\r
+                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
+                               }\r
+                               DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\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
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+HAL_StatusTypeDef hal_eth_init_status;\r
+BaseType_t xResult;\r
+\r
+       if( xEMACTaskHandle == NULL )\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
+\r
+               xETH.Instance = ETH;\r
+//#warning Enable auto-nego again\r
+               xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
+//             xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;\r
+               xETH.Init.Speed = ETH_SPEED_100M;\r
+               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+               xETH.Init.PhyAddress = ipconfigPHY_INDEX;\r
+\r
+               xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;\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
+\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
+\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
+\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
+\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
+\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, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+       } /* if( xEMACTaskHandle == NULL ) */\r
+\r
+       if( xPhyObject.ulLinkStatusMask != 0 )\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
+               FreeRTOS_printf( ( "Link Status still low\n" ) ) ;\r
+       }\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDMATxDescListInit()\r
+{\r
+ETH_DMADescTypeDef *pxDMADescriptor;\r
+BaseType_t xIndex;\r
+\r
+       /* Get the pointer on the first member of the descriptor list */\r
+       pxDMADescriptor = DMATxDscrTab;\r
+\r
+       /* Fill each DMA descriptor with the right values */\r
+       for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )\r
+       {\r
+               /* Set Second Address Chained bit */\r
+               pxDMADescriptor->Status = ETH_DMATXDESC_TCH;\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );\r
+               }\r
+               #endif\r
+\r
+               if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )\r
+               {\r
+                       /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
+                       pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
+               }\r
+\r
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
+               if( xIndex < ETH_TXBUFNB - 1 )\r
+               {\r
+                       /* Set next descriptor address register with next descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );\r
+               }\r
+               else\r
+               {\r
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;\r
+               }\r
+       }\r
+\r
+       /* Set Transmit Descriptor List Address Register */\r
+       xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDMARxDescListInit()\r
+{\r
+ETH_DMADescTypeDef *pxDMADescriptor;\r
+BaseType_t xIndex;\r
+       /*\r
+        * RX-descriptors.\r
+        */\r
+\r
+       /* Get the pointer on the first member of the descriptor list */\r
+       pxDMADescriptor = DMARxDscrTab;\r
+\r
+       /* Fill each DMA descriptor with the right values */\r
+       for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )\r
+       {\r
+\r
+               /* Set Buffer1 size and Second Address Chained bit */\r
+               pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
+\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+               /* Set Buffer1 address pointer */\r
+               NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+                       pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );\r
+                       /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'\r
+                       Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */\r
+                       configASSERT( pxBuffer != NULL );\r
+                       if( pxBuffer != NULL )\r
+                       {\r
+                               pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;\r
+                               pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
+                       }\r
+               }\r
+               #else\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );\r
+                       /* Set Own bit of the Rx descriptor Status */\r
+                       pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
+               }\r
+               #endif\r
+\r
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
+               if( xIndex < ETH_RXBUFNB - 1 )\r
+               {\r
+                       /* Set next descriptor address register with next descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );\r
+               }\r
+               else\r
+               {\r
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;\r
+               }\r
+\r
+       }\r
+       /* Set Receive Descriptor List Address Register */\r
+       xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)\r
+{\r
+uint32_t ulTempReg;\r
+\r
+       /* Calculate the selected MAC address high register. */\r
+       ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
+\r
+       /* Load the selected MAC address high register. */\r
+       ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;\r
+\r
+       /* Calculate the selected MAC address low register. */\r
+       ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];\r
+\r
+       /* Load the selected MAC address low register */\r
+       ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+uint32_t ulTransmitSize = 0;\r
+__IO ETH_DMADescTypeDef *pxDmaTxDesc;\r
+/* Do not wait too long for a free TX DMA buffer. */\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\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
+               {\r
+                       pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
+               }\r
+       }\r
+       #endif\r
+\r
+       /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+       do\r
+       {\r
+               if( xPhyObject.ulLinkStatusMask != 0 )\r
+               {\r
+                       if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+                       {\r
+                               /* Time-out waiting for a free TX descriptor. */\r
+                               break;\r
+                       }\r
+\r
+                       /* This function does the actual transmission of the packet. The packet is\r
+                       contained in 'pxDescriptor' that is passed to the function. */\r
+                       pxDmaTxDesc = xETH.TxDesc;\r
+\r
+                       /* Is this buffer available? */\r
+                       configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );\r
+\r
+                       {\r
+                               /* Is this buffer available? */\r
+                               /* Get bytes in current buffer. */\r
+                               ulTransmitSize = pxDescriptor->xDataLength;\r
+\r
+                               if( ulTransmitSize > ETH_TX_BUF_SIZE )\r
+                               {\r
+                                       ulTransmitSize = ETH_TX_BUF_SIZE;\r
+                               }\r
+\r
+                               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+                               {\r
+                                       /* Copy the bytes. */\r
+                                       memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );\r
+                               }\r
+                               #else\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
+                                       bReleaseAfterSend = pdFALSE_UNSIGNED;\r
+                               }\r
+                               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\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
+\r
+                               /* Prepare transmit descriptors to give to DMA. */\r
+\r
+                               /* Set LAST and FIRST segment */\r
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
+                               /* Set frame size */\r
+                               pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
+                               /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
+\r
+                               /* Point to next descriptor */\r
+                               xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );\r
+                               /* Ensure completion of memory access */\r
+                               __DSB();\r
+                               /* Resume DMA transmission*/\r
+                               xETH.Instance->DMATPDR = 0;\r
+                               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+                               xReturn = pdPASS;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The PHY has no Link Status, packet shall be dropped. */\r
+               }\r
+       } while( 0 );\r
+       /* The buffer has been sent so can be released. */\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )\r
+{\r
+const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;\r
+\r
+       switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )\r
+       {\r
+       case ipARP_FRAME_TYPE:\r
+               /* Check it later. */\r
+               return pdTRUE;\r
+       case ipIPv4_FRAME_TYPE:\r
+               /* Check it here. */\r
+               break;\r
+       default:\r
+               /* Refuse the packet. */\r
+               return pdFALSE;\r
+       }\r
+\r
+       #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+       {\r
+               const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);\r
+               uint32_t ulDestinationIPAddress;\r
+\r
+               /* Ensure that the incoming packet is not fragmented (only outgoing packets\r
+                * can be fragmented) as these are the only handled IP frames currently. */\r
+               if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+               /* HT: Might want to make the following configurable because\r
+                * most IP messages have a standard length of 20 bytes */\r
+\r
+               /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes\r
+                * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */\r
+               if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+\r
+               ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;\r
+               /* Is the packet for this node? */\r
+               if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&\r
+                       /* Is it a broadcast address x.x.x.255 ? */\r
+                       ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+                       ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&\r
+               #endif\r
+                       ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {\r
+                       FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );\r
+                       return pdFALSE;\r
+               }\r
+\r
+               if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
+               {\r
+                       uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;\r
+\r
+                       if( ( xPortHasUDPSocket( port ) == pdFALSE )\r
+                       #if ipconfigUSE_LLMNR == 1\r
+                               && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )\r
+                       #endif\r
+                       #if ipconfigUSE_NBNS == 1\r
+                               && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )\r
+                       #endif\r
+                       #if ipconfigUSE_DNS == 1\r
+                               && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )\r
+                       #endif\r
+                               ) {\r
+                               /* Drop this packet, not for this device. */\r
+                               return pdFALSE;\r
+                       }\r
+               }\r
+       }\r
+       #endif  /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+       return pdTRUE;\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
+__IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
+xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+uint8_t *pucBuffer;\r
+\r
+       pxDMARxDescriptor = xETH.RxDesc;\r
+\r
+       if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )\r
+       {\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
+               pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;\r
+\r
+               /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */\r
+               /* 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
+               hold a complete Ethernet packet (1536 bytes).\r
+               Therefore, two sanity checks: */\r
+               configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
+\r
+               if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )\r
+               {\r
+                       /* Not an Ethernet frame-type or a checmsum error. */\r
+                       xAccepted = pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       /* See if this packet must be handled. */\r
+                       xAccepted = xMayAcceptPacket( pucBuffer );\r
+               }\r
+\r
+               if( xAccepted != pdFALSE )\r
+               {\r
+                       /* The packet wil be accepted, but check first if a new Network Buffer can\r
+                       be obtained. If not, the packet will still be dropped. */\r
+                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );\r
+\r
+                       if( pxNewDescriptor == NULL )\r
+                       {\r
+                               /* A new descriptor can not be allocated now. This packet will be dropped. */\r
+                               xAccepted = pdFALSE;\r
+                       }\r
+               }\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       /* Find out which Network Buffer was originally passed to the descriptor. */\r
+                       pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                       configASSERT( pxCurDescriptor != NULL );\r
+               }\r
+               #else\r
+               {\r
+                       /* In this mode, the two descriptors are the same. */\r
+                       pxCurDescriptor = pxNewDescriptor;\r
+                       if( pxNewDescriptor != NULL )\r
+                       {\r
+                               /* The packet is acepted and a new Network Buffer was created,\r
+                               copy data to the Network Bufffer. */\r
+                               memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               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
+                       {\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
+                       }\r
+                       else\r
+                       {\r
+                               iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       }\r
+               }\r
+\r
+               /* Release descriptors to DMA */\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       if( pxNewDescriptor != NULL )\r
+                       {\r
+                               pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The packet was dropped and the same Network\r
+                               Buffer will be used to receive a new packet. */\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+               /* Set Buffer1 size and Second Address Chained bit */\r
+               pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
+               pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;\r
+\r
+               /* Ensure completion of memory access */\r
+               __DSB();\r
+               /* When Rx Buffer unavailable flag is set clear it and resume\r
+               reception. */\r
+               if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )\r
+               {\r
+                       /* Clear RBUS ETHERNET DMA flag. */\r
+                       xETH.Instance->DMASR = ETH_DMASR_RBUS;\r
+\r
+                       /* Resume DMA reception. */\r
+                       xETH.Instance->DMARPDR = 0;\r
+               }\r
+       }\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
+uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
+BaseType_t xResult;\r
+HAL_StatusTypeDef xHALResult;\r
+\r
+       xETH.Init.PhyAddress = xAddress;\r
+       xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );\r
+       xETH.Init.PhyAddress = usPrevAddress;\r
+\r
+       if( xHALResult == HAL_OK )\r
+       {\r
+               xResult = 0;\r
+       }\r
+       else\r
+       {\r
+               xResult = -1;\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )\r
+{\r
+uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
+BaseType_t xResult;\r
+HAL_StatusTypeDef xHALResult;\r
+\r
+       xETH.Init.PhyAddress = xAddress;\r
+       xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );\r
+       xETH.Init.PhyAddress = usPrevAddress;\r
+\r
+       if( xHALResult == HAL_OK )\r
+       {\r
+               xResult = 0;\r
+       }\r
+       else\r
+       {\r
+               xResult = -1;\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void phy_test()\r
+{\r
+BaseType_t xPhyCount;\r
+BaseType_t xPhyIndex;\r
+\r
+       vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
+       xPhyCount = xPhyDiscover( &xPhyObject );\r
+       FreeRTOS_printf( ( "PHY count %ld\n", xPhyCount ) );\r
+       for( xPhyIndex = 0; xPhyIndex < xPhyCount; xPhyIndex++ )\r
+       {\r
+               FreeRTOS_printf( ( "PHY[%d] at address %d ( 0x%08X )\n",\r
+                       xPhyIndex,\r
+                       xPhyObject.ucPhyIndexes[ xPhyIndex ],\r
+                       xPhyObject.ulPhyIDs[ xPhyIndex ] ) );\r
+\r
+       }\r
+       \r
+}\r
+\r
+void vMACBProbePhy( void )\r
+{\r
+       vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
+       xPhyDiscover( &xPhyObject );\r
+       xPhyConfigure( &xPhyObject, &xPHYProperties );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEthernetUpdateConfig( BaseType_t xForce )\r
+{\r
+       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02X Force %d\n",\r
+               xPhyObject.ulLinkStatusMask,\r
+               ( int )xForce ) );\r
+\r
+       if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )\r
+       {\r
+               /* Restart the auto-negotiation. */\r
+               if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )\r
+               {\r
+                       xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
+\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
+                       /* 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
+               else /* AutoNegotiation Disable */\r
+               {\r
+                       /* Check parameters */\r
+                       assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );\r
+                       assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );\r
+\r
+                       if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )\r
+                       {\r
+                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;\r
+                       }\r
+\r
+                       if( xETH.Init.Speed == ETH_SPEED_10M )\r
+                       {\r
+                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;\r
+                       }\r
+\r
+                       xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;\r
+\r
+                       /* Use predefined (fixed) configuration. */\r
+                       xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
+               }\r
+\r
+               /* ETHERNET MAC Re-Configuration */\r
+               HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);\r
+\r
+               /* Restart MAC interface */\r
+               HAL_ETH_Start( &xETH);\r
+       }\r
+       else\r
+       {\r
+               /* Stop MAC interface */\r
+               HAL_ETH_Stop( &xETH );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( xPhyObject.ulLinkStatusMask != 0 )\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+UBaseType_t uxLastMinQueueSpace = 0;\r
+#endif\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               xResult = 0;\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               if( xTXDescriptorSemaphore != NULL )\r
+               {\r
+               static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;\r
+\r
+                       uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+                       if( uxLowestSemCount > uxCurrentCount )\r
+                       {\r
+                               uxLowestSemCount = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );\r
+                       }\r
+\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       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
+\r
+               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: logging about errors that occurred. */\r
+                       ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+               }\r
+               if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )\r
+               {\r
+                       /* Something has changed to a Link Status, need re-check. */\r
+                       prvEthernetUpdateConfig( pdFALSE );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void ETH_IRQHandler( void )\r
+{\r
+       HAL_ETH_IRQHandler( &xETH );\r
+}\r
+\r