summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
new file mode 100644
index 000000000..e759141cc
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
@@ -0,0 +1,331 @@
+/*
+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;
+ }
+}