]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2822 1d2547de-c912-0410...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / M487 / NetworkInterface.c
index 6b926c8119141b8cbf3658884f137921bea87923..e759141cc34537942c595efe1fb5c12d58e4bdf1 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-#include "queue.h"
-#include "semphr.h"
-#include "task.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-
-#include "m480_eth.h"
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
-    #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-
-static SemaphoreHandle_t xTXMutex = NULL;
-
-/* The handle of the task that processes Rx packets.  The handle is required so
-the task can be notified when new packets arrive. */
-static TaskHandle_t xRxHanderTask = NULL;
-static TimerHandle_t xPhyHandlerTask = NULL;
-/*
- * A task that processes received frames.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-static void prvPhyTmrCallback( TimerHandle_t xTimer );
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-
-#define niBUFFER_1_PACKET_SIZE        1536
-#ifdef __ICCARM__
-#pragma data_alignment=4
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
-#else
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
-#endif
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-    uint8_t hwaddr[6];
-    BaseType_t xReturn = pdPASS;
-
-    /* Init ETH */
-    numaker_mac_address(hwaddr);
-    FreeRTOS_UpdateMACAddress(hwaddr);
-    FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
-    /* Enable clock & set EMAC configuration         */
-    /* Enable MAC and DMA transmission and reception */
-    if( numaker_eth_init(hwaddr) < 0)
-    {
-        xReturn = pdFAIL;
-    } else {
-        xReturn = pdPASS;
-        /* Guard against the task being created more than once and the
-        descriptors being initialized more than once. */
-        /* Timer task to monitor PHY Link status */
-        if( xPhyHandlerTask == NULL )
-        {
-            xPhyHandlerTask = xTimerCreate( "TimerPhy",  pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
-            configASSERT(xPhyHandlerTask);
-            xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
-            configASSERT( xReturn );
-        }
-        /* Rx task */
-        if( xRxHanderTask == NULL )
-        {
-            xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
-            configASSERT( xReturn );
-        }
-        
-        if( xTXMutex == NULL )
-        {
-            xTXMutex = xSemaphoreCreateMutex();
-            configASSERT( xTXMutex );
-        }        
-    }
-
-        NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
-        NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
-
-        numaker_eth_enable_interrupts();
-
-        FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
-
-    return xReturn;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
-{
-    uint8_t *buffer=NULL;
-//    FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
-    if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
-    {
-        FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
-        return pdFALSE;
-    }
-    
-    buffer = numaker_eth_get_tx_buf();
-    if( buffer == NULL )
-    {
-        NU_DEBUGF(("Eth TX slots are busy\n"));
-        return pdFALSE;
-    }    
-    
-    /* Get exclusive access */
-    xSemaphoreTake(xTXMutex, portMAX_DELAY);
-    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));   
-    //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
-    memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
-    numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
-    /* Call the standard trace macro to log the send event. */
-    iptraceNETWORK_INTERFACE_TRANSMIT();
-
-    if( xReleaseAfterSend != pdFALSE )
-    {
-        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
-        buffer.  The Ethernet buffer is therefore no longer needed, and must be
-        freed for re-use. */
-        vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-    }
-
-    xSemaphoreGive(xTXMutex);
-    
-    return pdTRUE;
-}
-
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-
-    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 += niBUFFER_1_PACKET_SIZE;
-    }
-}
-
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-    BaseType_t xReturn;
-
-    if( numaker_eth_link_ok() )
-    {
-        xReturn = pdPASS;
-    }
-    else
-    {
-        xReturn = pdFAIL;
-    }
-
-    return xReturn;
-}
-
-static void prvPhyTmrCallback( TimerHandle_t xTimer )
-{
-    IPStackEvent_t xRxEvent;
-    static BaseType_t lastLink = pdFAIL;
-    BaseType_t currLink = xGetPhyLinkStatus();
-    if( currLink != lastLink )
-    {
-        FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
-        if( !currLink )
-        {
-            xRxEvent.eEventType = eNetworkDownEvent;
-            xSendEventStructToIPTask( &xRxEvent, 0 );
-        }
-        lastLink = currLink;
-    }
-
-}    
-
-    
-static void prvEMACHandlerTask( void *pvParameters )
-{
-    TimeOut_t xPhyTime;
-    TickType_t xPhyRemTime;
-    UBaseType_t uxLastMinBufferCount = 0;
-    UBaseType_t uxCurrentCount;
-    BaseType_t xResult = 0;
-    uint32_t ulStatus;
-    uint16_t dataLength = 0;
-    uint8_t *buffer = NULL;
-    NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
-    IPStackEvent_t xRxEvent;
-    const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
-    
-    /* Remove compiler warnings about unused parameters. */
-    ( void ) pvParameters;
-    /* A possibility to set some additional task properties. */
-    
-    for( ;; )
-    {
-        uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-        if( uxLastMinBufferCount != uxCurrentCount )
-        {
-            /* The logging produced below may be helpful
-            while tuning +TCP: see how many buffers are in use. */
-            uxLastMinBufferCount = uxCurrentCount;
-            FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-        }
-        
-        /* No events to process now, wait for the next. */
-        ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); 
-        while(1)
-        {    
-            /* get received frame */
-            if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
-            /* The event was lost because a network buffer was not available.
-            Call the standard trace macro to log the occurrence. */
-                iptraceETHERNET_RX_EVENT_LOST();
-                break;
-            }        
-
-            /* Allocate a network buffer descriptor that points to a buffer
-            large enough to hold the received frame.  As this is the simple
-            rather than efficient example the received data will just be copied
-            into this buffer. */
-
-            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );
-
-            if( pxBufferDescriptor != NULL )
-            {        
-                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
-//                          FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
-                pxBufferDescriptor->xDataLength = dataLength;            
-            } else {
-                numaker_eth_rx_next();
-                iptraceETHERNET_RX_EVENT_LOST();
-                break;
-            }
-            /* The event about to be sent to the TCP/IP is an Rx event. */
-            xRxEvent.eEventType = eNetworkRxEvent;
-
-            /* pvData is used to point to the network buffer descriptor that
-                now references the received data. */
-            xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
-            /* Send the data to the TCP/IP stack. */
-            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
-            {
-                /* The buffer could not be sent to the IP task so the buffer
-                 must be released. */
-                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-
-                /* Make a call to the standard trace macro to log the
-                        occurrence. */
-
-                iptraceETHERNET_RX_EVENT_LOST();
-            } else
-            {
-                /* The message was successfully sent to the TCP/IP stack.
-                Call the standard trace macro to log the occurrence. */
-                iptraceNETWORK_INTERFACE_RECEIVE();
-            } 
-                numaker_eth_rx_next();
-        }    
-        numaker_eth_trigger_rx();
-    }
-}
-
-void xNetworkCallback(char event)
-{
-    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-    switch (event)
-    {
-      case 'R': //For RX event
-    /* Wakeup the prvEMACHandlerTask. */
-        if( xRxHanderTask != NULL )
-        {
-            vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
-            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-        }
-        break;
-      case 'T': //For TX event
-        // ack of tx done, no-op in this stage
-        break;
-      default:
-        break;
-    }
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 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
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+\r
+#include "m480_eth.h"\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\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
+\r
+static SemaphoreHandle_t xTXMutex = NULL;\r
+\r
+/* The handle of the task that processes Rx packets.  The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+static TimerHandle_t xPhyHandlerTask = NULL;\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer );\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+\r
+#define niBUFFER_1_PACKET_SIZE        1536\r
+#ifdef __ICCARM__\r
+#pragma data_alignment=4\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]\r
+#else\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+    uint8_t hwaddr[6];\r
+    BaseType_t xReturn = pdPASS;\r
+\r
+    /* Init ETH */\r
+    numaker_mac_address(hwaddr);\r
+    FreeRTOS_UpdateMACAddress(hwaddr);\r
+    FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );\r
+    /* Enable clock & set EMAC configuration         */\r
+    /* Enable MAC and DMA transmission and reception */\r
+    if( numaker_eth_init(hwaddr) < 0)\r
+    {\r
+        xReturn = pdFAIL;\r
+    } else {\r
+        xReturn = pdPASS;\r
+        /* Guard against the task being created more than once and the\r
+        descriptors being initialized more than once. */\r
+        /* Timer task to monitor PHY Link status */\r
+        if( xPhyHandlerTask == NULL )\r
+        {\r
+            xPhyHandlerTask = xTimerCreate( "TimerPhy",  pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );\r
+            configASSERT(xPhyHandlerTask);\r
+            xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;\r
+            configASSERT( xReturn );\r
+        }\r
+        /* Rx task */\r
+        if( xRxHanderTask == NULL )\r
+        {\r
+            xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+            configASSERT( xReturn );\r
+        }\r
+        \r
+        if( xTXMutex == NULL )\r
+        {\r
+            xTXMutex = xSemaphoreCreateMutex();\r
+            configASSERT( xTXMutex );\r
+        }        \r
+    }\r
+\r
+        NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+        NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+\r
+        numaker_eth_enable_interrupts();\r
+\r
+        FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );\r
+\r
+    return xReturn;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )\r
+{\r
+    uint8_t *buffer=NULL;\r
+//    FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));\r
+    if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )\r
+    {\r
+        FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));\r
+        return pdFALSE;\r
+    }\r
+    \r
+    buffer = numaker_eth_get_tx_buf();\r
+    if( buffer == NULL )\r
+    {\r
+        NU_DEBUGF(("Eth TX slots are busy\n"));\r
+        return pdFALSE;\r
+    }    \r
+    \r
+    /* Get exclusive access */\r
+    xSemaphoreTake(xTXMutex, portMAX_DELAY);\r
+    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));   \r
+    //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength\r
+    memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);\r
+    numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);\r
+    /* Call the standard trace macro to log the send event. */\r
+    iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+    if( xReleaseAfterSend != pdFALSE )\r
+    {\r
+        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet\r
+        buffer.  The Ethernet buffer is therefore no longer needed, and must be\r
+        freed for re-use. */\r
+        vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+    }\r
+\r
+    xSemaphoreGive(xTXMutex);\r
+    \r
+    return pdTRUE;\r
+}\r
+\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
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+    BaseType_t xReturn;\r
+\r
+    if( numaker_eth_link_ok() )\r
+    {\r
+        xReturn = pdPASS;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdFAIL;\r
+    }\r
+\r
+    return xReturn;\r
+}\r
+\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer )\r
+{\r
+    IPStackEvent_t xRxEvent;\r
+    static BaseType_t lastLink = pdFAIL;\r
+    BaseType_t currLink = xGetPhyLinkStatus();\r
+    if( currLink != lastLink )\r
+    {\r
+        FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));\r
+        if( !currLink )\r
+        {\r
+            xRxEvent.eEventType = eNetworkDownEvent;\r
+            xSendEventStructToIPTask( &xRxEvent, 0 );\r
+        }\r
+        lastLink = currLink;\r
+    }\r
+\r
+}    \r
+\r
+    \r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+    TimeOut_t xPhyTime;\r
+    TickType_t xPhyRemTime;\r
+    UBaseType_t uxLastMinBufferCount = 0;\r
+    UBaseType_t uxCurrentCount;\r
+    BaseType_t xResult = 0;\r
+    uint32_t ulStatus;\r
+    uint16_t dataLength = 0;\r
+    uint8_t *buffer = NULL;\r
+    NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;\r
+    IPStackEvent_t xRxEvent;\r
+    const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+    \r
+    /* Remove compiler warnings about unused parameters. */\r
+    ( void ) pvParameters;\r
+    /* A possibility to set some additional task properties. */\r
+    \r
+    for( ;; )\r
+    {\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
+        /* No events to process now, wait for the next. */\r
+        ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); \r
+        while(1)\r
+        {    \r
+            /* get received frame */\r
+            if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {\r
+            /* The event was lost because a network buffer was not available.\r
+            Call the standard trace macro to log the occurrence. */\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+                break;\r
+            }        \r
+\r
+            /* Allocate a network buffer descriptor that points to a buffer\r
+            large enough to hold the received frame.  As this is the simple\r
+            rather than efficient example the received data will just be copied\r
+            into this buffer. */\r
+\r
+            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );\r
+\r
+            if( pxBufferDescriptor != NULL )\r
+            {        \r
+                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );\r
+//                          FreeRTOS_printf(("--> dataLength=%d\n",dataLength));\r
+                pxBufferDescriptor->xDataLength = dataLength;            \r
+            } else {\r
+                numaker_eth_rx_next();\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+                break;\r
+            }\r
+            /* The event about to be sent to the TCP/IP is an Rx event. */\r
+            xRxEvent.eEventType = eNetworkRxEvent;\r
+\r
+            /* pvData is used to point to the network buffer descriptor that\r
+                now references the received data. */\r
+            xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+            /* Send the data to the TCP/IP stack. */\r
+            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+            {\r
+                /* The buffer could not be sent to the IP task so the buffer\r
+                 must be released. */\r
+                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+\r
+                /* Make a call to the standard trace macro to log the\r
+                        occurrence. */\r
+\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+            } else\r
+            {\r
+                /* The message was successfully sent to the TCP/IP stack.\r
+                Call the standard trace macro to log the occurrence. */\r
+                iptraceNETWORK_INTERFACE_RECEIVE();\r
+            } \r
+                numaker_eth_rx_next();\r
+        }    \r
+        numaker_eth_trigger_rx();\r
+    }\r
+}\r
+\r
+void xNetworkCallback(char event)\r
+{\r
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+    switch (event)\r
+    {\r
+      case 'R': //For RX event\r
+    /* Wakeup the prvEMACHandlerTask. */\r
+        if( xRxHanderTask != NULL )\r
+        {\r
+            vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+        }\r
+        break;\r
+      case 'T': //For TX event\r
+        // ack of tx done, no-op in this stage\r
+        break;\r
+      default:\r
+        break;\r
+    }\r
+}\r