--- /dev/null
+/*\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