summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c14
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c102
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c928
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c924
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h1418
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c6
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c12
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c10
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c45
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt5
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c16
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c8
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c889
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c2
18 files changed, 4296 insertions, 91 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
index 83c96a07c..dc70ed993 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -219,19 +219,19 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
}
if( xTxBufferQueue == NULL )
{
xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
- configASSERT( xTxBufferQueue );
+ configASSERT( xTxBufferQueue != NULL );
}
if( xTXDescriptorSemaphore == NULL )
{
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
- configASSERT( xTXDescriptorSemaphore );
+ configASSERT( xTXDescriptorSemaphore != NULL );
}
/* When returning non-zero, the stack will become active and
start DHCP (in configured) */
@@ -296,7 +296,7 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
#endif /* ipconfigZERO_COPY_TX_DRIVER */
/* Not interested in a call-back after TX. */
iptraceNETWORK_INTERFACE_TRANSMIT();
- } while( 0 );
+ } while( ipFALSE_BOOL );
if( bReleaseAfterSend != pdFALSE )
{
@@ -417,7 +417,7 @@ const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
/* Calculate the IP header checksum. */
pxIPHeader->usHeaderChecksum = 0x00;
- pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
/* Calculate the TCP checksum for an outgoing packet. */
@@ -519,7 +519,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
index 948f9a661..87b837702 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
@@ -141,7 +141,7 @@ typedef struct gmac_dev_mem {
/** Circular buffer is empty ? */
#define CIRC_EMPTY( head, tail ) ( head == tail )
/** Clear circular buffer */
-#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )
+#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( ipFALSE_BOOL )
/** Increment head or tail */
static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
index fa7695942..5d77b8bbe 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
@@ -34,60 +34,60 @@
#ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still high after 15 seconds of not
receiving packets. */
- #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000uL
+ #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000UL
#endif
#ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still low every second. */
- #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000uL
+ #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000UL
#endif
/* As the following 3 macro's are OK in most situations, and so they're not
included in 'FreeRTOSIPConfigDefaults.h'.
Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
#ifndef phyPHY_MAX_RESET_TIME_MS
- #define phyPHY_MAX_RESET_TIME_MS 1000uL
+ #define phyPHY_MAX_RESET_TIME_MS 1000UL
#endif
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
- #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000uL
+ #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000UL
#endif
#ifndef phySHORT_DELAY_MS
- #define phySHORT_DELAY_MS 50uL
+ #define phySHORT_DELAY_MS 50UL
#endif
/* Naming and numbering of basic PHY registers. */
-#define phyREG_00_BMCR 0x00u /* Basic Mode Control Register. */
-#define phyREG_01_BMSR 0x01u /* Basic Mode Status Register. */
-#define phyREG_02_PHYSID1 0x02u /* PHYS ID 1 */
-#define phyREG_03_PHYSID2 0x03u /* PHYS ID 2 */
-#define phyREG_04_ADVERTISE 0x04u /* Advertisement control reg */
+#define phyREG_00_BMCR 0x00U /* Basic Mode Control Register. */
+#define phyREG_01_BMSR 0x01U /* Basic Mode Status Register. */
+#define phyREG_02_PHYSID1 0x02U /* PHYS ID 1 */
+#define phyREG_03_PHYSID2 0x03U /* PHYS ID 2 */
+#define phyREG_04_ADVERTISE 0x04U /* Advertisement control reg */
/* Naming and numbering of extended PHY registers. */
-#define PHYREG_10_PHYSTS 0x10u /* 16 PHY status register Offset */
-#define phyREG_19_PHYCR 0x19u /* 25 RW PHY Control Register */
-#define phyREG_1F_PHYSPCS 0x1Fu /* 31 RW PHY Special Control Status */
+#define PHYREG_10_PHYSTS 0x10U /* 16 PHY status register Offset */
+#define phyREG_19_PHYCR 0x19U /* 25 RW PHY Control Register */
+#define phyREG_1F_PHYSPCS 0x1FU /* 31 RW PHY Special Control Status */
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
-#define phyBMCR_FULL_DUPLEX 0x0100u /* Full duplex. */
-#define phyBMCR_AN_RESTART 0x0200u /* Auto negotiation restart. */
-#define phyBMCR_ISOLATE 0x0400u /* 1 = Isolates 0 = Normal operation. */
-#define phyBMCR_AN_ENABLE 0x1000u /* Enable auto negotiation. */
-#define phyBMCR_SPEED_100 0x2000u /* Select 100Mbps. */
-#define phyBMCR_RESET 0x8000u /* Reset the PHY. */
+#define phyBMCR_FULL_DUPLEX 0x0100U /* Full duplex. */
+#define phyBMCR_AN_RESTART 0x0200U /* Auto negotiation restart. */
+#define phyBMCR_ISOLATE 0x0400U /* 1 = Isolates 0 = Normal operation. */
+#define phyBMCR_AN_ENABLE 0x1000U /* Enable auto negotiation. */
+#define phyBMCR_SPEED_100 0x2000U /* Select 100Mbps. */
+#define phyBMCR_RESET 0x8000U /* Reset the PHY. */
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
-#define PHYCR_MDIX_EN 0x8000u /* Enable Auto MDIX. */
-#define PHYCR_MDIX_FORCE 0x4000u /* Force MDIX crossed. */
+#define PHYCR_MDIX_EN 0x8000U /* Enable Auto MDIX. */
+#define PHYCR_MDIX_FORCE 0x4000U /* Force MDIX crossed. */
-#define phyBMSR_AN_COMPLETE 0x0020u /* Auto-Negotiation process completed */
+#define phyBMSR_AN_COMPLETE 0x0020U /* Auto-Negotiation process completed */
-#define phyBMSR_LINK_STATUS 0x0004u
+#define phyBMSR_LINK_STATUS 0x0004U
-#define phyPHYSTS_LINK_STATUS 0x0001u /* PHY Link mask */
-#define phyPHYSTS_SPEED_STATUS 0x0002u /* PHY Speed mask */
-#define phyPHYSTS_DUPLEX_STATUS 0x0004u /* PHY Duplex mask */
+#define phyPHYSTS_LINK_STATUS 0x0001U /* PHY Link mask */
+#define phyPHYSTS_SPEED_STATUS 0x0002U /* PHY Speed mask */
+#define phyPHYSTS_DUPLEX_STATUS 0x0004U /* PHY Duplex mask */
/* Bit fields for 'phyREG_1F_PHYSPCS
001 = 10BASE-T half-duplex
@@ -95,20 +95,20 @@ Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
010 = 100BASE-TX half-duplex
110 = 100BASE-TX full-duplex
*/
-#define phyPHYSPCS_SPEED_MASK 0x000Cu
-#define phyPHYSPCS_SPEED_10 0x0004u
-#define phyPHYSPCS_FULL_DUPLEX 0x0010u
+#define phyPHYSPCS_SPEED_MASK 0x000CU
+#define phyPHYSPCS_SPEED_10 0x0004U
+#define phyPHYSPCS_FULL_DUPLEX 0x0010U
/*
* Description of all capabilities that can be advertised to
* the peer (usually a switch or router).
*/
-#define phyADVERTISE_CSMA 0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
-#define phyADVERTISE_10HALF 0x0020u /* Try for 10mbps half-duplex. */
-#define phyADVERTISE_10FULL 0x0040u /* Try for 10mbps full-duplex. */
-#define phyADVERTISE_100HALF 0x0080u /* Try for 100mbps half-duplex. */
-#define phyADVERTISE_100FULL 0x0100u /* Try for 100mbps full-duplex. */
+#define phyADVERTISE_CSMA 0x0001U /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
+#define phyADVERTISE_10HALF 0x0020U /* Try for 10mbps half-duplex. */
+#define phyADVERTISE_10FULL 0x0040U /* Try for 10mbps full-duplex. */
+#define phyADVERTISE_100HALF 0x0080U /* Try for 100mbps half-duplex. */
+#define phyADVERTISE_100FULL 0x0100U /* Try for 100mbps full-duplex. */
#define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
@@ -167,7 +167,7 @@ BaseType_t xResult;
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite )
{
- memset( ( void * )pxPhyObject, '\0', sizeof( *pxPhyObject ) );
+ memset( ( void * )pxPhyObject, 0, sizeof( *pxPhyObject ) );
pxPhyObject->fnPhyRead = fnPhyRead;
pxPhyObject->fnPhyWrite = fnPhyWrite;
@@ -187,7 +187,7 @@ BaseType_t xPhyAddress;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
/* A valid PHY id can not be all zeros or all ones. */
- if( ( ulLowerID != ( uint16_t )~0u ) && ( ulLowerID != ( uint16_t )0u ) )
+ if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
{
uint32_t ulUpperID;
uint32_t ulPhyID;
@@ -225,7 +225,7 @@ TimeOut_t xTimer;
BaseType_t xPhyIndex;
/* A bit-mask of PHY ports that are ready. */
- ulDoneMask = 0ul;
+ ulDoneMask = 0UL;
/* Set the RESET bits high. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
@@ -251,7 +251,7 @@ BaseType_t xPhyIndex;
if( ( ulConfig & phyBMCR_RESET ) == 0 )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) );
- ulDoneMask |= ( 1ul << xPhyIndex );
+ ulDoneMask |= ( 1UL << xPhyIndex );
}
}
if( ulDoneMask == ulPhyMask )
@@ -270,7 +270,7 @@ BaseType_t xPhyIndex;
/* Clear the reset bits. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
- if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL )
+ if( ( ulDoneMask & ( 1UL << xPhyIndex ) ) == 0UL )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
@@ -454,9 +454,9 @@ with ulPhyMask. */
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{
BaseType_t xPhyIndex;
-uint32_t ulValue, ulBitMask = ( uint32_t )1u;
+uint32_t ulValue, ulBitMask = ( uint32_t )1U;
- ulValue = ( uint32_t )0u;
+ ulValue = ( uint32_t ) 0U;
if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
{
@@ -491,7 +491,7 @@ uint32_t ulPHYLinkStatus, ulRegValue;
TickType_t xRemainingTime;
TimeOut_t xTimer;
- if( ulPhyMask == ( uint32_t )0u )
+ if( ulPhyMask == ( uint32_t ) 0U )
{
return 0;
}
@@ -512,7 +512,7 @@ TimeOut_t xTimer;
/* Wait until the auto-negotiation will be completed */
for( ;; )
{
- ulBitMask = ( uint32_t )1u;
+ ulBitMask = ( uint32_t ) 1U;
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
@@ -541,16 +541,16 @@ TimeOut_t xTimer;
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
- if( ulDoneMask != ( uint32_t)0u )
+ if( ulDoneMask != ( uint32_t) 0U )
{
- ulBitMask = ( uint32_t )1u;
+ ulBitMask = ( uint32_t ) 1U;
pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
- if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u )
+ if( ( ulDoneMask & ulBitMask ) == ( uint32_t ) 0U )
{
continue;
}
@@ -632,7 +632,7 @@ TimeOut_t xTimer;
( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) );
- if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u )
+ if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t ) 0U )
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
}
@@ -650,7 +650,7 @@ TimeOut_t xTimer;
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
}
}
- } /* if( ulDoneMask != ( uint32_t)0u ) */
+ } /* if( ulDoneMask != ( uint32_t) 0U ) */
return 0;
}
@@ -658,7 +658,7 @@ TimeOut_t xTimer;
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
{
-uint32_t ulStatus, ulBitMask = 1u;
+uint32_t ulStatus, ulBitMask = 1U;
BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE;
@@ -670,7 +670,7 @@ BaseType_t xNeedCheck = pdFALSE;
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
- if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul )
+ if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0UL )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
@@ -705,7 +705,7 @@ BaseType_t xNeedCheck = pdFALSE;
}
}
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
- if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
+ if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )
{
/* The link status is high, so don't poll the PHY too often. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c
new file mode 100644
index 000000000..543cc1d62
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c
@@ -0,0 +1,928 @@
+/*
+FreeRTOS+TCP V2.2.1
+Copyright (C) 2017 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
+*/
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "FreeRTOS_ARP.h"
+#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
+
+/* Some files from the Atmel Software Framework */
+/* gmac_SAM.[ch] is a combination of the gmac.[ch] for both SAM4E and SAME70. */
+#include "gmac_SAM.h"
+#include <sysclk.h>
+#include "phyhandling.h"
+
+/* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */
+#include "conf_board.h"
+
+
+/* Interrupt events to process. Currently only the Rx event is processed
+although code for other events is included to allow for possible future
+expansion. */
+#define EMAC_IF_RX_EVENT 1UL
+#define EMAC_IF_TX_EVENT 2UL
+#define EMAC_IF_ERR_EVENT 4UL
+#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
+
+/* 1536 bytes is more than needed, 1524 would be enough.
+But 1536 is a multiple of 32, which gives a great alignment for
+cached memories. */
+
+#define NETWORK_BUFFER_SIZE 1536
+
+#ifndef EMAC_MAX_BLOCK_TIME_MS
+ /* The task 'prvEMACHandlerTask()' will wake-up every 100 ms, to see
+ if something has to be done, mostly checking if the PHY has a
+ change in Link Status. */
+ #define EMAC_MAX_BLOCK_TIME_MS 100ul
+#endif
+
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ #error This driver works optimal if ipconfigZERO_COPY_RX_DRIVER is defined as 1
+#endif
+
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ #error This driver works optimal if ipconfigZERO_COPY_TX_DRIVER is defined as 1
+#endif
+
+/* Default the size of the stack used by the EMAC deferred handler task to 4x
+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 ( 4 * configMINIMAL_STACK_SIZE )
+#endif
+
+#ifndef niEMAC_HANDLER_TASK_PRIORITY
+ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
+#endif
+
+#if( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
+ #include "core_cm7.h"
+ #warning This driver assumes the presence of DCACHE
+ #define NETWORK_BUFFERS_CACHED 1
+ #define CACHE_LINE_SIZE 32
+ #define NETWORK_BUFFER_HEADER_SIZE ( ipconfigPACKET_FILLER_SIZE + 8 )
+
+ static void cache_clean_invalidate()
+ {
+ /* If you application crashes here, make sure that SCB_EnableDCache() has been called. */
+ SCB_CleanInvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+ static void cache_clean_invalidate_by_addr(uint32_t addr, uint32_t size)
+ {
+ /* SAME70 does not have clean/invalidate per area. */
+ /* SCB_CleanInvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
+ SCB_CleanInvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+ static void cache_invalidate_by_addr(addr, size) \
+ {
+ /* SAME70 does not have clean/invalidate per area. */
+ /* SCB_InvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
+ SCB_InvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+#else
+ #warning Sure there is no caching?
+ #define cache_clean_invalidate() do {} while( 0 )
+ #define cache_clean_invalidate_by_addr(addr, size) do {} while( 0 )
+ #define cache_invalidate_by_addr(addr, size) do {} while( 0 )
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Update settings in GMAC for speed and duplex.
+ */
+static void prvEthernetUpdateConfig( BaseType_t xForce );
+
+/*
+ * Access functions to the PHY's: read() and write() to be used by
+ * phyHandling.c.
+ */
+static BaseType_t xPHY_Read( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue );
+static BaseType_t xPHY_Write( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue );
+
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
+ void vGMACGenerateChecksum( uint8_t *apBuffer, size_t uxLength );
+#endif
+
+/*
+ * Called from the ASF GMAC driver.
+ */
+void xRxCallback( uint32_t ulStatus );
+void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
+
+/*
+ * A deferred interrupt handler task that processes GMAC interrupts.
+ */
+static void prvEMACHandlerTask( void *pvParameters );
+
+/*
+ * Initialise the ASF GMAC driver.
+ */
+static BaseType_t prvGMACInit( void );
+
+/*
+ * Try to obtain an Rx packet from the hardware.
+ */
+static uint32_t prvEMACRxPoll( void );
+
+/*
+ * Handle transmission errors.
+ */
+static void hand_tx_errors( void );
+
+/*-----------------------------------------------------------*/
+
+/* Bit map of outstanding ETH interrupt events for processing. Currently only
+the Rx interrupt is handled, although code is included for other events to
+enable future expansion. */
+static volatile uint32_t ulISREvents;
+
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
+static volatile BaseType_t xGMACSwitchRequired;
+
+/* LLMNR multicast address. */
+static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
+
+/* The GMAC object as defined by the ASF drivers. */
+static gmac_device_t gs_gmac_dev;
+
+/* MAC address to use. */
+extern const uint8_t ucMACAddress[ 6 ];
+
+/* Holds the handle of the task used as a deferred interrupt processor. The
+handle is used so direct notifications can be sent to the task for all EMAC/DMA
+related interrupts. */
+TaskHandle_t xEMACTaskHandle = NULL;
+
+static QueueHandle_t xTxBufferQueue;
+int tx_release_count[ 4 ];
+
+/* xTXDescriptorSemaphore is a counting semaphore with
+a maximum count of GMAC_TX_BUFFERS, which is the number of
+DMA TX descriptors. */
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
+
+/* For local use only: describe the PHY's properties: */
+const PhyProperties_t xPHYProperties =
+{
+ #if( ipconfigETHERNET_AN_ENABLE != 0 )
+ .ucSpeed = PHY_SPEED_AUTO,
+ .ucDuplex = PHY_DUPLEX_AUTO,
+ #else
+ #if( ipconfigETHERNET_USE_100MB != 0 )
+ .ucSpeed = PHY_SPEED_100,
+ #else
+ .ucSpeed = PHY_SPEED_10,
+ #endif
+
+ #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
+ .ucDuplex = PHY_DUPLEX_FULL,
+ #else
+ .ucDuplex = PHY_DUPLEX_HALF,
+ #endif
+ #endif
+
+ #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
+ .ucMDI_X = PHY_MDIX_AUTO,
+ #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
+ .ucMDI_X = PHY_MDIX_CROSSED,
+ #else
+ .ucMDI_X = PHY_MDIX_DIRECT,
+ #endif
+};
+
+/* All PHY handling code has now been separated from the NetworkInterface.c,
+see "../Common/phyHandling.c". */
+static EthernetPhy_t xPhyObject;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * GMAC interrupt handler.
+ */
+void GMAC_Handler(void)
+{
+ xGMACSwitchRequired = pdFALSE;
+
+ /* gmac_handler() may call xRxCallback() which may change
+ the value of xGMACSwitchRequired. */
+ gmac_handler( &gs_gmac_dev );
+
+ if( xGMACSwitchRequired != pdFALSE )
+ {
+ portEND_SWITCHING_ISR( xGMACSwitchRequired );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void xRxCallback( uint32_t ulStatus )
+{
+ if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )
+ {
+ /* let the prvEMACHandlerTask know that there was an RX event. */
+ ulISREvents |= EMAC_IF_RX_EVENT;
+ /* Only an RX interrupt can wakeup prvEMACHandlerTask. */
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void returnTxBuffer(uint8_t *puc_buffer)
+{
+ /* Called from a non-ISR context. */
+ if( xTxBufferQueue != NULL )
+ {
+ xQueueSend( xTxBufferQueue, &puc_buffer, 0 );
+ xTaskNotifyGive( xEMACTaskHandle );
+ ulISREvents |= EMAC_IF_TX_EVENT;
+ }
+}
+
+void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )
+{
+ if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
+ {
+ /* let the prvEMACHandlerTask know that there was an TX event. */
+ ulISREvents |= EMAC_IF_TX_EVENT;
+ /* Wakeup prvEMACHandlerTask. */
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
+ xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );
+ tx_release_count[ 2 ]++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+
+/*
+ The two standard defines 'GMAC_MAN_RW_TYPE' and 'GMAC_MAN_READ_ONLY'
+ are incorrect.
+ Therefore, use the following:
+*/
+
+#define GMAC_MAINTENANCE_READ_ACCESS (2)
+#define GMAC_MAINTENANCE_WRITE_ACCESS (1)
+
+static BaseType_t xPHY_Read( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
+{
+BaseType_t xReturn;
+UBaseType_t uxWasEnabled;
+
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ /*
+ * OP: Operation: 10 is read. 01 is write.
+ */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ GMAC->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(xAddress)
+ | GMAC_MAN_REGA(xRegister)
+ | GMAC_MAN_OP(GMAC_MAINTENANCE_READ_ACCESS)
+ | GMAC_MAN_DATA( (uint16_t)0u );
+
+ if (gmac_wait_phy(GMAC, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT)
+ {
+ *pulValue = (uint32_t)0xffffu;
+ xReturn = -1;
+ }
+ else
+ {
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+
+ /* Return data */
+ *pulValue = (uint32_t)(GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk);
+
+ xReturn = 0;
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t xPHY_Write( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
+{
+BaseType_t xReturn;
+UBaseType_t uxWasEnabled;
+
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ GMAC->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(xAddress)
+ | GMAC_MAN_REGA(xRegister)
+ | GMAC_MAN_OP(GMAC_MAINTENANCE_WRITE_ACCESS)
+ | GMAC_MAN_DATA( (uint16_t)ulValue );
+
+ if (gmac_wait_phy(GMAC, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT )
+ {
+ xReturn = -1;
+ }
+ else
+ {
+ xReturn = 0;
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xNetworkInterfaceInitialise( void )
+{
+const TickType_t x5_Seconds = 5000UL;
+
+ if( xEMACTaskHandle == NULL )
+ {
+ prvGMACInit();
+
+ cache_clean_invalidate();
+
+ /* The handler task is created at the highest possible priority to
+ ensure the interrupt handler can return directly to it. */
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle );
+ }
+
+ if( xTxBufferQueue == NULL )
+ {
+ xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
+ configASSERT( xTxBufferQueue );
+ }
+
+ if( xTXDescriptorSemaphore == NULL )
+ {
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
+ configASSERT( xTXDescriptorSemaphore );
+ }
+ /* When returning non-zero, the stack will become active and
+ start DHCP (in configured) */
+ return xGetPhyLinkStatus();
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xGetPhyLinkStatus( void )
+{
+BaseType_t xReturn;
+
+ if( xPhyObject.ulLinkStatusMask != 0 )
+ {
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+/** The GMAC TX errors to handle */
+#define GMAC_TX_ERRORS (GMAC_TSR_TFC | GMAC_TSR_HRESP)
+
+static void hand_tx_errors( void )
+{
+/* Handle GMAC underrun or AHB errors. */
+ if (gmac_get_tx_status(GMAC) & GMAC_TX_ERRORS) {
+
+ gmac_enable_transmit(GMAC, false);
+
+ /* Reinit TX descriptors. */
+// gmac_tx_init(ps_gmac_dev);
+ gmac_reset_tx_mem(&gs_gmac_dev);
+ /* Clear error status. */
+ gmac_clear_tx_status(GMAC, GMAC_TX_ERRORS);
+
+ gmac_enable_transmit(GMAC, true);
+ }
+}
+
+volatile IPPacket_t *pxSendPacket;
+
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
+{
+/* Do not wait too long for a free TX DMA buffer. */
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
+uint32_t ulTransmitSize;
+
+ ulTransmitSize = pxDescriptor->xDataLength;
+
+ pxSendPacket = (IPPacket_t *)pxDescriptor->pucEthernetBuffer;
+
+ if( ulTransmitSize > NETWORK_BUFFER_SIZE )
+ {
+ ulTransmitSize = NETWORK_BUFFER_SIZE;
+ }
+ /* A do{}while(0) loop is introduced to allow the use of multiple break
+ statement. */
+ do {
+ if( xPhyObject.ulLinkStatusMask == 0ul )
+ {
+ /* Do not attempt to send packets as long as the Link Status is low. */
+ break;
+ }
+ if( xTXDescriptorSemaphore == NULL )
+ {
+ /* Semaphore has not been created yet? */
+ break;
+ }
+ hand_tx_errors();
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
+ {
+ /* Time-out waiting for a free TX descriptor. */
+ tx_release_count[ 3 ]++;
+ break;
+ }
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Confirm that the pxDescriptor may be kept by the driver. */
+ configASSERT( bReleaseAfterSend != pdFALSE );
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+ #if( NETWORK_BUFFERS_CACHED != 0 )
+ {
+ uint32_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );
+ uint32_t xAddress = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );
+ cache_clean_invalidate_by_addr( xAddress, xlength );
+ }
+ #endif
+
+ gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );
+
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Confirm that the pxDescriptor may be kept by the driver. */
+ bReleaseAfterSend = pdFALSE;
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ /* Not interested in a call-back after TX. */
+ iptraceNETWORK_INTERFACE_TRANSMIT();
+ } while( ipFALSE_BOOL );
+
+ if( bReleaseAfterSend != pdFALSE )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+ }
+ return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvGMACInit( void )
+{
+uint32_t ncfgr;
+
+ gmac_options_t gmac_option;
+
+ gmac_enable_management(GMAC, true);
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+
+ memset( &gmac_option, '\0', sizeof( gmac_option ) );
+ gmac_option.uc_copy_all_frame = 0;
+ gmac_option.uc_no_boardcast = 0;
+ memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );
+
+ gs_gmac_dev.p_hw = GMAC;
+ gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );
+
+ NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
+ NVIC_EnableIRQ( GMAC_IRQn );
+
+ {
+ /* Set MDC clock divider. */
+ gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() );
+
+ vPhyInitialise( &xPhyObject, xPHY_Read, xPHY_Write );
+ xPhyDiscover( &xPhyObject );
+ xPhyConfigure( &xPhyObject, &xPHYProperties );
+
+ /* For a reset / reconfigure of the EMAC. */
+ prvEthernetUpdateConfig( pdTRUE );
+
+ /* Select Media Independent Interface type */
+ #if( SAME70 != 0 )
+ {
+ /* Selecting RMII mode. */
+ GMAC->GMAC_UR &= ~GMAC_UR_RMII;
+ }
+ #else
+ {
+ gmac_select_mii_mode(GMAC, ETH_PHY_MODE);
+ }
+ #endif
+
+ gmac_enable_transmit(GMAC, true);
+ gmac_enable_receive(GMAC, true);
+
+ }
+
+ gmac_enable_management(GMAC, true);
+
+ gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );
+
+ gmac_enable_management(GMAC, false);
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+
+ return 1;
+}
+/*-----------------------------------------------------------*/
+
+static void prvEthernetUpdateConfig( BaseType_t xForce )
+{
+ FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
+ xPhyObject.ulLinkStatusMask,
+ ( int )xForce ) );
+
+ if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
+ {
+ #if( ipconfigETHERNET_AN_ENABLE != 0 )
+ {
+ UBaseType_t uxWasEnabled;
+
+ /* Restart the auto-negotiation. */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
+
+ /* Configure the MAC with the Duplex Mode fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
+ {
+ gmac_enable_full_duplex(GMAC, pdTRUE);
+ }
+ else
+ {
+ gmac_enable_full_duplex(GMAC, pdFALSE);
+ }
+
+ /* Configure the MAC with the speed fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
+ {
+ gmac_set_speed(GMAC, pdFALSE);
+ }
+ else
+ {
+ gmac_set_speed(GMAC, pdTRUE);
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+ }
+ #else
+ {
+ if( xPHYProperties.ucDuplex == PHY_DUPLEX_FULL )
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
+ gmac_enable_full_duplex(GMAC, pdTRUE);
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
+ gmac_enable_full_duplex(GMAC, pdFALSE);
+ }
+
+ if( xPHYProperties.ucSpeed == PHY_SPEED_100 )
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
+ gmac_set_speed(GMAC, pdTRUE);
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
+ gmac_set_speed(GMAC, pdFALSE);
+ }
+
+ xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
+
+ /* Use predefined (fixed) configuration. */
+ xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
+ }
+ #endif
+
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vGMACGenerateChecksum( uint8_t *pucBuffer, size_t uxLength )
+{
+ProtocolPacket_t *xProtPacket = ( ProtocolPacket_t * ) pucBuffer;
+
+ if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
+ {
+ IPHeader_t *pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader );
+
+ /* Calculate the IP header checksum. */
+ pxIPHeader->usHeaderChecksum = 0x00;
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
+
+ /* Calculate the TCP checksum for an outgoing packet. */
+ usGenerateProtocolChecksum( pucBuffer, uxLength, pdTRUE );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static uint32_t prvEMACRxPoll( void )
+{
+unsigned char *pucUseBuffer;
+uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;
+static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;
+const UBaseType_t xMinDescriptorsToLeave = 2UL;
+const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );
+static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
+uint8_t *pucDMABuffer = NULL;
+
+ for( ;; )
+ {
+ /* If pxNextNetworkBufferDescriptor was not left pointing at a valid
+ descriptor then allocate one now. */
+ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )
+ {
+ pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );
+ }
+
+ if( pxNextNetworkBufferDescriptor != NULL )
+ {
+ /* Point pucUseBuffer to the buffer pointed to by the descriptor. */
+ pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );
+ }
+ else
+ {
+ /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming
+ messages will be flushed and ignored. */
+ pucUseBuffer = NULL;
+ }
+
+ /* Read the next packet from the hardware into pucUseBuffer. */
+ ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount, &pucDMABuffer );
+
+ if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )
+ {
+ /* No data from the hardware. */
+ break;
+ }
+
+ if( pxNextNetworkBufferDescriptor == NULL )
+ {
+ /* Data was read from the hardware, but no descriptor was available
+ for it, so it will be dropped. */
+ iptraceETHERNET_RX_EVENT_LOST();
+ continue;
+ }
+
+ iptraceNETWORK_INTERFACE_RECEIVE();
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+ {
+ pxNextNetworkBufferDescriptor = pxPacketBuffer_to_NetworkBuffer( pucDMABuffer );
+ if( pxNextNetworkBufferDescriptor == NULL )
+ {
+ /* STrange: can not translate from a DMA buffer to a Network Buffer. */
+ break;
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+ pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
+ xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;
+
+ /* Send the descriptor to the IP task for processing. */
+ if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )
+ {
+ /* The buffer could not be sent to the stack so must be released
+ again. */
+ vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );
+ iptraceETHERNET_RX_EVENT_LOST();
+ FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
+ }
+
+ /* Now the buffer has either been passed to the IP-task,
+ or it has been released in the code above. */
+ pxNextNetworkBufferDescriptor = NULL;
+ ulReturnValue++;
+ }
+
+ return ulReturnValue;
+}
+/*-----------------------------------------------------------*/
+
+volatile UBaseType_t uxLastMinBufferCount = 0;
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ volatile UBaseType_t uxLastMinQueueSpace;
+#endif
+volatile UBaseType_t uxCurrentSemCount;
+volatile UBaseType_t uxLowestSemCount;
+
+void vCheckBuffersAndQueue( void )
+{
+static UBaseType_t uxCurrentCount;
+
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ {
+ uxCurrentCount = uxGetMinimumIPQueueSpace();
+ if( uxLastMinQueueSpace != uxCurrentCount )
+ {
+ /* The logging produced below may be helpful
+ while tuning +TCP: see how many buffers are in use. */
+ uxLastMinQueueSpace = uxCurrentCount;
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
+ }
+ }
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
+ 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 ) );
+ }
+ if( xTXDescriptorSemaphore != NULL )
+ {
+ uxCurrentSemCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
+ if( uxLowestSemCount > uxCurrentSemCount )
+ {
+ uxLowestSemCount = uxCurrentSemCount;
+ FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
+ }
+
+ }
+
+}
+/*-----------------------------------------------------------*/
+
+extern uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
+{
+uint8_t *ucRAMBuffer = ucNetworkPackets;
+uint32_t ulIndex;
+
+ for( ulIndex = 0; ulIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ulIndex++ )
+ {
+ pxNetworkBuffers[ ulIndex ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
+ *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ulIndex ] ) );
+ ucRAMBuffer += NETWORK_BUFFER_SIZE;
+ }
+ cache_clean_invalidate();
+}
+/*-----------------------------------------------------------*/
+
+static void prvEMACHandlerTask( void *pvParameters )
+{
+UBaseType_t uxCount;
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ NetworkBufferDescriptor_t *pxBuffer;
+#endif
+uint8_t *pucBuffer;
+BaseType_t xResult = 0;
+uint32_t xStatus;
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
+
+ /* Remove compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ configASSERT( xEMACTaskHandle );
+
+ for( ;; )
+ {
+ xResult = 0;
+ vCheckBuffersAndQueue();
+
+ if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
+ {
+ /* No events to process now, wait for the next. */
+ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
+ }
+
+ if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
+ {
+ ulISREvents &= ~EMAC_IF_RX_EVENT;
+
+ /* Wait for the EMAC interrupt to indicate that another packet has been
+ received. */
+ xResult = prvEMACRxPoll();
+ }
+
+ if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
+ {
+ /* Future extension: code to release TX buffers if zero-copy is used. */
+ ulISREvents &= ~EMAC_IF_TX_EVENT;
+ while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )
+ {
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
+ if( pxBuffer != NULL )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );
+ tx_release_count[ 0 ]++;
+ }
+ else
+ {
+ tx_release_count[ 1 ]++;
+ }
+ }
+ #else
+ {
+ tx_release_count[ 0 ]++;
+ }
+ #endif
+ uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );
+ if( uxCount < GMAC_TX_BUFFERS )
+ {
+ /* Tell the counting semaphore that one more TX descriptor is available. */
+ xSemaphoreGive( xTXDescriptorSemaphore );
+ }
+ }
+ }
+
+ if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
+ {
+ /* Future extension: logging about errors that occurred. */
+ ulISREvents &= ~EMAC_IF_ERR_EVENT;
+ }
+ gmac_enable_management(GMAC, true);
+ if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
+ {
+ /* Something has changed to a Link Status, need re-check. */
+ prvEthernetUpdateConfig( pdFALSE );
+ }
+ gmac_enable_management(GMAC, false);
+ }
+}
+/*-----------------------------------------------------------*/
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c
new file mode 100644
index 000000000..6732ec51b
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c
@@ -0,0 +1,924 @@
+/**
+ * \file
+ *
+ * \brief GMAC (Ethernet MAC) driver for SAM.
+ *
+ * Copyright (c) 2015-2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+#include "FreeRTOSIPConfig.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "FreeRTOS_ARP.h"
+#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
+
+#include "compiler.h"
+#include "gmac_SAM.h"
+
+#if( SAME70 != 0 )
+ /* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */
+ #include "conf_board.h"
+ #include "core_cm7.h"
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#ifndef ARRAY_SIZE
+ #define ARRAY_SIZE(x) (int)( sizeof(x) / sizeof(x)[0] )
+#endif
+
+#if( GMAC_RX_BUFFERS <= 1 )
+ #error Configuration error
+#endif
+
+#if( GMAC_TX_BUFFERS <= 1 )
+ #error Configuration error
+#endif
+
+/**
+ * \defgroup gmac_group Ethernet Media Access Controller
+ *
+ * See \ref gmac_quickstart.
+ *
+ * Driver for the GMAC (Ethernet Media Access Controller).
+ * This file contains basic functions for the GMAC, with support for all modes, settings
+ * and clock speeds.
+ *
+ * \section dependencies Dependencies
+ * This driver does not depend on other modules.
+ *
+ * @{
+ */
+
+#define NETWORK_BUFFER_SIZE 1536
+
+__attribute__ ( ( aligned( 32 ) ) )
+__attribute__ ( ( section( ".first_data" ) ) )
+ uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];
+
+/** TX descriptor lists */
+__attribute__ ((section(".first_data")))
+COMPILER_ALIGNED(8)
+static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];
+
+#if( SAME70 != 0 )
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static gmac_tx_descriptor_t gs_tx_desc_null;
+#endif
+
+/** RX descriptors lists */
+__attribute__ ((section(".first_data")))
+COMPILER_ALIGNED(8)
+static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];
+
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the
+ * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits
+ * of the address shall be set to 0.
+ */
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ /** Receive Buffer */
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];
+#endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+/** Return count in buffer */
+#define CIRC_CNT( head, tail, size ) ( ( ( head ) - ( tail ) ) % ( size ) )
+
+/*
+ * Return space available, from 0 to size-1.
+ * Always leave one free char as a completely full buffer that has (head == tail),
+ * which is the same as empty.
+ */
+#define CIRC_SPACE( head, tail, size ) CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )
+
+/** Circular buffer is empty ? */
+#define CIRC_EMPTY( head, tail ) ( ( head ) == ( tail ) )
+/** Clear circular buffer */
+#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )
+
+/* Two call-back functions that should be defined in NetworkInterface.c */
+extern void xRxCallback( uint32_t ulStatus );
+extern void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
+extern void returnTxBuffer(uint8_t *puc_buffer);
+
+
+/** Increment head or tail */
+static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
+{
+ ( *lHeadOrTail ) ++;
+ if( ( *lHeadOrTail ) >= ( int32_t )ulSize )
+ {
+ ( *lHeadOrTail ) = 0;
+ }
+}
+
+/**
+ * \brief Wait PHY operation to be completed.
+ *
+ * \param p_gmac HW controller address.
+ * \param ul_retry The retry times, 0 to wait forever until completeness.
+ *
+ * Return GMAC_OK if the operation is completed successfully.
+ */
+uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)
+{
+ volatile uint32_t ul_retry_count = 0;
+ const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );
+
+ while (!gmac_is_phy_idle(p_gmac)) {
+ if (ul_retry == 0) {
+ continue;
+ }
+
+ ul_retry_count++;
+
+ if (ul_retry_count >= ul_retry) {
+ return GMAC_TIMEOUT;
+ }
+
+ /* Block the task to allow other tasks to execute while the PHY
+ is not connected. */
+ vTaskDelay( xPHYPollDelay );
+ }
+ return GMAC_OK;
+}
+
+/**
+ * \brief Disable transfer, reset registers and descriptor lists.
+ *
+ * \param p_dev Pointer to GMAC driver instance.
+ *
+ */
+void gmac_reset_tx_mem(gmac_device_t* p_dev)
+{
+ Gmac *p_hw = p_dev->p_hw;
+
+ uint32_t ul_index;
+ uint32_t ul_address;
+
+ /* Disable TX */
+ gmac_enable_transmit(p_hw, 0);
+
+ {
+ for( ul_index = 0; ul_index < ARRAY_SIZE(gs_tx_desc); ul_index++ )
+ {
+ uint32_t ulAddr = gs_tx_desc[ul_index].addr;
+ if (ulAddr) {
+ returnTxBuffer ((uint8_t *)ulAddr);
+ }
+ }
+ }
+ /* Set up the TX descriptors */
+ CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);
+ for( ul_index = 0; ul_index < GMAC_TX_BUFFERS; ul_index++ )
+ {
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ ul_address = (uint32_t) 0u;
+ }
+ #else
+ {
+ ul_address = (uint32_t) (&(gs_uc_tx_buffer[ul_index * GMAC_TX_UNITSIZE]));
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ gs_tx_desc[ul_index].addr = ul_address;
+ gs_tx_desc[ul_index].status.val = GMAC_TXD_USED;
+ }
+ /* Set the WRAP bit in the last descriptor. */
+ gs_tx_desc[GMAC_TX_BUFFERS - 1].status.val = GMAC_TXD_USED | GMAC_TXD_WRAP;
+
+ /* Set transmit buffer queue */
+ gmac_set_tx_queue(p_hw, (uint32_t) gs_tx_desc);
+ #if( SAME70 != 0 )
+ {
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_1);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_2);
+ /* Note that SAME70 REV B had 6 priority queues. */
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_3);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_4);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_5);
+ }
+ #endif
+}
+
+/**
+ * \brief Disable receiver, reset registers and descriptor list.
+ *
+ * \param p_dev Pointer to GMAC Driver instance.
+ */
+static void gmac_reset_rx_mem(gmac_device_t* p_dev)
+{
+ Gmac *p_hw = p_dev->p_hw;
+
+ uint32_t ul_index;
+ uint32_t ul_address;
+
+ /* Disable RX */
+ gmac_enable_receive(p_hw, 0);
+
+ /* Set up the RX descriptors */
+ p_dev->ul_rx_idx = 0;
+ for( ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++ )
+ {
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+ {
+ NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor;
+
+ pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( GMAC_RX_UNITSIZE, 0ul );
+ configASSERT( pxNextNetworkBufferDescriptor != NULL );
+ ul_address = ( uint32_t )( pxNextNetworkBufferDescriptor->pucEthernetBuffer );
+ }
+ #else
+ {
+ ul_address = ( uint32_t ) ( &( gs_uc_rx_buffer[ ul_index * GMAC_RX_UNITSIZE ] ) );
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+ gs_rx_desc[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
+ gs_rx_desc[ul_index].status.val = 0;
+ }
+ /* Set the WRAP bit in the last descriptor. */
+ gs_rx_desc[GMAC_RX_BUFFERS - 1].addr.bm.b_wrap = 1;
+
+ /* Set receive buffer queue */
+ gmac_set_rx_queue(p_hw, (uint32_t)gs_rx_desc);
+}
+
+
+/**
+ * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.
+ * Must be invoked after gmac_dev_init() but before RX/TX starts.
+ *
+ * \note If input address is not 8-byte aligned, the address is automatically
+ * adjusted and the list size is reduced by one.
+ *
+ * \param p_gmac Pointer to GMAC instance.
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ * \param p_dev_mm Pointer to the GMAC memory management control block.
+ *
+ * \return GMAC_OK or GMAC_PARAM.
+ */
+static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev)
+{
+ /* Assign TX buffers */
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ if ((((uint32_t) gs_uc_tx_buffer) & 0x7)
+ || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
+ p_dev_mm->ul_tx_size--;
+ }
+ p_gmac_dev->p_tx_buffer =
+ (uint8_t *) (((uint32_t) gs_uc_tx_buffer) & 0xFFFFFFF8);
+#endif
+
+ /* Reset TX & RX Memory */
+ gmac_reset_rx_mem(p_gmac_dev);
+ gmac_reset_tx_mem(p_gmac_dev);
+
+ /* Enable Rx and Tx, plus the statistics register */
+ gmac_enable_transmit(p_gmac, true);
+ gmac_enable_receive(p_gmac, true);
+ gmac_enable_statistics_write(p_gmac, true);
+
+ /* Set up the interrupts for transmission and errors */
+ gmac_enable_interrupt(p_gmac,
+ GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */
+ GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
+ GMAC_IER_ROVR | /* Enable receive overrun interrupt. */
+ GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
+ GMAC_IER_TUR | /* Enable transmit underrun interrupt. */
+ GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */
+ GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
+ GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */
+ GMAC_IER_PTZ | /* Enable pause time zero interrupt. */
+ GMAC_IER_RCOMP); /* Enable receive complete interrupt. */
+
+ return GMAC_OK;
+}
+
+/**
+ * \brief Initialize the GMAC driver.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_opt GMAC configure options.
+ */
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
+ gmac_options_t* p_opt)
+{
+ /* Disable TX & RX and more */
+ gmac_network_control(p_gmac, 0);
+ gmac_disable_interrupt(p_gmac, ~0u);
+
+ gmac_clear_statistics(p_gmac);
+
+ /* Clear all status bits in the receive status register. */
+ gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA
+ | GMAC_RSR_HNO);
+
+#ifndef GMAC_TSR_UND
+ /* GMAC_TSR_UND is only defined by SAM4E. */
+ #define GMAC_TSR_UND 0ul
+#endif
+ /* Clear all status bits in the transmit status register */
+ gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
+ | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);
+
+ /* Clear interrupts */
+ gmac_get_interrupt_status(p_gmac);
+#if !defined(ETHERNET_CONF_DATA_OFFSET)
+ /* Receive Buffer Offset
+ * Indicates the number of bytes by which the received data
+ * is offset from the start of the receive buffer
+ * which can be handy for alignment reasons */
+ /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */
+ #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0
+#endif
+ /* Enable the copy of data into the buffers
+ ignore broadcasts, and not copy FCS. */
+
+ gmac_set_config(p_gmac,
+ ( gmac_get_config(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |
+ GMAC_NCFGR_RFCS | /* Remove FCS, frame check sequence (last 4 bytes) */
+ GMAC_NCFGR_PEN | /* Pause Enable */
+ GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) | /* Set Ethernet Offset */
+ GMAC_RXD_RXCOEN ); /* RXCOEN related function */
+
+ /*
+ * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
+ * Note: SAM4E/SAME70 do have RX checksum offloading
+ * but TX checksum offloading has NOT been implemented,
+ * at least on a SAM4E.
+ * http://community.atmel.com/forum/sam4e-gmac-transmit-checksum-offload-enablesolved
+ */
+
+ {
+ uint32_t ulValue = gmac_get_dma(p_gmac);
+
+ /* Let the GMAC set TX checksum's. */
+ ulValue |= GMAC_DCFGR_TXCOEN;
+ #if( SAME70 != 0 )
+ {
+ /* Transmitter Packet Buffer Memory Size Select:
+ Use full configured addressable space (4 Kbytes). */
+ ulValue |= GMAC_DCFGR_TXPBMS;
+ }
+ #endif
+
+ /* Clear the DMA Receive Buffer Size (DRBS) field: */
+ ulValue &= ~( GMAC_DCFGR_DRBS_Msk );
+ /* And set it: */
+ ulValue |= ( GMAC_RX_UNITSIZE / 64 ) << GMAC_DCFGR_DRBS_Pos;
+
+ gmac_set_dma(p_gmac, ulValue);
+ }
+
+ /* Enable/Disable Copy(Receive) All Valid Frames. */
+ gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
+
+ /* Disable/Enable broadcast receiving */
+ gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);
+
+
+ /* Initialize memory */
+ gmac_init_mem(p_gmac, p_gmac_dev);
+
+ /* Set Mac Address */
+ gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);
+}
+
+/**
+ * \brief Frames can be read from the GMAC in multiple sections.
+ *
+ * Returns > 0 if a complete frame is available
+ * It also it cleans up incomplete older frames
+ */
+
+static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)
+{
+ uint32_t ulReturn = 0;
+ int32_t ulIndex = p_gmac_dev->ul_rx_idx;
+ gmac_rx_descriptor_t *pxHead = &gs_rx_desc[ulIndex];
+
+// #warning Just for debugging
+// if((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0)
+// {
+// NVIC_DisableIRQ( GMAC_IRQn );
+// }
+
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+ /* Discard any incomplete frames */
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&
+ (pxHead->status.val & GMAC_RXD_SOF) == 0)
+ {
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ #if( GMAC_STATS != 0 )
+ {
+ gmacStats.incompCount++;
+ }
+ #endif
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER == 0 */
+
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0)
+ {
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+ if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {
+ /* Here a complete frame has been seen with SOF and EOF */
+ ulReturn = pxHead->status.bm.b_len;
+ break;
+ }
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {
+ /* CPU is not the owner (yet) */
+ break;
+ }
+ if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {
+ /* Strange, we found a new Start Of Frame
+ * discard previous segments */
+ int32_t ulPrev = p_gmac_dev->ul_rx_idx;
+ pxHead = &gs_rx_desc[ulPrev];
+ do {
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&ulPrev, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulPrev];
+ #if( GMAC_STATS != 0 )
+ {
+ gmacStats.truncCount++;
+ }
+ #endif
+ } while (ulPrev != ulIndex);
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ }
+ }
+ #else /* ipconfigZERO_COPY_RX_DRIVER */
+ {
+ if ((pxHead->status.val & (GMAC_RXD_SOF|GMAC_RXD_EOF)) == (GMAC_RXD_SOF|GMAC_RXD_EOF)) {
+ /* Here a complete frame in a single segment. */
+ ulReturn = pxHead->status.bm.b_len;
+ break;
+ }
+ /* Return the buffer to DMA. */
+ pxHead->addr.bm.b_ownership = 0;
+
+ /* Let ulIndex/pxHead point to the next buffer. */
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ /* And remember this index. */
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+ }
+ return ulReturn;
+}
+
+/**
+ * \brief Frames can be read from the GMAC in multiple sections.
+ * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.
+ * p_rcv_size is the size of the entire frame. Generally gmac_read
+ * will be repeatedly called until the sum of all the ul_frame_size equals
+ * the value of p_rcv_size.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_frame Address of the frame buffer.
+ * \param ul_frame_size Length of the frame.
+ * \param p_rcv_size Received frame size.
+ *
+ * \return GMAC_OK if receiving frame successfully, otherwise failed.
+ */
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
+ uint32_t ul_frame_size, uint32_t* p_rcv_size,
+ uint8_t** pp_recv_frame)
+{
+ int32_t nextIdx; /* A copy of the Rx-index 'ul_rx_idx' */
+ int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);
+ gmac_rx_descriptor_t *pxHead;
+
+ if (bytesLeft == 0 )
+ {
+ return GMAC_RX_NO_DATA;
+ }
+
+ /* gmac_dev_poll has confirmed that there is a complete frame at
+ * the current position 'ul_rx_idx'
+ */
+ nextIdx = p_gmac_dev->ul_rx_idx;
+
+ /* Read +2 bytes because buffers are aligned at -2 bytes */
+ bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );
+
+#if( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
+ SCB_InvalidateDCache();
+#endif
+
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+
+ /* The frame will be copied in 1 or 2 memcpy's */
+ if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )
+ {
+ const uint8_t *source;
+ int32_t left;
+ int32_t toCopy;
+
+ source = gs_uc_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
+ left = bytesLeft;
+ toCopy = ( GMAC_RX_BUFFERS - nextIdx ) * GMAC_RX_UNITSIZE;
+ if(toCopy > left )
+ {
+ toCopy = left;
+ }
+ memcpy (p_frame, source, toCopy);
+ left -= toCopy;
+
+ if( left != 0ul )
+ {
+ memcpy (p_frame + toCopy, (void*)gs_uc_rx_buffer, left);
+ }
+ }
+ }
+ #else /* ipconfigZERO_COPY_RX_DRIVER */
+ {
+ if( p_frame != NULL )
+ {
+ /* Return a pointer to the earlier DMA buffer. */
+ *( pp_recv_frame ) = ( uint8_t * )
+ ( ( ( gs_rx_desc[nextIdx].addr.val ) & ~( 0x03ul ) ) + 2 );
+ /* Set the new DMA-buffer. */
+ gs_rx_desc[nextIdx].addr.bm.addr_dw = ( ( uint32_t )p_frame ) / 4;
+ }
+ else
+ {
+ /* The driver couldn't not allocate a buffer to receive a packet.
+ Leave the current DMA buffer in place. */
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+ do
+ {
+ pxHead = &gs_rx_desc[nextIdx];
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&nextIdx, GMAC_RX_BUFFERS);
+ } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);
+
+ p_gmac_dev->ul_rx_idx = nextIdx;
+
+ *p_rcv_size = bytesLeft;
+
+// #warning Just for debugging
+// NVIC_EnableIRQ( GMAC_IRQn );
+
+ return GMAC_OK;
+}
+
+extern void vGMACGenerateChecksum( uint8_t *apBuffer, size_t uxLength );
+
+/**
+ * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
+ * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.
+ * If lEndOfFrame is true then the data being copied is the end of the frame
+ * and the frame can be transmitted.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_buffer Pointer to the data buffer.
+ * \param ul_size Length of the frame.
+ *
+ * \return Length sent.
+ */
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
+ uint32_t ul_size)
+{
+ volatile gmac_tx_descriptor_t *p_tx_td;
+
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+
+ /* Check parameter */
+ if (ul_size > GMAC_TX_UNITSIZE) {
+ return GMAC_PARAM;
+ }
+
+ /* Pointers to the current transmit descriptor */
+ p_tx_td = &gs_tx_desc[p_gmac_dev->l_tx_head];
+
+ /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
+ {
+ return GMAC_TX_BUSY;
+ }
+
+ /* Set up/copy data to transmission buffer */
+ if (p_buffer && ul_size) {
+ /* Driver manages the ring buffer */
+ /* Calculating the checksum here is faster than calculating it from the GMAC buffer
+ * because withing p_buffer, it is well aligned */
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Zero-copy... */
+ p_tx_td->addr = ( uint32_t ) p_buffer;
+ }
+ #else
+ {
+ /* Or memcopy... */
+ memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size );
+ }
+
+ //#warning Trying out
+ gmac_start_transmission(p_hw);
+
+ /* Update transmit descriptor status */
+
+ /* The buffer size defined is the length of ethernet frame,
+ so it's always the last buffer of the frame. */
+ if( p_gmac_dev->l_tx_head == ( int32_t )( GMAC_TX_BUFFERS - 1 ) )
+ {
+ /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked
+ GMAC_TXD_USED will now be cleared. */
+ p_tx_td->status.val =
+ ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
+ } else {
+ /* GMAC_TXD_USED will now be cleared. */
+ p_tx_td->status.val =
+ ul_size | GMAC_TXD_LAST;
+ }
+
+ circ_inc32( &p_gmac_dev->l_tx_head, GMAC_TX_BUFFERS );
+
+ /* Now start to transmit if it is still not done */
+ gmac_start_transmission(p_hw);
+
+ return GMAC_OK;
+}
+
+/**
+ * \brief Get current load of transmit.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ *
+ * \return Current load of transmit.
+ */
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)
+{
+ uint16_t us_head = p_gmac_dev->l_tx_head;
+ uint16_t us_tail = p_gmac_dev->l_tx_tail;
+ return CIRC_CNT(us_head, us_tail, GMAC_TX_BUFFERS);
+}
+
+/**
+ * \brief Register/Clear TX wakeup callback.
+ *
+ * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application
+ * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and
+ * enters suspend state. The callback is in charge to resume the task once
+ * several transmit descriptors have been released. The next time gmac_dev_write() will be called,
+ * it shall be successful.
+ *
+ * This function is usually invoked with NULL callback from the TX wakeup
+ * callback itself, to unregister. Once the callback has resumed the
+ * application task, there is no need to invoke the callback again.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ * \param func_wakeup Pointer to wakeup callback function.
+ * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.
+ *
+ * \return GMAC_OK, GMAC_PARAM on parameter error.
+ */
+#if( GMAC_USES_WAKEUP_CALLBACK )
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)
+{
+ if (func_wakeup_cb == NULL) {
+ p_gmac_dev->func_wakeup_cb = NULL;
+ } else {
+ if (uc_threshold <= GMAC_TX_BUFFERS) {
+ p_gmac_dev->func_wakeup_cb = func_wakeup_cb;
+ p_gmac_dev->ul_wakeup_threshold = ( uint32_t )uc_threshold;
+ } else {
+ return GMAC_PARAM;
+ }
+ }
+
+ return GMAC_OK;
+}
+#endif /* GMAC_USES_WAKEUP_CALLBACK */
+
+/**
+ * \brief Reset TX & RX queue & statistics.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ */
+void gmac_dev_reset(gmac_device_t* p_gmac_dev)
+{
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+ gmac_reset_rx_mem(p_gmac_dev);
+ gmac_reset_tx_mem(p_gmac_dev);
+ gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN
+ | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
+}
+
+void gmac_dev_halt(Gmac* p_gmac);
+
+void gmac_dev_halt(Gmac* p_gmac)
+{
+ gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
+ gmac_disable_interrupt(p_gmac, ~0u);
+}
+
+
+/**
+ * \brief GMAC Interrupt handler.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ */
+
+#if( GMAC_STATS != 0 )
+ extern int logPrintf( const char *pcFormat, ... );
+
+ void gmac_show_irq_counts ()
+ {
+ int index;
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
+ if (gmacStats.intStatus[intPairs[index].index]) {
+ logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);
+ }
+ }
+ }
+#endif
+
+void gmac_handler(gmac_device_t* p_gmac_dev)
+{
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+ gmac_tx_descriptor_t *p_tx_td;
+ uint32_t ul_tx_status_flag;
+#if( GMAC_STATS != 0 )
+ int index;
+#endif
+
+ uint32_t ul_isr = gmac_get_interrupt_status(p_hw);
+ uint32_t ul_rsr = gmac_get_rx_status(p_hw);
+ uint32_t ul_tsr = gmac_get_tx_status(p_hw);
+
+ #if( GMAC_STATS != 0 )
+ {
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
+ if (ul_isr & intPairs[index].mask)
+ gmacStats.intStatus[intPairs[index].index]++;
+ }
+ }
+ #endif /* GMAC_STATS != 0 */
+
+ /* RX packet */
+ if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {
+ /* Clear status */
+ gmac_clear_rx_status(p_hw, ul_rsr);
+
+ if (ul_isr & GMAC_ISR_RCOMP)
+ ul_rsr |= GMAC_RSR_REC;
+ /* Invoke callbacks which can be useful to wake op a task */
+ xRxCallback( ul_rsr );
+ }
+
+ /* TX packet */
+ if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {
+
+ ul_tx_status_flag = GMAC_TSR_TXCOMP;
+ /* A frame transmitted */
+
+ /* Check RLE */
+ if (ul_tsr & GMAC_TSR_RLE) {
+ /* Status RLE & Number of discarded buffers */
+ ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,
+ p_gmac_dev->l_tx_tail, GMAC_TX_BUFFERS);
+ gmac_reset_tx_mem(p_gmac_dev);
+ gmac_enable_transmit(p_hw, 1);
+ }
+ /* Clear status */
+ gmac_clear_tx_status(p_hw, ul_tsr);
+
+ if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {
+ /* Check the buffers */
+ do {
+ p_tx_td = &gs_tx_desc[p_gmac_dev->l_tx_tail];
+ /* Any error? Exit if buffer has not been sent yet */
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
+ break;
+ }
+
+ /* Notify upper layer that a packet has been sent */
+ xTxCallback(ul_tx_status_flag, (void*)p_tx_td->addr); // Function call prvTxCallback
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ p_tx_td->addr = 0ul;
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+ circ_inc32(&p_gmac_dev->l_tx_tail, GMAC_TX_BUFFERS);
+ } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
+ GMAC_TX_BUFFERS));
+ }
+
+ if (ul_tsr & GMAC_TSR_RLE) {
+ /* Notify upper layer RLE */
+ xTxCallback(ul_tx_status_flag, NULL);
+ }
+
+#if( GMAC_USES_WAKEUP_CALLBACK )
+ /* If a wakeup has been scheduled, notify upper layer that it can
+ send other packets, and the sending will be successful. */
+ if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
+ GMAC_TX_BUFFERS) >= p_gmac_dev->ul_wakeup_threshold)
+ && p_gmac_dev->func_wakeup_cb) {
+ p_gmac_dev->func_wakeup_cb();
+ }
+#endif
+ }
+}
+
+//@}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h
new file mode 100644
index 000000000..1965889b1
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h
@@ -0,0 +1,1418 @@
+ /**
+ * \file
+ *
+ * \brief GMAC (Ethernet MAC) driver for SAM.
+ *
+ * Copyright (c) 2013-2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef GMAC_H_INCLUDED
+#define GMAC_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** The buffer addresses written into the descriptors must be aligned, so the
+ last few bits are zero. These bits have special meaning for the GMAC
+ peripheral and cannot be used as part of the address. */
+#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC
+#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */
+#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */
+
+#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */
+#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */
+#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */
+#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */
+#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */
+#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */
+#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */
+#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */
+#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */
+#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */
+#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
+#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */
+#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */
+#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */
+#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */
+#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */
+#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */
+
+#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */
+#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */
+#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */
+#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */
+#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */
+#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */
+#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */
+#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */
+#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */
+#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */
+
+/** The MAC can support frame lengths up to 1536 bytes */
+#define GMAC_FRAME_LENTGH_MAX 1536
+
+//#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */
+#define GMAC_RX_UNITSIZE 1536 /**< Fixed size for RX buffer */
+
+//#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */
+#define GMAC_TX_UNITSIZE 1536 /**< Size for ETH frame length */
+
+/** GMAC clock speed */
+#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)
+#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)
+#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)
+#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)
+#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)
+#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)
+
+/** GMAC maintain code default value*/
+#define GMAC_MAN_CODE_VALUE (10)
+
+/** GMAC maintain start of frame default value*/
+#define GMAC_MAN_SOF_VALUE (1)
+
+/** GMAC maintain read/write*/
+#define GMAC_MAN_RW_TYPE (2)
+
+/** GMAC maintain read only*/
+#define GMAC_MAN_READ_ONLY (1)
+
+/** GMAC address length */
+#define GMAC_ADDR_LENGTH (6)
+
+
+#define GMAC_DUPLEX_HALF 0
+#define GMAC_DUPLEX_FULL 1
+
+#define GMAC_SPEED_10M 0
+#define GMAC_SPEED_100M 1
+
+/**
+ * \brief Return codes for GMAC APIs.
+ */
+typedef enum {
+ GMAC_OK = 0, /** 0 Operation OK */
+ GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */
+ GMAC_TX_BUSY, /** 2 TX in progress */
+ GMAC_RX_NO_DATA, /** 3 No data received */
+ GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */
+ GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */
+ GMAC_RX_ERROR, /** 6 RX error */
+ GMAC_INVALID = 0xFF, /* Invalid */
+} gmac_status_t;
+
+/**
+ * \brief Media Independent Interface (MII) type.
+ */
+typedef enum {
+ GMAC_PHY_MII = 0, /** MII mode */
+ GMAC_PHY_RMII = 1, /** Reduced MII mode */
+ GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/
+} gmac_mii_mode_t;
+
+/* This is the list of GMAC priority queue */
+typedef enum {
+ GMAC_QUE_0 = 0,
+#if !(SAM4E)
+ GMAC_QUE_1 = 1,
+ GMAC_QUE_2 = 2,
+ /* Only SAM E70 Rev-B. */
+ GMAC_QUE_3 = 3,
+ GMAC_QUE_4 = 4,
+ GMAC_QUE_5 = 5,
+#endif
+# if !defined(__DOXYGEN__)
+ GMAC_QUE_N,
+# endif
+
+}gmac_quelist_t;
+
+/** Receive buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_rx_descriptor {
+ union gmac_rx_addr {
+ uint32_t val;
+ struct gmac_rx_addr_bm {
+ uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */
+ b_wrap:1, /**< Marks last descriptor in receive buffer */
+ addr_dw:30; /**< Address in number of DW */
+ } bm;
+ } addr; /**< Address, Wrap & Ownership */
+ union gmac_rx_status {
+ uint32_t val;
+ struct gmac_rx_status_bm {
+ uint32_t b_len:13, /** 0..12 Length of frame including FCS */
+ b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */
+ b_sof:1, /** 14 Start of frame */
+ b_eof:1, /** 15 End of frame */
+ b_cfi:1, /** 16 Concatenation Format Indicator */
+ b_vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */
+ b_priority_detected:1, /** 20 Priority tag detected */
+ b_vlan_detected:1, /** 21 VLAN tag detected */
+ b_type_id_match:2, /** 22..23 Type ID match */
+ b_checksumoffload:1, /** 24 Checksum offload specific function */
+ b_addrmatch:2, /** 25..26 Address register match */
+ b_ext_addr_match:1, /** 27 External address match found */
+ reserved:1, /** 28 */
+ b_uni_hash_match:1, /** 29 Unicast hash match */
+ b_multi_hash_match:1, /** 30 Multicast hash match */
+ b_boardcast_detect:1; /** 31 Global broadcast address detected */
+ } bm;
+ } status;
+} gmac_rx_descriptor_t;
+
+/** Transmit buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_tx_descriptor {
+ uint32_t addr;
+ union gmac_tx_status {
+ uint32_t val;
+ struct gmac_tx_status_bm {
+ uint32_t b_len:14, /** 0..13 Length of buffer */
+ reserved:1, /** 14 */
+ b_last_buffer:1, /** 15 Last buffer (in the current frame) */
+ b_no_crc:1, /** 16 No CRC */
+ reserved1:3, /** 17..19 */
+ b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */
+ reserved2:3, /** 23..25 */
+ b_lco:1, /** 26 Late collision, transmit error detected */
+ b_exhausted:1, /** 27 Buffer exhausted in mid frame */
+ b_underrun:1, /** 28 Transmit underrun */
+ b_error:1, /** 29 Retry limit exceeded, error detected */
+ b_wrap:1, /** 30 Marks last descriptor in TD list */
+ b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */
+ } bm;
+ } status;
+} gmac_tx_descriptor_t;
+
+COMPILER_PACK_RESET()
+
+/**
+ * \brief Input parameters when initializing the gmac module mode.
+ */
+typedef struct gmac_options {
+ /* Enable/Disable CopyAllFrame */
+ uint8_t uc_copy_all_frame;
+ /* Enable/Disable NoBroadCast */
+ uint8_t uc_no_boardcast;
+ /* MAC address */
+ uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];
+} gmac_options_t;
+
+/** Wakeup callback */
+typedef void (*gmac_dev_wakeup_cb_t) (void);
+
+/**
+ * GMAC driver structure.
+ */
+typedef struct gmac_device {
+
+ /** Pointer to HW register base */
+ Gmac *p_hw;
+ /**
+ * Pointer to allocated TX buffer.
+ * Section 3.6 of AMBA 2.0 spec states that burst should not cross
+ * 1K Boundaries.
+ * Receive buffer manager writes are burst of 2 words => 3 lsb bits
+ * of the address shall be set to 0.
+ */
+#if( GMAC_USES_WAKEUP_CALLBACK != 0 )
+ /** Optional callback to be invoked once several TDs have been released */
+ gmac_dev_wakeup_cb_t func_wakeup_cb;
+#endif
+ /** RX index for current processing TD */
+ uint32_t ul_rx_idx;
+ /** Circular buffer head pointer by upper layer (buffer to be sent) */
+ int32_t l_tx_head;
+ /** Circular buffer tail pointer incremented by handlers (buffer sent) */
+ int32_t l_tx_tail;
+
+ /** Number of free TD before wakeup callback is invoked */
+ uint32_t ul_wakeup_threshold;
+} gmac_device_t;
+
+uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry);
+
+/**
+ * \brief Write network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_ncr Network control value.
+ */
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)
+{
+ p_gmac->GMAC_NCR = ul_ncr;
+}
+
+/**
+ * \brief Get network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCR;
+}
+
+/**
+ * \brief Enable/Disable GMAC receive.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC transmit.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC transmit, else to enable it.
+ */
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC management.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC management, else to enable it.
+ */
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_MPE;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+}
+
+/**
+ * \brief Clear all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_clear_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
+}
+
+/**
+ * \brief Increase all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_increase_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
+}
+
+/**
+ * \brief Enable/Disable statistics registers writing.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the statistics registers writing, else to enable it.
+ */
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,
+ uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
+ }
+}
+
+/**
+ * \brief In half-duplex mode, forces collisions on all received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the back pressure, else to enable it.
+ */
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_BP;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;
+ }
+}
+
+/**
+ * \brief Start transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_start_transmission(Gmac* p_gmac)
+{
+ __DSB();
+ p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
+}
+
+/**
+ * \brief Halt transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_halt_transmission(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_THALT;
+}
+
+/**
+ * \brief Transmit pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;
+}
+
+/**
+ * \brief Transmit zero quantum pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;
+}
+
+/**
+ * \brief Store receivetime stamp to memory.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to normal operation, else to enable the store.
+ */
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;
+ }
+}
+
+/**
+ * \brief Enable PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to set the reception, 0 to disable.
+ */
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;
+ }
+}
+
+/**
+ * \brief Transmit PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;
+}
+
+/**
+ * \brief Flush next packet.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_flush_next_packet(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_FNP;
+}
+
+/**
+ * \brief Set up network configuration register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_cfg Network configuration value.
+ */
+static inline void gmac_set_config(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_NCFGR = ul_cfg;
+}
+
+/* Get and set DMA Configuration Register */
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_DCFGR = ul_cfg;
+}
+
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_DCFGR;
+}
+
+/**
+ * \brief Get network configuration.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network configuration.
+ */
+static inline uint32_t gmac_get_config(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCFGR;
+}
+
+/**
+ * \brief Set speed.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
+ */
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)
+{
+ if (uc_speed) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Full-Duplex mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.
+ */
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable copying all valid frames, else to enable it.
+ */
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
+ }
+}
+
+/**
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the jumbo frames, else to enable it.
+ */
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;
+ }
+}
+
+/**
+ * \brief Disable/Enable broadcast receiving.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to disable the broadcast, else to enable it.
+ */
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;
+ }
+}
+
+/**
+ * \brief Enable/Disable multicast hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the multicast hash, else to enable it.
+ */
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable big frames (over 1518, up to 1536).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable big frames else to enable it.
+ */
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;
+ }
+}
+
+/**
+ * \brief Set MDC clock divider.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_mck GMAC MCK.
+ *
+ * \return GMAC_OK if successfully.
+ */
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
+{
+ uint32_t ul_clk, ul_value;
+
+ if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
+ return GMAC_INVALID;
+ } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_96;
+ } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_64;
+ } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_48;
+ } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_32;
+ } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_16;
+ } else {
+ ul_clk = GMAC_NCFGR_CLK_MCK_8;
+ }
+ ul_value = p_gmac->GMAC_NCFGR;
+ ul_value &= ~GMAC_NCFGR_CLK_Msk;
+ ul_value |= ul_clk;
+ p_gmac->GMAC_NCFGR = ul_value;
+ return GMAC_OK;
+}
+
+/**
+ * \brief Enable/Disable retry test.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;
+ }
+}
+
+/**
+ * \brief Enable/Disable pause (when a valid pause frame is received).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable pause frame, else to enable it.
+ */
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;
+ }
+}
+
+/**
+ * \brief Set receive buffer offset to 0 ~ 3.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)
+{
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);
+}
+
+/**
+ * \brief Enable/Disable receive length field checking.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable receive length field checking, else to enable it.
+ */
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;
+ }
+}
+
+/**
+ * \brief Enable/Disable discarding FCS field of received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.
+ */
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;
+ }
+}
+
+
+/**
+ * \brief Enable/Disable frames to be received in half-duplex mode
+ * while transmitting.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.
+ */
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;
+ }
+}
+
+/**
+ * \brief Enable/Disable ignore RX FCS.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable ignore RX FCS, else to enable it.
+ */
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;
+ }
+}
+
+/**
+ * \brief Get Network Status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network status.
+ */
+static inline uint32_t gmac_get_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NSR;
+}
+
+/**
+ * \brief Get MDIO IN pin status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return MDIO IN pin status.
+ */
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);
+}
+
+/**
+ * \brief Check if PHY is idle.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return 1 if PHY is idle.
+ */
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
+}
+
+/**
+ * \brief Return transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Transmit status.
+ */
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TSR;
+}
+
+/**
+ * \brief Clear transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Transmit status.
+ */
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_TSR = ul_status;
+}
+
+/**
+ * \brief Return receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RSR;
+}
+
+/**
+ * \brief Clear receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Receive status.
+ */
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_RSR = ul_status;
+}
+
+/**
+ * \brief Set Rx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Rx queue address.
+ */
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Set Rx buffer size.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Rx buffer.
+ */
+static inline void gmac_set_rx_bufsize(Gmac* p_gmac, uint32_t ul_code)
+{
+ p_gmac->GMAC_DCFGR = (p_gmac->GMAC_DCFGR & ~GMAC_DCFGR_DRBS_Msk)
+ | GMAC_DCFGR_DRBS(ul_code);
+}
+
+/**
+ * \brief Get Rx Queue Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RBQB;
+}
+
+/**
+ * \brief Set Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Tx queue address.
+ */
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TBQB;
+}
+
+/**
+ * \brief Enable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be enabled.
+ */
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IER = ul_source;
+}
+
+/**
+ * \brief Disable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be disabled.
+ */
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IDR = ul_source;
+}
+
+/**
+ * \brief Return interrupt status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt status.
+ */
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_ISR;
+}
+
+/**
+ * \brief Return interrupt mask.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt mask.
+ */
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_IMR;
+}
+
+/**
+ * \brief Execute PHY maintenance command.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_phy_addr PHY address.
+ * \param uc_reg_addr Register address.
+ * \param uc_rw 1 to Read, 0 to write.
+ * \param us_data Data to be performed, write only.
+ */
+static inline void gmac_maintain_phy(Gmac* p_gmac,
+ uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
+ uint16_t us_data)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(uc_phy_addr)
+ | GMAC_MAN_REGA(uc_reg_addr)
+ | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))
+ | GMAC_MAN_DATA(us_data);
+}
+
+/**
+ * \brief Get PHY maintenance data returned.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Get PHY data.
+ */
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Return data */
+ return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
+}
+
+/**
+ * \brief Set Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_hash_top Hash top.
+ * \param ul_hash_bottom Hash bottom.
+ */
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,
+ uint32_t ul_hash_bottom)
+{
+ p_gmac->GMAC_HRB = ul_hash_bottom;
+ p_gmac->GMAC_HRT = ul_hash_top;
+}
+
+/**
+ * \brief Set 64 bits Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ull_hash 64 bits hash value.
+ */
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)
+{
+ p_gmac->GMAC_HRB = (uint32_t) ull_hash;
+ p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);
+}
+
+/**
+ * \brief Set MAC Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param p_mac_addr GMAC address.
+ */
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,
+ const uint8_t* p_mac_addr)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)
+ | (p_mac_addr[2] << 16)
+ | (p_mac_addr[1] << 8)
+ | (p_mac_addr[0]);
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)
+ | (p_mac_addr[4]);
+}
+
+/**
+ * \brief Set MAC Address via 2 dword.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ul_mac_top GMAC top address.
+ * \param ul_mac_bottom GMAC bottom address.
+ */
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,
+ uint32_t ul_mac_top, uint32_t ul_mac_bottom)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;
+}
+
+/**
+ * \brief Set MAC Address via int64.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ull_mac 64-bit GMAC address.
+ */
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,
+ uint64_t ull_mac)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);
+}
+
+/**
+ * \brief Select media independent interface mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param mode Media independent interface mode.
+ */
+#if (SAM4E)
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
+{
+ switch (mode) {
+ case GMAC_PHY_MII:
+ case GMAC_PHY_RMII:
+ p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;
+ break;
+
+ default:
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
+ break;
+ }
+}
+#else
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
+{
+ switch (mode) {
+ case GMAC_PHY_MII:
+ p_gmac->GMAC_UR |= GMAC_UR_RMII;
+ break;
+
+ case GMAC_PHY_RMII:
+ default:
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMII;
+ break;
+ }
+}
+#endif
+
+#if !(SAM4E)
+/**
+ * \brief Set 1588 timer comparison.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param seconds47 Second comparison high
+ * \param seconds31 Second comparison low
+ * \param nanosec Nanosecond Comparison
+ */
+static inline void gmac_set_tsu_compare(Gmac *p_gmac, uint32_t seconds47, uint32_t seconds31, uint32_t nanosec)
+{
+ p_gmac->GMAC_SCH = seconds47;
+ p_gmac->GMAC_SCL = seconds31;
+ p_gmac->GMAC_NSC = nanosec;
+}
+
+/**
+ * \brief Get interrupt status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Interrupt status.
+ */
+static inline uint32_t gmac_get_priority_interrupt_status(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_ISRPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set base address of TX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_tx_priority_queue(Gmac* p_gmac, uint32_t ul_addr, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_TBQBAPQ[queue_idx - 1] = GMAC_TBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get base address of TX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Base address.
+ */
+static inline uint32_t gmac_get_tx_priority_queue(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_TBQBAPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set base address of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_rx_priority_queue(Gmac* p_gmac, uint32_t ul_addr, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_RBQBAPQ[queue_idx - 1] = GMAC_RBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get base address of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Base address.
+ */
+static inline uint32_t gmac_get_rx_priority_queue(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_RBQBAPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set size of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_rx_priority_bufsize(Gmac* p_gmac, uint32_t ul_size, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_RBSRPQ[queue_idx - 1] = ul_size;
+}
+
+/**
+ * \brief Enable or disable credit-based shaping on the second highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable, 1 to enable it
+ */
+static inline void gmac_enable_cbsque_a(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_CBSCR |= GMAC_CBSCR_QAE;
+ } else {
+ p_gmac->GMAC_CBSCR &= ~GMAC_CBSCR_QAE;
+ }
+}
+
+/**
+ * \brief Enable or disable credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable, 1 to enable it
+ */
+static inline void gmac_enable_cbsque_b(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_CBSCR |= GMAC_CBSCR_QBE;
+ } else {
+ p_gmac->GMAC_CBSCR &= ~GMAC_CBSCR_QBE;
+ }
+}
+
+/**
+ * \brief Set credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param idleslope_a Value for queue A in bytes/second
+ */
+static inline void gmac_config_idleslope_a(Gmac* p_gmac, uint32_t idleslope_a)
+{
+ p_gmac->GMAC_CBSISQA = idleslope_a;
+}
+
+/**
+ * \brief Set credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param idleslope_b Value for queue B in bytes/second
+ */
+static inline void gmac_config_idleslope_b(Gmac* p_gmac, uint32_t idleslope_b)
+{
+ p_gmac->GMAC_CBSISQB = idleslope_b;
+}
+
+/**
+ * \brief Set screening type 1 register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param reg_val Value for screening type 1
+ * \param index Index of register
+ */
+static inline void gmac_write_screener_reg_1(Gmac* p_gmac, uint32_t reg_val, uint32_t index)
+{
+ p_gmac->GMAC_ST1RPQ[index] = reg_val;
+}
+
+/**
+ * \brief Set screening type 2 register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param reg_val Value for screening type 2
+ * \param index Index of register
+ */
+static inline void gmac_write_screener_reg_2 (Gmac* p_gmac, uint32_t reg_val, uint32_t index)
+{
+ p_gmac->GMAC_ST2RPQ[index] = reg_val;
+}
+
+/**
+ * \brief Enable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be enabled.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_enable_priority_interrupt(Gmac* p_gmac, uint32_t ul_source, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_IERPQ[queue_idx - 1] = ul_source;
+}
+
+/**
+ * \brief Disable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be disabled.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_disable_priority_interrupt(Gmac* p_gmac, uint32_t ul_source, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_IDRPQ[queue_idx - 1] = ul_source;
+}
+
+/**
+ * \brief Get interrupt mask.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Interrupt mask.
+ */
+static inline uint32_t gmac_get_priority_interrupt_mask(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_IMRPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set screening type 2 eherType register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ethertype Ethertype compare value
+ * \param index Index of register
+ */
+static inline void gmac_write_ethtype_reg(Gmac* p_gmac, uint16_t ethertype, uint32_t index)
+{
+ p_gmac->GMAC_ST2ER[index] = (uint32_t)ethertype;
+}
+
+/**
+ * \brief Set screening type 2 compare word register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param c0reg Compare value 0
+ * \param c1reg Compare value 1
+ * \param index Index of register
+ */
+static inline void gmac_write_screen_compare_reg(Gmac* p_gmac, uint32_t c0reg, uint16_t c1reg, uint32_t index)
+{
+ volatile uint32_t *p_PRAS;
+ uint32_t ul_dlt;
+
+ ul_dlt = (uint32_t)&(p_gmac->GMAC_ST2CW01);
+ ul_dlt = ul_dlt - (uint32_t)&(p_gmac->GMAC_ST2CW00);
+
+ p_PRAS = (volatile uint32_t *)((uint32_t)&(p_gmac->GMAC_ST2CW00) +
+ index * ul_dlt);
+ *p_PRAS = c0reg;
+ p_PRAS = (volatile uint32_t *)((uint32_t)&(p_gmac->GMAC_ST2CW10) +
+ index * ul_dlt);
+ *p_PRAS = (uint32_t)c1reg;
+}
+
+#endif /* !(SAM4E) */
+
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
+ uint32_t* p_value);
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
+ uint8_t uc_address, uint32_t ul_value);
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
+ gmac_options_t* p_opt);
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
+ uint32_t ul_frame_size, uint32_t* p_rcv_size, uint8_t** pp_recv_frame);
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
+ uint32_t ul_size);
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);
+void gmac_handler(gmac_device_t* p_gmac_dev);
+
+void gmac_reset_tx_mem(gmac_device_t* p_dev);
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+
+# define GMAC_STATS 0
+
+#if( GMAC_STATS != 0 )
+
+ /* Here below some code to study the types and
+ frequencies of GMAC interrupts. */
+ #define GMAC_IDX_RXUBR 0
+ #define GMAC_IDX_TUR 1
+ #define GMAC_IDX_RLEX 2
+ #define GMAC_IDX_TFC 3
+ #define GMAC_IDX_RCOMP 4
+ #define GMAC_IDX_TCOMP 5
+ #define GMAC_IDX_ROVR 6
+ #define GMAC_IDX_HRESP 7
+ #define GMAC_IDX_PFNZ 8
+ #define GMAC_IDX_PTZ 9
+
+ struct SGmacStats {
+ unsigned recvCount;
+ unsigned rovrCount;
+ unsigned bnaCount;
+ unsigned sendCount;
+ unsigned sovrCount;
+ unsigned incompCount;
+ unsigned truncCount;
+
+ unsigned intStatus[10];
+ };
+ extern struct SGmacStats gmacStats;
+
+ struct SIntPair {
+ const char *name;
+ unsigned mask;
+ int index;
+ };
+
+ #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME
+ static const struct SIntPair intPairs[] = {
+ { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */
+ { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */
+ { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */
+ { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */
+ { MK_PAIR( RCOMP ) }, /* Receive complete */
+ { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */
+ { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */
+ { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */
+ { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */
+ { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */
+ };
+
+ void gmac_show_irq_counts ();
+
+#endif
+
+#endif /* GMAC_H_INCLUDED */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
index e0d04e454..8bd539614 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -100,7 +100,7 @@ extern uint8_t ucMACAddress[ 6 ];
if( xStatus != ERROR )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
- configASSERT( xEMACRxEventSemaphore );
+ configASSERT( xEMACRxEventSemaphore != NULL );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
@@ -212,7 +212,7 @@ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters;
- configASSERT( xEMACRxEventSemaphore );
+ configASSERT( xEMACRxEventSemaphore != NULL );
for( ;; )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
index ac01d41af..e01602b9d 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -81,7 +81,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#ifndef iptraceEMAC_TASK_STARTING
- #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
+ #define iptraceEMAC_TASK_STARTING() do { } while( ipFALSE_BOOL )
#endif
/* Define the bits of .STATUS that indicate a reception error. */
@@ -284,7 +284,7 @@ BaseType_t xReturn = pdPASS;
if( xRxHanderTask == NULL )
{
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
- configASSERT( xReturn );
+ configASSERT( xReturn != NULL );
}
if( xTXDescriptorSemaphore == NULL )
@@ -292,7 +292,7 @@ BaseType_t xReturn = pdPASS;
/* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'
and a maximum of 'configNUM_TX_DESCRIPTORS'. */
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );
- configASSERT( xTXDescriptorSemaphore );
+ configASSERT( xTXDescriptorSemaphore != NULL );
}
/* Enable MAC interrupts. */
@@ -526,7 +526,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will
often not use a malloc() failed hook as the TCP stack will recover
from allocation failures. */
- configASSERT( xDMATxDescriptors[ x ].B1ADD );
+ configASSERT( xDMATxDescriptors[ x ].B1ADD != 0U );
}
#endif
@@ -592,7 +592,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will often
not use a malloc failed hook as the TCP stack will recover from
allocation failures. */
- configASSERT( xDMARxDescriptors[ x ].B1ADD );
+ configASSERT( xDMARxDescriptors[ x ].B1ADD != 0U );
xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );
xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;
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
index e759141cc..2149a7bdd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
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
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
index 44d19f3a9..92b1573f7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
index 84019d637..aa3a1f58e 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
@@ -4,7 +4,7 @@
*/
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -828,7 +828,7 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
#endif
) {
/* Drop this packet, not for this device. */
- FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) );
+ /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */
return pdFALSE;
}
}
@@ -1178,9 +1178,9 @@ BaseType_t xReturn;
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
static
-#if defined(STM32F7xx)
- __attribute__ ((section(".first_data")))
-#endif
+ #if defined(STM32F7xx)
+ __attribute__ ((section(".first_data")))
+ #endif
uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
index 474629e46..511b27859 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -445,6 +445,11 @@ void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_
if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
{
+ /* The received packets will be written to a C source file,
+ only if 'ipconfigUSE_DUMP_PACKETS' is defined.
+ Otherwise, there is no action. */
+ iptraceDUMP_PACKET( ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen, pdTRUE );
+
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );
}
@@ -489,6 +494,10 @@ const DWORD xMaxMSToWait = 1000;
{
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
+ /* The packets sent will be written to a C source file,
+ only if 'ipconfigUSE_DUMP_PACKETS' is defined.
+ Otherwise, there is no action. */
+ iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE );
if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
{
ulWinPCAPSendFailures++;
@@ -498,6 +507,31 @@ const DWORD xMaxMSToWait = 1000;
}
/*-----------------------------------------------------------*/
+static BaseType_t xPacketBouncedBack( const uint8_t *pucBuffer )
+{
+EthernetHeader_t *pxEtherHeader;
+BaseType_t xResult;
+
+ pxEtherHeader = ( EthernetHeader_t * ) pucBuffer;
+ if( memcmp( ucMACAddress, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
+ {
+ FreeRTOS_printf( ( "Bounced back: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pxEtherHeader->xSourceAddress.ucBytes[ 0 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 1 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 2 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 3 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 4 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 5 ] ) );
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
+}
+/*-----------------------------------------------------------*/
+
static void prvInterruptSimulatorTask( void *pvParameters )
{
struct pcap_pkthdr xHeader;
@@ -545,7 +579,14 @@ eFrameProcessingResult_t eResult;
is ok to call the task level function here, but note that
some buffer implementations cannot be called from a real
interrupt. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+ if( xPacketBouncedBack( pucPacketData ) == pdFALSE )
+ {
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+ }
+ else
+ {
+ pxNetworkBuffer = NULL;
+ }
if( pxNetworkBuffer != NULL )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
index 4a6af81f9..dab007ba8 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
@@ -238,7 +238,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer,
}
}
#endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
- if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL )
+ if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0UL )
{
iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
index 10a72b464..a1185c104 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
@@ -10,6 +10,11 @@ Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
+The file uncached_memory.c can also be found in:
+
+ vendors\xilinx\boards\microzed\aws_demos\application_code\xilinx_code
+ vendors\xilinx\boards\microzed\aws_tests\application_code\xilinx_code
+
And include the following source files from the Xilinx library:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
index aa0a646b4..251640d7e 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
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
@@ -41,23 +41,23 @@ considers need processing. */
BaseType_t xNetworkInterfaceInitialise( void )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
- /* FIX ME. */
+ /* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
} \ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
index 544e5ba09..4df3ac370 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -351,7 +351,7 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
}
/* When returning non-zero, the stack will become active and
@@ -1059,7 +1059,7 @@ static void ksz8851snl_low_level_init( void )
if( ksz8851snl_init() < 0 )
{
FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );
- configASSERT(0 == 1);
+ configASSERT( ipFALSE_BOOL );
}
memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );
ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );
@@ -1166,7 +1166,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c
new file mode 100644
index 000000000..41f28a0d2
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c
@@ -0,0 +1,889 @@
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2020 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 "event_groups.h"
+#include "task.h"
+#include "semphr.h"
+
+/* ========================= FreeRTOS+TCP includes ========================== */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_IP_Private.h"
+#include "NetworkBufferManagement.h"
+#include "FreeRTOS_Stream_Buffer.h"
+
+/* ======================== Standard Library inludes ======================== */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/sysinfo.h>
+#include <signal.h>
+#include <pcap.h>
+
+/* ========================== Local includes =================================*/
+#include "utils/wait_for_event.h"
+
+/* ======================== Macro Definitions =============================== */
+#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
+#else
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) \
+ eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
+#endif
+
+/* ============================== Definitions =============================== */
+#define xSEND_BUFFER_SIZE 32768
+#define xRECV_BUFFER_SIZE 32768
+#define MAX_CAPTURE_LEN 65535
+#define IP_SIZE 100
+
+/* ================== Static Function Prototypes ============================ */
+static int prvConfigureCaptureBehaviour( void );
+static int prvCreateThreadSafeBuffers( void );
+static void * prvLinuxPcapSendThread( void *pvParam );
+static void * prvLinuxPcapRecvThread( void *pvParam );
+static void prvInterruptSimulatorTask( void *pvParameters );
+static void prvPrintAvailableNetworkInterfaces( pcap_if_t * pxAllNetworkInterfaces );
+static pcap_if_t * prvGetAvailableNetworkInterfaces( void );
+static const char * prvRemoveSpaces( char *pcBuffer,
+ int aBuflen,
+ const char *pcMessage );
+static int prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
+static int prvCreateWorkerThreads( void );
+static int prvSetDeviceModes( void );
+static void print_hex( unsigned const char * const bin_data,
+ size_t len );
+
+/* ======================== Static Global Variables ========================= */
+static StreamBuffer_t *xSendBuffer = NULL;
+static StreamBuffer_t *xRecvBuffer = NULL;
+extern uint8_t ucMACAddress[ 6 ];
+static char errbuf[ PCAP_ERRBUF_SIZE ];
+static pcap_t *pxOpenedInterfaceHandle = NULL;
+static struct event *pvSendEvent = NULL;
+static uint32_t ulPCAPSendFailures = 0;
+static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;
+static BaseType_t xInvalidInterfaceDetected = pdFALSE;
+
+/* ======================= API Function definitions ========================= */
+
+/*!
+ * @brief API call, called from reeRTOS_IP.c to initialize the capture device
+ * to be able to send and receive packets
+ * @return pdPASS if successful else pdFAIL
+ */
+BaseType_t xNetworkInterfaceInitialise( void )
+{
+BaseType_t ret = pdFAIL;
+pcap_if_t *pxAllNetworkInterfaces;
+
+ /* Query the computer the simulation is being executed on to find the
+ network interfaces it has installed. */
+ pxAllNetworkInterfaces = prvGetAvailableNetworkInterfaces();
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ prvPrintAvailableNetworkInterfaces( pxAllNetworkInterfaces );
+ ret = prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
+
+ if( ret == pdPASS )
+ {
+ ret = prvCreateThreadSafeBuffers();
+
+ if( ret == pdPASS )
+ {
+ ret = prvCreateWorkerThreads();
+ }
+ }
+
+ /* The device list is no longer required. */
+ pcap_freealldevs( pxAllNetworkInterfaces );
+ }
+
+ if( ( pxOpenedInterfaceHandle != NULL ) && ( ret == pdPASS ) )
+ {
+ ret = pdPASS;
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief API call, called from reeRTOS_IP.c to send a network packet over the
+ * selected interface
+ * @return pdTRUE if successful else pdFALSE
+ */
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
+ BaseType_t bReleaseAfterSend )
+{
+size_t xSpace;
+
+ iptraceNETWORK_INTERFACE_TRANSMIT();
+ configASSERT( xIsCallingFromIPTask() == pdTRUE );
+
+ /* Both the length of the data being sent and the actual data being sent
+ are placed in the thread safe buffer used to pass data between the FreeRTOS
+ tasks and the pthread that sends data via the pcap library. Drop
+ the packet if there is insufficient space in the buffer to hold both. */
+ xSpace = uxStreamBufferGetSpace( xSendBuffer );
+
+ if( ( pxNetworkBuffer->xDataLength <=
+ ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
+ ( xSpace >= ( pxNetworkBuffer->xDataLength +
+ sizeof( pxNetworkBuffer->xDataLength ) ) ) )
+ {
+ /* First write in the length of the data, then write in the data
+ itself. */
+ uxStreamBufferAdd( xSendBuffer,
+ 0,
+ ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ),
+ sizeof( pxNetworkBuffer->xDataLength ) );
+ uxStreamBufferAdd( xSendBuffer,
+ 0,
+ ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer,
+ pxNetworkBuffer->xDataLength );
+ }
+ else
+ {
+ FreeRTOS_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n",
+ pxNetworkBuffer->xDataLength ) );
+ }
+
+ /* Kick the Tx task in either case in case it doesn't know the buffer is
+ full. */
+ event_signal( pvSendEvent );
+
+ /* The buffer has been sent so can be released. */
+ if( bReleaseAfterSend != pdFALSE )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ }
+
+ return pdPASS;
+}
+
+/* ====================== Static Function definitions ======================= */
+
+/*!
+ * @brief create thread safe buffers to send/receive packets between threads
+ * @returns
+ */
+static int prvCreateThreadSafeBuffers( void )
+{
+int ret = pdFAIL;
+
+ /* The buffer used to pass data to be transmitted from a FreeRTOS task to
+ the linux thread that sends via the pcap library. */
+ do
+ {
+ if( xSendBuffer == NULL )
+ {
+ xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );
+
+ if( xSendBuffer == NULL )
+ {
+ break;
+ }
+
+ configASSERT( xSendBuffer );
+ memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );
+ xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;
+ }
+
+ /* The buffer used to pass received data from the pthread that receives
+ via the pcap library to the FreeRTOS task. */
+ if( xRecvBuffer == NULL )
+ {
+ xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );
+
+ if( xRecvBuffer == NULL )
+ {
+ break;
+ }
+
+ configASSERT( xRecvBuffer );
+ memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );
+ xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ return ret;
+}
+
+/*!
+ * @brief print network interfaces available on the system
+ * @param[in] pxAllNetworkInterfaces interface structure list to print
+ */
+static void prvPrintAvailableNetworkInterfaces( pcap_if_t * pxAllNetworkInterfaces )
+{
+pcap_if_t *xInterface;
+int32_t lInterfaceNumber = 1;
+char cBuffer[ 512 ];
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ /* Print out the list of network interfaces. The first in the list
+ is interface '1', not interface '0'. */
+ for( xInterface = pxAllNetworkInterfaces;
+ xInterface != NULL; xInterface = xInterface->next )
+ {
+ /* The descriptions of the devices can be full of spaces, clean them
+ a little. printf() can only be used here because the network is not
+ up yet - so no other network tasks will be running. */
+ printf( "Interface %d - %s\n",
+ lInterfaceNumber,
+ prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );
+ printf( " (%s)\n",
+ prvRemoveSpaces( cBuffer,
+ sizeof( cBuffer ),
+ xInterface->description ? xInterface->description :
+ "No description" ) );
+ printf( "\n" );
+ lInterfaceNumber++;
+ }
+ }
+
+ if( lInterfaceNumber == 1 )
+ {
+ /* The interface number was never incremented, so the above for() loop
+ did not execute meaning no interfaces were found. */
+ printf( " \nNo network interfaces were found.\n" );
+ pxAllNetworkInterfaces = NULL;
+ }
+
+ printf( "\r\nThe interface that will be opened is set by " );
+ printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );
+
+ if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) )
+ {
+ printf( "\r\nERROR: configNETWORK_INTERFACE_TO_USE is set to %ld, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse );
+ printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );
+ printf( "then re-compile and re-start the application. Only Ethernet (as opposed to WiFi)\r\n" );
+ printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );
+ xInvalidInterfaceDetected = pdTRUE;
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ /* Free the device list, as no devices are going to be opened. */
+ pcap_freealldevs( pxAllNetworkInterfaces );
+ pxAllNetworkInterfaces = NULL;
+ }
+ }
+ else
+ {
+ printf( "Attempting to open interface number %ld.\n", xConfigNetworkInterfaceToUse );
+ }
+}
+
+/*!
+ * @brief get network interfaces from the system
+ * @returns the structure list containing all found devices
+ */
+static pcap_if_t * prvGetAvailableNetworkInterfaces( void )
+{
+pcap_if_t * pxAllNetworkInterfaces = NULL;
+
+ if( xInvalidInterfaceDetected == pdFALSE )
+ {
+ int ret;
+ ret = pcap_findalldevs( &pxAllNetworkInterfaces, errbuf );
+
+ if( ret == PCAP_ERROR )
+ {
+ FreeRTOS_printf( ( "Could not obtain a list of network interfaces\n%s\n",
+ errbuf ) );
+ pxAllNetworkInterfaces = NULL;
+ }
+ else
+ {
+ printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );
+ }
+ }
+
+ return pxAllNetworkInterfaces;
+}
+
+/*!
+ * @brief set device operation modes
+ * @returns pdPASS on success pdFAIL on failure
+ */
+static int prvSetDeviceModes()
+{
+int ret = pdFAIL;
+
+ /*
+ Open in promiscuous mode as the MAC and
+ IP address is going to be "simulated", and
+ not be the real MAC and IP address. This allows
+ traffic to the simulated IP address to be routed
+ to uIP, and traffic to the real IP address to be
+ routed to the Linux TCP/IP stack.
+ */
+ FreeRTOS_debug_printf( ( "setting device modes of operation...\n" ) );
+
+ do
+ {
+ ret = pcap_set_promisc( pxOpenedInterfaceHandle, 1 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not activate promisuous mode\n" ) );
+ break;
+ }
+
+ ret = pcap_set_snaplen( pxOpenedInterfaceHandle,
+ ipTOTAL_ETHERNET_FRAME_SIZE );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set snaplen\n" ) );
+ break;
+ }
+
+ ret = pcap_set_timeout( pxOpenedInterfaceHandle, 200 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set timeout\n" ) );
+ break;
+ }
+
+ ret = pcap_set_buffer_size( pxOpenedInterfaceHandle,
+ ipTOTAL_ETHERNET_FRAME_SIZE * 1100 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set buffer size\n" ) );
+ break;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ return ret;
+}
+
+/*!
+ * @brief open selected interface given its name
+ * @param [in] pucName interface name to pen
+ * @returns pdPASS on success pdFAIL on failure
+ */
+static int prvOpenInterface( const char *pucName )
+{
+static char pucInterfaceName[ 256 ];
+int ret = pdFAIL;
+
+ if( pucName != NULL )
+ {
+ ( void ) strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );
+ pucInterfaceName[ sizeof( pucInterfaceName ) - ( size_t ) 1 ] = '\0';
+
+ FreeRTOS_debug_printf( ( "opening interface %s\n", pucInterfaceName ) );
+
+ pxOpenedInterfaceHandle = pcap_create( pucInterfaceName, errbuf );
+
+ if( pxOpenedInterfaceHandle != NULL )
+ {
+ ret = prvSetDeviceModes();
+
+ if( ret == pdPASS )
+ {
+ if( pcap_activate( pxOpenedInterfaceHandle ) == 0 )
+ {
+ /* Configure the capture filter to allow blocking reads, and to filter
+ out packets that are not of interest to this demo. */
+ ret = prvConfigureCaptureBehaviour();
+ }
+ else
+ {
+ FreeRTOS_debug_printf( ( "pcap activate error %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) ) );
+ ret = pdFAIL;
+ }
+ }
+ }
+ else
+ {
+ FreeRTOS_printf( ( "\n%s is not supported by pcap and cannot be opened %s\n",
+ pucInterfaceName, errbuf ) );
+ }
+ }
+ else
+ {
+ FreeRTOS_printf( ( "could not open interface: name is null\n" ) );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief Open the network interface. The number of the interface to be opened is
+ * set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h
+ * Calling this function will set the pxOpenedInterfaceHandle variable
+ * If, after calling this function, pxOpenedInterfaceHandle
+ * is equal to NULL, then the interface could not be opened.
+ * @param [in] pxAllNetworkInterfaces network interface list to choose from
+ * @returns pdPASS on success or pdFAIL when something goes wrong
+ */
+static int prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
+{
+pcap_if_t *pxInterface;
+int32_t x;
+int ret = pdFAIL;
+
+ /* Walk the list of devices until the selected device is located. */
+ pxInterface = pxAllNetworkInterfaces;
+
+ for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )
+ {
+ pxInterface = pxInterface->next;
+ }
+
+ /* Open the selected interface. */
+ if( prvOpenInterface( pxInterface->name ) == pdPASS )
+ {
+ FreeRTOS_debug_printf( ( "Successfully opened interface number %d.\n", x + 1 ) );
+ ret = pdPASS;
+ }
+ else
+ {
+ FreeRTOS_printf( ( "Failed to open interface number %d.\n", x + 1 ) );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief launch 2 linux threads, one for Tx and one for Rx
+ * and one FreeRTOS thread that will simulate an interrupt
+ * and notify the tcp/ip stack of new data
+ * @return pdPASS on success otherwise pdFAIL
+ */
+static int prvCreateWorkerThreads( void )
+{
+pthread_t vPcapRecvThreadHandle;
+pthread_t vPcapSendThreadHandle;
+int ret = pdPASS;
+
+ if( pvSendEvent == NULL )
+ {
+ FreeRTOS_debug_printf( ( "Creating Threads ..\n" ) );
+ ret = pdFAIL;
+ /* Create event used to signal the pcap Tx thread. */
+ pvSendEvent = event_create();
+
+ do
+ {
+ /* Create the thread that handles pcap Rx. */
+ ret = pthread_create( &vPcapRecvThreadHandle,
+ NULL,
+ prvLinuxPcapRecvThread,
+ NULL );
+
+ if( ret != 0 )
+ {
+ FreeRTOS_printf( ( "pthread error %d", ret ) );
+ break;
+ }
+
+ /* Create the thread that handles pcap Tx. */
+ ret = pthread_create( &vPcapSendThreadHandle,
+ NULL,
+ prvLinuxPcapSendThread,
+ NULL );
+
+ if( ret != 0 )
+ {
+ FreeRTOS_printf( ( "pthread error %d", ret ) );
+ break;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ /* Create a task that simulates an interrupt in a real system. This will
+ block waiting for packets, then send a message to the IP task when data
+ is available. */
+ if( xTaskCreate( prvInterruptSimulatorTask,
+ "MAC_ISR",
+ configMINIMAL_STACK_SIZE,
+ NULL,
+ configMAC_ISR_SIMULATOR_PRIORITY,
+ NULL ) != pdPASS )
+ {
+ ret = pdFAIL;
+ FreeRTOS_printf( ( "xTaskCreate could not create a new task\n" ) );
+ }
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief Create the buffers used to pass packets between the FreeRTOS simulator
+ * and the pthreads that are handling pcap as well as the FreeRTOS task
+ * responsible of simulating an interrupt.
+ * @returns pdPASS when successful and pdFAIL when there is a failure
+ */
+static int prvConfigureCaptureBehaviour( void )
+{
+ struct bpf_program xFilterCode;
+ uint32_t ulNetMask;
+ char pcap_filter[ 500 ];
+ int ret = pdFAIL;
+
+ FreeRTOS_debug_printf( ( "Configuring Capture behaviour\n" ) );
+
+ /* Set up a filter so only the packets of interest are passed to the IP
+ stack. errbuf is used for convenience to create the string. Don't
+ confuse this with an error message. */
+ sprintf( pcap_filter, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",
+ ucMACAddress[ 0 ],
+ ucMACAddress[ 1 ],
+ ucMACAddress[ 2 ],
+ ucMACAddress[ 3 ],
+ ucMACAddress[ 4 ],
+ ucMACAddress[ 5 ] );
+ FreeRTOS_debug_printf( ( "pcap filter to compile: %s\n", pcap_filter ) );
+
+ ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
+
+ ret = pcap_compile( pxOpenedInterfaceHandle,
+ &xFilterCode,
+ pcap_filter,
+ 1,
+ ulNetMask );
+
+ if( ret < 0 )
+ {
+ ( void ) printf( "\nThe packet filter string is invalid %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) );
+ }
+ else
+ {
+ ret = pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode );
+
+ if( ret < 0 )
+ {
+ ( void ) printf( "\nAn error occurred setting the packet filter. %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) );
+ }
+ else
+ {
+ ret = pdPASS;
+ }
+
+ /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct
+ parameter.pcap_freecode() will free that memory. */
+ pcap_freecode( &xFilterCode );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief callback function called from pcap_dispatch function when new
+ * data arrives on the interface
+ * @param [in] user data sent to pcap_dispatch
+ * @param [in] pkt_header received packet header
+ * @param [in] pkt_data received packet data
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ */
+static void pcap_callback( unsigned char *user,
+ const struct pcap_pkthdr *pkt_header,
+ const u_char *pkt_data )
+{
+ FreeRTOS_debug_printf( ( "Receiving < =========== network callback user: %s len: %d caplen: %d\n",
+ user,
+ pkt_header->len,
+ pkt_header->caplen ) );
+ print_hex( pkt_data, pkt_header->len );
+
+ /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */
+ if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
+ ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
+ {
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) );
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen );
+ }
+}
+
+/*!
+ * @brief infinite loop pthread to read from pcap
+ * @param [in] pvParam not used
+ * @returns NULL
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ * @remarks This function disables signal, to prevent it from being put into
+ * sleep byt the posix port
+ */
+static void * prvLinuxPcapRecvThread( void *pvParam )
+{
+int ret;
+
+ ( void ) pvParam;
+
+ /* Disable signals to this thread since this is a Linux pthread to be able to
+ * printf and other blocking operations without being interruped and put in
+ * suspension mode by the linux port signals
+ */
+ sigset_t set;
+ sigfillset( &set );
+ pthread_sigmask( SIG_SETMASK, &set, NULL );
+
+ for( ; ; )
+ {
+ ret = pcap_dispatch( pxOpenedInterfaceHandle, 1,
+ pcap_callback, ( u_char * ) "mydata" );
+
+ if( ret == -1 )
+ {
+ FreeRTOS_printf( ( "pcap_dispatch error received: %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) ) );
+ }
+ }
+
+ return NULL;
+}
+
+/*!
+ * @brief Infinite loop thread that waits for events when there is data
+ * available then sends the data on the interface
+ * @param [in] pvParam not used
+ * @returns NULL
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ */
+static void * prvLinuxPcapSendThread( void *pvParam )
+{
+size_t xLength;
+uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
+const time_t xMaxMSToWait = 1000;
+
+ ( void ) pvParam;
+
+ /* disable signals to avoid treating this thread as a FreeRTOS task and puting
+ * it to sleep by the scheduler */
+ sigset_t set;
+ sigfillset( &set );
+ pthread_sigmask( SIG_SETMASK, &set, NULL );
+
+ for( ; ; )
+ {
+ /* Wait until notified of something to send. */
+ event_wait_timed( pvSendEvent, xMaxMSToWait );
+
+ /* Is there more than the length value stored in the circular buffer
+ used to pass data from the FreeRTOS simulator into this pthread?*/
+ while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )
+ {
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) ucBuffer, xLength, pdFALSE );
+ FreeRTOS_debug_printf( ( "Sending ========== > data pcap_sendpadcket %lu\n", xLength ) );
+ print_hex( ucBuffer, xLength );
+
+ if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
+ {
+ FreeRTOS_printf( ( "pcap_sendpackeet: send failed %d\n", ulPCAPSendFailures ) );
+ ulPCAPSendFailures++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*!
+ * @brief FreeRTOS infinite loop thread that simulates a network interrupt to notify the
+ * network stack of the presence of new data
+ * @param [in] pvParameters not used
+ */
+static void prvInterruptSimulatorTask( void *pvParameters )
+{
+ struct pcap_pkthdr xHeader;
+ static struct pcap_pkthdr *pxHeader;
+ const uint8_t *pucPacketData;
+ uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
+ NetworkBufferDescriptor_t *pxNetworkBuffer;
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
+ eFrameProcessingResult_t eResult;
+
+ /* Remove compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ for( ; ; )
+ {
+ /* Does the circular buffer used to pass data from the pthread thread that
+ handles pacap Rx into the FreeRTOS simulator contain another packet? */
+ if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )
+ {
+ /* Get the next packet. */
+ uxStreamBufferGet( xRecvBuffer, 0, ( uint8_t * ) &xHeader, sizeof( xHeader ), pdFALSE );
+ uxStreamBufferGet( xRecvBuffer, 0, ( uint8_t * ) ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );
+ pucPacketData = ucRecvBuffer;
+ pxHeader = &xHeader;
+
+ iptraceNETWORK_INTERFACE_RECEIVE();
+
+ /* Check for minimal size. */
+ if( pxHeader->len >= sizeof( EthernetHeader_t ) )
+ {
+ eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
+ }
+ else
+ {
+ eResult = eReleaseBuffer;
+ }
+
+ if( eResult == eProcessBuffer )
+ {
+ /* Will the data fit into the frame buffer? */
+ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
+ {
+ /* Obtain a buffer into which the data can be placed. This
+ is only an interrupt simulator, not a real interrupt, so it
+ is ok to call the task level function here, but note that
+ some buffer implementations cannot be called from a real
+ interrupt. */
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+
+ if( pxNetworkBuffer != NULL )
+ {
+ memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
+ pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
+
+ #if ( niDISRUPT_PACKETS == 1 )
+ {
+ pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );
+ }
+ #endif /* niDISRUPT_PACKETS */
+
+ if( pxNetworkBuffer != NULL )
+ {
+ xRxEvent.pvData = ( void * ) pxNetworkBuffer;
+
+ /* Data was received and stored. Send a message to
+ the IP task to let it know. */
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
+ {
+ /* The buffer could not be sent to the stack so
+ must be released again. This is only an
+ interrupt simulator, not a real interrupt, so it
+ is ok to use the task level function here, but
+ note no all buffer implementations will allow
+ this function to be executed from a real
+ interrupt. */
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ iptraceETHERNET_RX_EVENT_LOST();
+ }
+ }
+ else
+ {
+ /* The packet was already released or stored inside
+ vRxFaultInjection(). Don't release it here. */
+ }
+ }
+ else
+ {
+ iptraceETHERNET_RX_EVENT_LOST();
+ }
+ }
+ else
+ {
+ /* Log that a packet was dropped because it would have
+ overflowed the buffer, but there may be more buffers to
+ process. */
+ }
+ }
+ }
+ else
+ {
+ /* There is no real way of simulating an interrupt. Make sure
+ other tasks can run. */
+ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
+ }
+ }
+}
+
+/*!
+ * @brief remove spacces from pcMessage into pcBuffer
+ * @param [out] pcBuffer buffer to fill up
+ * @param [in] aBuflen length of pcBuffer
+ * @param [in] pcMessage original message
+ * @returns
+ */
+static const char * prvRemoveSpaces( char *pcBuffer,
+ int aBuflen,
+ const char *pcMessage )
+{
+char *pcTarget = pcBuffer;
+
+ /* Utility function used to formap messages being printed only. */
+ while( ( *pcMessage != 0 ) && ( pcTarget < ( &pcBuffer[ aBuflen - 1 ] ) ) )
+ {
+ *( pcTarget++ ) = *pcMessage;
+
+ if( isspace( *pcMessage ) != pdFALSE )
+ {
+ while( isspace( *pcMessage ) != pdFALSE )
+ {
+ pcMessage++;
+ }
+ }
+ else
+ {
+ pcMessage++;
+ }
+ }
+
+ *pcTarget = '\0';
+
+ return pcBuffer;
+}
+
+/*!
+ * @brief print binary packet in hex
+ * @param [in] bin_daa data to print
+ * @param [in] len length of the data
+ */
+static void print_hex( unsigned const char * const bin_data,
+ size_t len )
+/*static void print_hex(unsigned char *bin_data, size_t len) */
+{
+size_t i;
+
+ for( i = 0; i < len; ++i )
+ {
+ FreeRTOS_debug_printf( ( "%.2X ", bin_data[ i ] ) );
+ }
+
+ FreeRTOS_debug_printf( ( "\n" ) );
+}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
index 87161fd39..f6d152a8c 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
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