*/\r
\r
/*\r
- * FreeRTOS+TCP V2.0.0\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. If you wish to use our Amazon\r
- * FreeRTOS name, please do so in a fair use way that does not cause confusion.\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
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
\r
/* Standard includes. */\r
#include <stdint.h>\r
#include "FreeRTOS_Sockets.h"\r
#include "FreeRTOS_IP_Private.h"\r
#include "FreeRTOS_DNS.h"\r
+#include "FreeRTOS_ARP.h"\r
#include "NetworkBufferManagement.h"\r
#include "NetworkInterface.h"\r
#include "phyHandling.h"\r
\r
/* ST includes. */\r
-#ifdef STM32F7xx\r
+#if defined( STM32F7xx )\r
#include "stm32f7xx_hal.h"\r
-#else\r
+#elif defined( STM32F4xx )\r
#include "stm32f4xx_hal.h"\r
+#elif defined( STM32F2xx )\r
+ #include "stm32f2xx_hal.h"\r
+#elif !defined( _lint ) /* Lint does not like an #error */\r
+ #error What part?\r
#endif\r
\r
+#include "stm32fxx_hal_eth.h"\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
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
+#ifndef niEMAC_HANDLER_TASK_PRIORITY\r
+ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1\r
+#endif\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
+#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )\r
+ #warning Consider enabling checksum offloading\r
+#endif\r
+\r
+#ifndef niDESCRIPTOR_WAIT_TIME_MS\r
+ #define niDESCRIPTOR_WAIT_TIME_MS 250uL\r
+#endif\r
+\r
/*\r
* Most users will want a PHY that negotiates about\r
* the connection properties: speed, dmix and duplex.\r
#endif /* STM32F7xx */\r
#endif /* ipconfigUSE_RMII */\r
\r
+#if( ipconfigUSE_RMII != 0 )\r
+ #warning Using RMII, make sure if this is correct\r
+#else\r
+ #warning Using MII, make sure if this is correct\r
+#endif\r
+\r
+typedef enum\r
+{\r
+ eMACInit, /* Must initialise MAC. */\r
+ eMACPass, /* Initialisation was successful. */\r
+ eMACFailed, /* Initialisation failed. */\r
+} eMAC_INIT_STATUS_TYPE;\r
\r
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
\r
/*-----------------------------------------------------------*/\r
\r
__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
+/* DMATxDescToClear points to the next TX DMA descriptor\r
+that must be cleared by vClearTXBuffers(). */\r
+static __IO ETH_DMADescTypeDef *DMATxDescToClear;\r
\r
/* Holds the handle of the task used as a deferred interrupt processor. The\r
handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
#endif\r
\r
#if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
- .duplex = PHY_DUPLEX_FULL,\r
+ .ucDuplex = PHY_DUPLEX_FULL,\r
#else\r
- .duplex = PHY_DUPLEX_HALF,\r
+ .ucDuplex = PHY_DUPLEX_HALF,\r
#endif\r
#endif\r
\r
{\r
BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
\r
+ ( void ) heth;\r
+\r
/* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
ulISREvents |= EMAC_IF_RX_EVENT;\r
/* Wakeup the prvEMACHandlerTask. */\r
{\r
BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
\r
+ ( void ) heth;\r
+\r
/* This call-back is only useful in case packets are being sent\r
zero-copy. Once they're sent, the buffers will be released\r
by the function vClearTXBuffers(). */\r
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
}\r
-\r
}\r
/*-----------------------------------------------------------*/\r
\r
HAL_StatusTypeDef hal_eth_init_status;\r
BaseType_t xResult;\r
\r
- if( xEMACTaskHandle == NULL )\r
+ if( xMacInitStatus == eMACInit )\r
{\r
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
if( xTXDescriptorSemaphore == NULL )\r
{\r
- xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
- configASSERT( xTXDescriptorSemaphore );\r
+ xMacInitStatus = eMACFailed;\r
}\r
+ else\r
+ {\r
+ /* Initialise ETH */\r
\r
- /* Initialise ETH */\r
-\r
- xETH.Instance = ETH;\r
- xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
- xETH.Init.Speed = ETH_SPEED_100M;\r
- xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
- /* Value of PhyAddress doesn't matter, will be probed for. */\r
- xETH.Init.PhyAddress = 0;\r
+ xETH.Instance = ETH;\r
+ xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
+ xETH.Init.Speed = ETH_SPEED_100M;\r
+ xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+ /* Value of PhyAddress doesn't matter, will be probed for. */\r
+ xETH.Init.PhyAddress = 0;\r
\r
- xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;\r
- xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
+ xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress();\r
+ xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
\r
- /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
- both the IP and the protocol checksums will be calculated\r
- by the peripheral. */\r
- xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ {\r
+ /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
+ both the IP and the protocol checksums will be calculated\r
+ by the peripheral. */\r
+ xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
+ }\r
+ #else\r
+ {\r
+ xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;\r
+ }\r
+ #endif\r
\r
- #if( ipconfigUSE_RMII != 0 )\r
- {\r
- xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
- }\r
- #else\r
- {\r
- xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
- }\r
- #endif /* ipconfigUSE_RMII */\r
+ #if( ipconfigUSE_RMII != 0 )\r
+ {\r
+ xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
+ }\r
+ #else\r
+ {\r
+ xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
+ }\r
+ #endif /* ipconfigUSE_RMII */\r
\r
- hal_eth_init_status = HAL_ETH_Init( &xETH );\r
+ hal_eth_init_status = HAL_ETH_Init( &xETH );\r
\r
- /* Only for inspection by debugger. */\r
- ( void ) hal_eth_init_status;\r
+ /* Only for inspection by debugger. */\r
+ ( void ) hal_eth_init_status;\r
\r
- /* Set the TxDesc and RxDesc pointers. */\r
- xETH.TxDesc = DMATxDscrTab;\r
- xETH.RxDesc = DMARxDscrTab;\r
+ /* Set the TxDesc and RxDesc pointers. */\r
+ xETH.TxDesc = DMATxDscrTab;\r
+ xETH.RxDesc = DMARxDscrTab;\r
\r
- /* Make sure that all unused fields are cleared. */\r
- memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
- memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
+ /* Make sure that all unused fields are cleared. */\r
+ memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
+ memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
\r
- /* Initialize Tx Descriptors list: Chain Mode */\r
- DMATxDescToClear = DMATxDscrTab;\r
+ /* Initialize Tx Descriptors list: Chain Mode */\r
+ DMATxDescToClear = DMATxDscrTab;\r
\r
- /* Initialise TX-descriptors. */\r
- prvDMATxDescListInit();\r
+ /* Initialise TX-descriptors. */\r
+ prvDMATxDescListInit();\r
\r
- /* Initialise RX-descriptors. */\r
- prvDMARxDescListInit();\r
+ /* Initialise RX-descriptors. */\r
+ prvDMARxDescListInit();\r
\r
- #if( ipconfigUSE_LLMNR != 0 )\r
- {\r
- /* Program the LLMNR address at index 1. */\r
- prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
- }\r
- #endif\r
+ #if( ipconfigUSE_LLMNR != 0 )\r
+ {\r
+ /* Program the LLMNR address at index 1. */\r
+ prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
+ }\r
+ #endif\r
\r
- /* Force a negotiation with the Switch or Router and wait for LS. */\r
- prvEthernetUpdateConfig( pdTRUE );\r
+ /* Force a negotiation with the Switch or Router and wait for LS. */\r
+ prvEthernetUpdateConfig( pdTRUE );\r
\r
- /* The deferred interrupt handler task is created at the highest\r
- possible priority to ensure the interrupt handler can return directly\r
- to it. The task's handle is stored in xEMACTaskHandle so interrupts can\r
- notify the task when there is something to process. */\r
- xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+ /* The deferred interrupt handler task is created at the highest\r
+ possible priority to ensure the interrupt handler can return directly\r
+ to it. The task's handle is stored in xEMACTaskHandle so interrupts can\r
+ notify the task when there is something to process. */\r
+ if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS )\r
+ {\r
+ /* The xTXDescriptorSemaphore and the task are created successfully. */\r
+ xMacInitStatus = eMACPass;\r
+ }\r
+ else\r
+ {\r
+ xMacInitStatus = eMACFailed;\r
+ }\r
+ }\r
} /* if( xEMACTaskHandle == NULL ) */\r
\r
- if( xPhyObject.ulLinkStatusMask != 0 )\r
+ if( xMacInitStatus != eMACPass )\r
{\r
- xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
- xResult = pdPASS;\r
- FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
+ /* EMAC initialisation failed, return pdFAIL. */\r
+ xResult = pdFAIL;\r
}\r
else\r
{\r
- /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
- and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
- xResult = pdFAIL;\r
- FreeRTOS_printf( ( "Link Status still low\n" ) ) ;\r
+ if( xPhyObject.ulLinkStatusMask != 0uL )\r
+ {\r
+ xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
+ xResult = pdPASS;\r
+ FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
+ }\r
+ else\r
+ {\r
+ /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
+ and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
+ xResult = pdFAIL;\r
+ }\r
}\r
/* When returning non-zero, the stack will become active and\r
start DHCP (in configured) */\r
/* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
}\r
+ else\r
+ {\r
+ pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL );\r
+ }\r
\r
/* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
if( xIndex < ETH_TXBUFNB - 1 )\r
{\r
uint32_t ulTempReg;\r
\r
+ ( void ) heth;\r
+\r
/* Calculate the selected MAC address high register. */\r
ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
\r
/* 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
+ /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+ do\r
{\r
- ProtocolPacket_t *pxPacket;\r
-\r
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )\r
{\r
- configASSERT( bReleaseAfterSend != 0 );\r
+ /* The packet has been sent back to the IP-task.\r
+ The IP-task will further handle it.\r
+ Do not release the descriptor. */\r
+ bReleaseAfterSend = pdFALSE;\r
+ break;\r
}\r
- #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ {\r
+ ProtocolPacket_t *pxPacket;\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
+ /* 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
+ if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )\r
+ {\r
+ pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
+ }\r
}\r
- }\r
- #endif\r
-\r
- /* Open a do {} while ( 0 ) loop to be able to call break. */\r
- do\r
- {\r
+ #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */\r
if( xPhyObject.ulLinkStatusMask != 0 )\r
{\r
if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
}\r
#else\r
{\r
+ configASSERT( bReleaseAfterSend != 0 );\r
+\r
/* Move the buffer. */\r
pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;\r
/* The Network Buffer has been passed to DMA, no need to release it. */\r
\r
/* Ask to set the IPv4 checksum.\r
Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */\r
- pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ {\r
+ pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
+ }\r
+ #else\r
+ {\r
+ pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC );\r
+ pxDmaTxDesc->Status |= ETH_DMATXDESC_IC;\r
+ }\r
+ #endif\r
+ \r
\r
/* Prepare transmit descriptors to give to DMA. */\r
\r
pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
/* Set frame size */\r
pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
+\r
+ #if( NETWORK_BUFFERS_CACHED != 0 )\r
+ {\r
+ BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );\r
+ uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );\r
+ cache_clean_invalidate_by_addr( pulBuffer, xlength );\r
+ }\r
+ #endif\r
+\r
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
\r
\r
if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
{\r
- uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;\r
+ uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort );\r
+ uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort );\r
\r
- if( ( xPortHasUDPSocket( port ) == pdFALSE )\r
+ if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )\r
#if ipconfigUSE_LLMNR == 1\r
- && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )\r
+ && ( usDestinationPort != ipLLMNR_PORT )\r
+ && ( usSourcePort != ipLLMNR_PORT )\r
#endif\r
#if ipconfigUSE_NBNS == 1\r
- && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )\r
+ && ( usDestinationPort != ipNBNS_PORT )\r
+ && ( usSourcePort != ipNBNS_PORT )\r
#endif\r
#if ipconfigUSE_DNS == 1\r
- && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )\r
+ && ( usSourcePort != ipDNS_PORT )\r
#endif\r
) {\r
/* Drop this packet, not for this device. */\r
+ /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */\r
return pdFALSE;\r
}\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )\r
+{\r
+IPStackEvent_t xRxEvent;\r
+\r
+ xRxEvent.eEventType = eNetworkRxEvent;\r
+ xRxEvent.pvData = ( void * ) pxDescriptor;\r
+\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )\r
+ {\r
+ /* The buffer could not be sent to the stack so must be released again.\r
+ This is a deferred handler taskr, not a real interrupt, so it is ok to\r
+ use the task level function here. */\r
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+ {\r
+ do\r
+ {\r
+ NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ pxDescriptor = pxNext;\r
+ } while( pxDescriptor != NULL );\r
+ }\r
+ #else\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+ #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );\r
+ }\r
+ else\r
+ {\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ }\r
+}\r
+\r
static BaseType_t prvNetworkInterfaceInput( void )\r
{\r
NetworkBufferDescriptor_t *pxCurDescriptor;\r
NetworkBufferDescriptor_t *pxNewDescriptor = NULL;\r
-BaseType_t xReceivedLength, xAccepted;\r
+#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+ NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;\r
+ NetworkBufferDescriptor_t *pxLastDescriptor = NULL;\r
+#endif\r
+BaseType_t xReceivedLength = 0;\r
__IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
-xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS );\r
uint8_t *pucBuffer;\r
\r
pxDMARxDescriptor = xETH.RxDesc;\r
\r
- if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )\r
+ while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u )\r
{\r
+ BaseType_t xAccepted = pdTRUE;\r
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */\r
xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;\r
\r
/* 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
if( xAccepted != pdFALSE )\r
{\r
pxCurDescriptor->xDataLength = xReceivedLength;\r
- xRxEvent.pvData = ( void * ) pxCurDescriptor;\r
-\r
- /* Pass the data to the TCP/IP task for processing. */\r
- if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
{\r
- /* Could not send the descriptor into the TCP/IP stack, it\r
- must be released. */\r
- vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );\r
- iptraceETHERNET_RX_EVENT_LOST();\r
+ pxCurDescriptor->pxNextBuffer = NULL;\r
+\r
+ if( pxFirstDescriptor == NULL )\r
+ {\r
+ // Becomes the first message\r
+ pxFirstDescriptor = pxCurDescriptor;\r
+ }\r
+ else if( pxLastDescriptor != NULL )\r
+ {\r
+ // Add to the tail\r
+ pxLastDescriptor->pxNextBuffer = pxCurDescriptor;\r
+ }\r
+\r
+ pxLastDescriptor = pxCurDescriptor;\r
}\r
- else\r
+ #else\r
{\r
- iptraceNETWORK_INTERFACE_RECEIVE();\r
+ prvPassEthMessages( pxCurDescriptor );\r
}\r
+ #endif\r
}\r
\r
/* Release descriptors to DMA */\r
/* Resume DMA reception. */\r
xETH.Instance->DMARPDR = 0;\r
}\r
+ pxDMARxDescriptor = xETH.RxDesc;\r
+ }\r
+\r
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+ {\r
+ if( pxFirstDescriptor != NULL )\r
+ {\r
+ prvPassEthMessages( pxFirstDescriptor );\r
+ }\r
}\r
+ #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
\r
return ( xReceivedLength > 0 );\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-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
\r
/* Uncomment this in case BufferAllocation_1.c is used. */\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
+static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
uint8_t *ucRAMBuffer = ucNetworkPackets;\r
uint32_t ul;\r
\r
{\r
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
- ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+ ucRAMBuffer += ETH_MAX_PACKET_SIZE;\r
}\r
}\r
-*/\r
/*-----------------------------------------------------------*/\r
\r
static void prvEMACHandlerTask( void *pvParameters )\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