--- /dev/null
+Update pack_struct_start.h and pack_struct_end.h for your architecure.
+These files define the specifiers needed by your compiler to properly pack struct data
+need by FreeRTOS+TCP.
\ No newline at end of file
--- /dev/null
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ http://aws.amazon.com/freertos
+ http://www.FreeRTOS.org
+*/
+
+/*****************************************************************************
+ *
+ * See the following URL for an explanation of this file:
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
+ *
+ *****************************************************************************/
+; /* FIX ME. Update for the compiler specifier needed at end of a struct declartion to pack the struct. */
\ No newline at end of file
--- /dev/null
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ http://aws.amazon.com/freertos
+ http://www.FreeRTOS.org
+*/
+
+/*****************************************************************************
+ *
+ * See the following URL for an explanation of this file:
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
+ *
+ *****************************************************************************/
+/* FIX ME. Update for the compiler specifier needed at the start of a struct declartion to pack the struct. */
\ No newline at end of file
-/*
-FreeRTOS+TCP V2.0.11
-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 "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Some files from the Atmel Software Framework */
-/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */
-#include "instance/gmac.h"
-#include <sysclk.h>
-#include <ethernet_phy.h>
-
-#ifndef BMSR_LINK_STATUS
- #define BMSR_LINK_STATUS 0x0004 //!< Link status
-#endif
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
- receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 15000
-#endif
-
-#ifndef PHY_LS_LOW_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still low every second. */
- #define PHY_LS_LOW_CHECK_TIME_MS 1000
-#endif
-
-/* 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 )
-
-#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR
-
-#define HZ_PER_MHZ ( 1000000UL )
-
-#ifndef EMAC_MAX_BLOCK_TIME_MS
- #define EMAC_MAX_BLOCK_TIME_MS 100ul
-#endif
-
-#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )
- #error Please define GMAC_USES_TX_CALLBACK 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
-
-/*-----------------------------------------------------------*/
-
-/*
- * Wait a fixed time for the link status to indicate the network is up.
- */
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime );
-
-#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
- void vGMACGenerateChecksum( uint8_t *apBuffer );
-#endif
-
-/*
- * Called from the ASF GMAC driver.
- */
-static void prvRxCallback( uint32_t ulStatus );
-static void prvTxCallback( 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 );
-
-/*-----------------------------------------------------------*/
-
-/* 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 uint32_t ulPHYLinkStatus = 0;
-static volatile BaseType_t xGMACSwitchRequired;
-
-/* ethernet_phy_addr: the address of the PHY in use.
-Atmel was a bit ambiguous about it so the address will be stored
-in this variable, see ethernet_phy.c */
-extern int ethernet_phy_addr;
-
-/* 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;
-
-/*-----------------------------------------------------------*/
-
-/*
- * GMAC interrupt handler.
- */
-void GMAC_Handler(void)
-{
- xGMACSwitchRequired = pdFALSE;
-
- /* gmac_handler() may call prvRxCallback() which may change
- the value of xGMACSwitchRequired. */
- gmac_handler( &gs_gmac_dev );
-
- if( xGMACSwitchRequired != pdFALSE )
- {
- portEND_SWITCHING_ISR( xGMACSwitchRequired );
- }
-}
-/*-----------------------------------------------------------*/
-
-static void prvRxCallback( 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 );
- }
-}
-/*-----------------------------------------------------------*/
-
-static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )
-{
- if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
- {
- /* let the prvEMACHandlerTask know that there was an RX event. */
- ulISREvents |= EMAC_IF_TX_EVENT;
-
- vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
- xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );
- tx_release_count[ 2 ]++;
- }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-const TickType_t x5_Seconds = 5000UL;
-
- if( xEMACTaskHandle == NULL )
- {
- prvGMACInit();
-
- /* Wait at most 5 seconds for a Link Status in the PHY. */
- xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );
-
- /* 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 );
- }
-
- 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 ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xResult;
-
- /* This function returns true if the Link Status in the PHY is high. */
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xResult = pdTRUE;
- }
- else
- {
- xResult = pdFALSE;
- }
-
- return xResult;
-}
-/*-----------------------------------------------------------*/
-
-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 );
-
- do {
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
- {
- /* 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;
- }
- 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 */
-
- gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );
-
- #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( 0 );
-
- if( bReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
- return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACInit( void )
-{
-uint32_t ncfgr;
-
- gmac_options_t gmac_option;
-
- 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 );
-
- /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */
- ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );
-
- ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );
- ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );
-
- /* The GMAC driver will call a hook prvRxCallback(), which
- in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */
- gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );
- gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );
-
- ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;
-
- GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;
-
- return 1;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )
-{
-uint32_t ulValue, ulReturn;
-int rc;
-
- gmac_enable_management( GMAC, 1 );
- rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );
- gmac_enable_management( GMAC, 0 );
- if( rc == GMAC_OK )
- {
- ulReturn = ulValue;
- }
- else
- {
- ulReturn = 0UL;
- }
-
- return ulReturn;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime = xTaskGetTickCount();
-TickType_t xEndTime;
-BaseType_t xReturn;
-const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
-
- for( ;; )
- {
- xEndTime = xTaskGetTickCount();
-
- if( ( xEndTime - xStartTime ) > xMaxTime )
- {
- /* Wated more than xMaxTime, return. */
- xReturn = pdFALSE;
- break;
- }
-
- /* Check the link status again. */
- ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- /* Link is up - return. */
- xReturn = pdTRUE;
- break;
- }
-
- /* Link is down - wait in the Blocked state for a short while (to allow
- other tasks to execute) before checking again. */
- vTaskDelay( xShortTime );
- }
-
- FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",
- xReturn,
- ethernet_phy_addr,
- sysclk_get_cpu_hz() / HZ_PER_MHZ ) );
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
-
- void vGMACGenerateChecksum( uint8_t *apBuffer )
- {
- ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;
-
- 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( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
- pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
-
- /* Calculate the TCP checksum for an outgoing packet. */
- usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );
- }
- }
-
-//#endif
-/*-----------------------------------------------------------*/
-
-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 };
-
- 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 );
-
- 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();
- 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;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0, uxCount;
-UBaseType_t uxCurrentCount;
-#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- UBaseType_t uxLastMinQueueSpace;
-#endif
-#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 );
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
- for( ;; )
- {
- uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
- if( uxLastMinBufferCount != uxCurrentCount )
- {
- /* The logging produced below may be helpful
- while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
- }
-
- #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 */
-
- 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;
- }
-
- if( xResult > 0 )
- {
- /* A packet was received. No need to check for the PHY status now,
- but set a timer to check it later on. */
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- xResult = 0;
- }
- else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
- {
- /* Check the link status again. */
- xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
- {
- ulPHYLinkStatus = xStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */\r
+#include "instance/gmac.h"\r
+#include <sysclk.h>\r
+#include <ethernet_phy.h>\r
+\r
+#ifndef BMSR_LINK_STATUS\r
+ #define BMSR_LINK_STATUS 0x0004 //!< Link status\r
+#endif\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+ receiving packets. */\r
+ #define PHY_LS_HIGH_CHECK_TIME_MS 15000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still low every second. */\r
+ #define PHY_LS_LOW_CHECK_TIME_MS 1000\r
+#endif\r
+\r
+/* Interrupt events to process. Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT 1UL\r
+#define EMAC_IF_TX_EVENT 2UL\r
+#define EMAC_IF_ERR_EVENT 4UL\r
+#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR\r
+\r
+#define HZ_PER_MHZ ( 1000000UL )\r
+\r
+#ifndef EMAC_MAX_BLOCK_TIME_MS\r
+ #define EMAC_MAX_BLOCK_TIME_MS 100ul\r
+#endif\r
+\r
+#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )\r
+ #error Please define GMAC_USES_TX_CALLBACK as 1\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+ #define configEMAC_TASK_STACK_SIZE ( 4 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+ void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+#endif\r
+\r
+/*\r
+ * Called from the ASF GMAC driver.\r
+ */\r
+static void prvRxCallback( uint32_t ulStatus );\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Initialise the ASF GMAC driver.\r
+ */\r
+static BaseType_t prvGMACInit( void );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing. Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+/* ethernet_phy_addr: the address of the PHY in use.\r
+Atmel was a bit ambiguous about it so the address will be stored\r
+in this variable, see ethernet_phy.c */\r
+extern int ethernet_phy_addr;\r
+\r
+/* LLMNR multicast address. */\r
+static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+\r
+/* The GMAC object as defined by the ASF drivers. */\r
+static gmac_device_t gs_gmac_dev;\r
+\r
+/* MAC address to use. */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor. The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+static QueueHandle_t xTxBufferQueue;\r
+int tx_release_count[ 4 ];\r
+\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of GMAC_TX_BUFFERS, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * GMAC interrupt handler.\r
+ */\r
+void GMAC_Handler(void)\r
+{\r
+ xGMACSwitchRequired = pdFALSE;\r
+\r
+ /* gmac_handler() may call prvRxCallback() which may change\r
+ the value of xGMACSwitchRequired. */\r
+ gmac_handler( &gs_gmac_dev );\r
+\r
+ if( xGMACSwitchRequired != pdFALSE )\r
+ {\r
+ portEND_SWITCHING_ISR( xGMACSwitchRequired );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRxCallback( uint32_t ulStatus )\r
+{\r
+ if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )\r
+ {\r
+ /* let the prvEMACHandlerTask know that there was an RX event. */\r
+ ulISREvents |= EMAC_IF_RX_EVENT;\r
+ /* Only an RX interrupt can wakeup prvEMACHandlerTask. */\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )\r
+{\r
+ if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )\r
+ {\r
+ /* let the prvEMACHandlerTask know that there was an RX event. */\r
+ ulISREvents |= EMAC_IF_TX_EVENT;\r
+\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+ xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );\r
+ tx_release_count[ 2 ]++;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+ if( xEMACTaskHandle == NULL )\r
+ {\r
+ prvGMACInit();\r
+\r
+ /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+ xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+ /* The handler task is created at the highest possible priority to\r
+ ensure the interrupt handler can return directly to it. */\r
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+ configASSERT( xEMACTaskHandle );\r
+ }\r
+\r
+ if( xTxBufferQueue == NULL )\r
+ {\r
+ xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );\r
+ configASSERT( xTxBufferQueue );\r
+ }\r
+\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );\r
+ configASSERT( xTXDescriptorSemaphore );\r
+ }\r
+ /* When returning non-zero, the stack will become active and\r
+ start DHCP (in configured) */\r
+ return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+ /* This function returns true if the Link Status in the PHY is high. */\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xResult = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ xResult = pdFALSE;\r
+ }\r
+\r
+ return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+/* Do not wait too long for a free TX DMA buffer. */\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
+\r
+ do {\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+ {\r
+ /* Do not attempt to send packets as long as the Link Status is low. */\r
+ break;\r
+ }\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ /* Semaphore has not been created yet? */\r
+ break;\r
+ }\r
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+ {\r
+ /* Time-out waiting for a free TX descriptor. */\r
+ tx_release_count[ 3 ]++;\r
+ break;\r
+ }\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* Confirm that the pxDescriptor may be kept by the driver. */\r
+ configASSERT( bReleaseAfterSend != pdFALSE );\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+ gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );\r
+\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* Confirm that the pxDescriptor may be kept by the driver. */\r
+ bReleaseAfterSend = pdFALSE;\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+ /* Not interested in a call-back after TX. */\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+ } while( 0 );\r
+\r
+ if( bReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+ return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACInit( void )\r
+{\r
+uint32_t ncfgr;\r
+\r
+ gmac_options_t gmac_option;\r
+\r
+ memset( &gmac_option, '\0', sizeof( gmac_option ) );\r
+ gmac_option.uc_copy_all_frame = 0;\r
+ gmac_option.uc_no_boardcast = 0;\r
+ memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );\r
+\r
+ gs_gmac_dev.p_hw = GMAC;\r
+ gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );\r
+\r
+ NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+ NVIC_EnableIRQ( GMAC_IRQn );\r
+\r
+ /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */\r
+ ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );\r
+\r
+ ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );\r
+ ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );\r
+\r
+ /* The GMAC driver will call a hook prvRxCallback(), which\r
+ in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */\r
+ gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );\r
+ gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );\r
+\r
+ ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;\r
+\r
+ GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;\r
+\r
+ return 1;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )\r
+{\r
+uint32_t ulValue, ulReturn;\r
+int rc;\r
+\r
+ gmac_enable_management( GMAC, 1 );\r
+ rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );\r
+ gmac_enable_management( GMAC, 0 );\r
+ if( rc == GMAC_OK )\r
+ {\r
+ ulReturn = ulValue;\r
+ }\r
+ else\r
+ {\r
+ ulReturn = 0UL;\r
+ }\r
+\r
+ return ulReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+\r
+ for( ;; )\r
+ {\r
+ xEndTime = xTaskGetTickCount();\r
+\r
+ if( ( xEndTime - xStartTime ) > xMaxTime )\r
+ {\r
+ /* Wated more than xMaxTime, return. */\r
+ xReturn = pdFALSE;\r
+ break;\r
+ }\r
+\r
+ /* Check the link status again. */\r
+ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ /* Link is up - return. */\r
+ xReturn = pdTRUE;\r
+ break;\r
+ }\r
+\r
+ /* Link is down - wait in the Blocked state for a short while (to allow\r
+ other tasks to execute) before checking again. */\r
+ vTaskDelay( xShortTime );\r
+ }\r
+\r
+ FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",\r
+ xReturn,\r
+ ethernet_phy_addr,\r
+ sysclk_get_cpu_hz() / HZ_PER_MHZ ) );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+\r
+ void vGMACGenerateChecksum( uint8_t *apBuffer )\r
+ {\r
+ ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;\r
+\r
+ if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )\r
+ {\r
+ IPHeader_t *pxIPHeader = &(xProtPacket->xTCPPacket.xIPHeader);\r
+\r
+ /* Calculate the IP header checksum. */\r
+ pxIPHeader->usHeaderChecksum = 0x00;\r
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+ pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+ /* Calculate the TCP checksum for an outgoing packet. */\r
+ usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );\r
+ }\r
+ }\r
+\r
+//#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+unsigned char *pucUseBuffer;\r
+uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;\r
+static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;\r
+const UBaseType_t xMinDescriptorsToLeave = 2UL;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );\r
+static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+ for( ;; )\r
+ {\r
+ /* If pxNextNetworkBufferDescriptor was not left pointing at a valid\r
+ descriptor then allocate one now. */\r
+ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )\r
+ {\r
+ pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );\r
+ }\r
+\r
+ if( pxNextNetworkBufferDescriptor != NULL )\r
+ {\r
+ /* Point pucUseBuffer to the buffer pointed to by the descriptor. */\r
+ pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );\r
+ }\r
+ else\r
+ {\r
+ /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming\r
+ messages will be flushed and ignored. */\r
+ pucUseBuffer = NULL;\r
+ }\r
+\r
+ /* Read the next packet from the hardware into pucUseBuffer. */\r
+ ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );\r
+\r
+ if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )\r
+ {\r
+ /* No data from the hardware. */\r
+ break;\r
+ }\r
+\r
+ if( pxNextNetworkBufferDescriptor == NULL )\r
+ {\r
+ /* Data was read from the hardware, but no descriptor was available\r
+ for it, so it will be dropped. */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ continue;\r
+ }\r
+\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;\r
+ xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;\r
+\r
+ /* Send the descriptor to the IP task for processing. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )\r
+ {\r
+ /* The buffer could not be sent to the stack so must be released\r
+ again. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+ }\r
+\r
+ /* Now the buffer has either been passed to the IP-task,\r
+ or it has been released in the code above. */\r
+ pxNextNetworkBufferDescriptor = NULL;\r
+ ulReturnValue++;\r
+ }\r
+\r
+ return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0, uxCount;\r
+UBaseType_t uxCurrentCount;\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ UBaseType_t uxLastMinQueueSpace;\r
+#endif\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ NetworkBufferDescriptor_t *pxBuffer;\r
+#endif\r
+uint8_t *pucBuffer;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+\r
+ configASSERT( xEMACTaskHandle );\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+ for( ;; )\r
+ {\r
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+ if( uxLastMinBufferCount != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+ }\r
+\r
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+ if( uxLastMinQueueSpace != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinQueueSpace = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+ }\r
+ }\r
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+ if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+ {\r
+ /* No events to process now, wait for the next. */\r
+ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+ {\r
+ ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+ /* Wait for the EMAC interrupt to indicate that another packet has been\r
+ received. */\r
+ xResult = prvEMACRxPoll();\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+ {\r
+ /* Future extension: code to release TX buffers if zero-copy is used. */\r
+ ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+ while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )\r
+ {\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+ if( pxBuffer != NULL )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+ tx_release_count[ 0 ]++;\r
+ }\r
+ else\r
+ {\r
+ tx_release_count[ 1 ]++;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ tx_release_count[ 0 ]++;\r
+ }\r
+ #endif\r
+ uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );\r
+ if( uxCount < GMAC_TX_BUFFERS )\r
+ {\r
+ /* Tell the counting semaphore that one more TX descriptor is available. */\r
+ xSemaphoreGive( xTXDescriptorSemaphore );\r
+ }\r
+ }\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+ {\r
+ /* Future extension: logging about errors that occurred. */\r
+ ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+ }\r
+\r
+ if( xResult > 0 )\r
+ {\r
+ /* A packet was received. No need to check for the PHY status now,\r
+ but set a timer to check it later on. */\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ xResult = 0;\r
+ }\r
+ else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+ {\r
+ /* Check the link status again. */\r
+ xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+ {\r
+ ulPHYLinkStatus = xStatus;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+ }\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ }\r
+ else\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
-/**
- * \file
- *
- * Copyright (c) 2012 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
- *
- */
-
-#ifndef _SAM4E_GMAC_COMPONENT_
-#define _SAM4E_GMAC_COMPONENT_
-
-/* ============================================================================= */
-/** SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */
-/* ============================================================================= */
-/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */
-/*@{*/
-
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
-/** \brief GmacSa hardware registers */
-typedef struct {
- RwReg GMAC_SAB; /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */
- RwReg GMAC_SAT; /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */
-} GmacSa;
-/** \brief Gmac hardware registers */
-#define GMACSA_NUMBER 4
-typedef struct {
- RwReg GMAC_NCR; /**< \brief (Gmac Offset: 0x000) Network Control Register */
- RwReg GMAC_NCFGR; /**< \brief (Gmac Offset: 0x004) Network Configuration Register */
- RoReg GMAC_NSR; /**< \brief (Gmac Offset: 0x008) Network Status Register */
- RwReg GMAC_UR; /**< \brief (Gmac Offset: 0x00C) User Register */
- RwReg GMAC_DCFGR; /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */
- RwReg GMAC_TSR; /**< \brief (Gmac Offset: 0x014) Transmit Status Register */
- RwReg GMAC_RBQB; /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */
- RwReg GMAC_TBQB; /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */
- RwReg GMAC_RSR; /**< \brief (Gmac Offset: 0x020) Receive Status Register */
- RoReg GMAC_ISR; /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */
- WoReg GMAC_IER; /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */
- WoReg GMAC_IDR; /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */
- RoReg GMAC_IMR; /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */
- RwReg GMAC_MAN; /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */
- RoReg GMAC_RPQ; /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */
- RwReg GMAC_TPQ; /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */
- RwReg GMAC_TPSF; /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */
- RwReg GMAC_RPSF; /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */
- RoReg Reserved1[14];
- RwReg GMAC_HRB; /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */
- RwReg GMAC_HRT; /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */
- GmacSa GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */
- RwReg GMAC_TIDM[4]; /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */
- RwReg GMAC_WOL; /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */
- RwReg GMAC_IPGS; /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */
- RwReg GMAC_SVLAN; /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */
- RwReg GMAC_TPFCP; /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */
- RwReg GMAC_SAMB1; /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */
- RwReg GMAC_SAMT1; /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */
- RoReg Reserved2[12];
- RoReg GMAC_OTLO; /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */
- RoReg GMAC_OTHI; /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */
- RoReg GMAC_FT; /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */
- RoReg GMAC_BCFT; /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */
- RoReg GMAC_MFT; /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */
- RoReg GMAC_PFT; /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */
- RoReg GMAC_BFT64; /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */
- RoReg GMAC_TBFT127; /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */
- RoReg GMAC_TBFT255; /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */
- RoReg GMAC_TBFT511; /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */
- RoReg GMAC_TBFT1023; /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */
- RoReg GMAC_TBFT1518; /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */
- RoReg GMAC_GTBFT1518; /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */
- RoReg GMAC_TUR; /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */
- RoReg GMAC_SCF; /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */
- RoReg GMAC_MCF; /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */
- RoReg GMAC_EC; /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */
- RoReg GMAC_LC; /**< \brief (Gmac Offset: 0x144) Late Collisions Register */
- RoReg GMAC_DTF; /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */
- RoReg GMAC_CSE; /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */
- RoReg GMAC_ORLO; /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */
- RoReg GMAC_ORHI; /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */
- RoReg GMAC_FR; /**< \brief (Gmac Offset: 0x158) Frames Received Register */
- RoReg GMAC_BCFR; /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */
- RoReg GMAC_MFR; /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */
- RoReg GMAC_PFR; /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */
- RoReg GMAC_BFR64; /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */
- RoReg GMAC_TBFR127; /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */
- RoReg GMAC_TBFR255; /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */
- RoReg GMAC_TBFR511; /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */
- RoReg GMAC_TBFR1023; /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */
- RoReg GMAC_TBFR1518; /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */
- RoReg GMAC_TMXBFR; /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */
- RoReg GMAC_UFR; /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */
- RoReg GMAC_OFR; /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */
- RoReg GMAC_JR; /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */
- RoReg GMAC_FCSE; /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */
- RoReg GMAC_LFFE; /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */
- RoReg GMAC_RSE; /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */
- RoReg GMAC_AE; /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */
- RoReg GMAC_RRE; /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */
- RoReg GMAC_ROE; /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */
- RoReg GMAC_IHCE; /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */
- RoReg GMAC_TCE; /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */
- RoReg GMAC_UCE; /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */
- RoReg Reserved3[5];
- RwReg GMAC_TSSS; /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */
- RwReg GMAC_TSSN; /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */
- RwReg GMAC_TS; /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */
- RwReg GMAC_TN; /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */
- WoReg GMAC_TA; /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */
- RwReg GMAC_TI; /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */
- RoReg GMAC_EFTS; /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */
- RoReg GMAC_EFTN; /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */
- RoReg GMAC_EFRS; /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */
- RoReg GMAC_EFRN; /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */
- RoReg GMAC_PEFTS; /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */
- RoReg GMAC_PEFTN; /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */
- RoReg GMAC_PEFRS; /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */
- RoReg GMAC_PEFRN; /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */
- RoReg Reserved4[128];
- RoReg GMAC_ISRPQ[7]; /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */
- RoReg Reserved5[9];
- RwReg GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */
- RoReg Reserved6[9];
- RwReg GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */
- RoReg Reserved7[1];
- RwReg GMAC_RBSRPQ[7]; /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */
- RoReg Reserved8[17];
- RwReg GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */
- RwReg GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */
- RoReg Reserved9[32];
- WoReg GMAC_IERPQ[7]; /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */
- RoReg Reserved10[1];
- WoReg GMAC_IDRPQ[7]; /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */
- RoReg Reserved11[1];
- RwReg GMAC_IMRPQ[7]; /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */
-} Gmac;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
-/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */
-#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */
-#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */
-#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */
-#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */
-#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */
-#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */
-#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */
-#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */
-#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */
-#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */
-#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */
-#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */
-#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */
-#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */
-#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */
-#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */
-#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */
-#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */
-/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */
-#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */
-#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */
-#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */
-#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */
-#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */
-#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */
-#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */
-#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */
-#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */
-#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */
-#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */
-#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */
-#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */
-#define GMAC_NCFGR_RXBUFO_Pos 14
-#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */
-#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))
-#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */
-#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */
-#define GMAC_NCFGR_CLK_Pos 18
-#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */
-#define GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */
-#define GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */
-#define GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */
-#define GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */
-#define GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */
-#define GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */
-#define GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */
-#define GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */
-#define GMAC_NCFGR_DBW_Pos 21
-#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */
-#define GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */
-#define GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */
-#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */
-#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */
-#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */
-#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */
-#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */
-#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */
-#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */
-/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */
-#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */
-#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */
-/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */
-#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */
-#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */
-#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */
-/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */
-#define GMAC_DCFGR_FBLDO_Pos 0
-#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */
-#define GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */
-#define GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */
-#define GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */
-#define GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */
-#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */
-#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */
-#define GMAC_DCFGR_RXBMS_Pos 8
-#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */
-#define GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */
-#define GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */
-#define GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */
-#define GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */
-#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */
-#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */
-#define GMAC_DCFGR_DRBS_Pos 16
-#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */
-#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))
-#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */
-/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */
-#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */
-#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */
-#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */
-#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */
-#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */
-#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */
-#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */
-#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */
-#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */
-/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */
-#define GMAC_RBQB_ADDR_Pos 2
-#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */
-#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))
-/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */
-#define GMAC_TBQB_ADDR_Pos 2
-#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */
-#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))
-/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */
-#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */
-#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */
-#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */
-#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */
-/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */
-#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */
-#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */
-#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */
-#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */
-#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */
-#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */
-#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */
-#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */
-#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */
-#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */
-#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */
-#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */
-#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */
-#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */
-#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */
-#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */
-#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */
-#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */
-#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */
-#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */
-#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */
-#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */
-#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */
-/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */
-#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */
-#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */
-#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */
-#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */
-#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */
-#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */
-#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */
-#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */
-#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */
-#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */
-#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */
-#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */
-#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */
-#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */
-#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */
-#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */
-#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */
-#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */
-#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */
-#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */
-#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */
-#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */
-#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */
-/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */
-#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */
-#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */
-#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */
-#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */
-#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */
-#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */
-#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */
-#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */
-#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */
-#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */
-#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */
-#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */
-#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */
-#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */
-#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */
-#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */
-#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */
-#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */
-#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */
-#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */
-#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */
-#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */
-#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */
-/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */
-#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */
-#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */
-#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */
-#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */
-#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */
-#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */
-#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */
-#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */
-#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */
-#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */
-#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */
-#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */
-#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */
-#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */
-#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */
-#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */
-#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */
-#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */
-#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */
-#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */
-#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */
-/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */
-#define GMAC_MAN_DATA_Pos 0
-#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */
-#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))
-#define GMAC_MAN_WTN_Pos 16
-#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */
-#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))
-#define GMAC_MAN_REGA_Pos 18
-#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */
-#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))
-#define GMAC_MAN_PHYA_Pos 23
-#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */
-#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))
-#define GMAC_MAN_OP_Pos 28
-#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */
-#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))
-#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */
-#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */
-/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */
-#define GMAC_RPQ_RPQ_Pos 0
-#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */
-/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */
-#define GMAC_TPQ_TPQ_Pos 0
-#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */
-#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))
-/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */
-#define GMAC_TPSF_TPB1ADR_Pos 0
-#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */
-#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))
-#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */
-/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */
-#define GMAC_RPSF_RPB1ADR_Pos 0
-#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */
-#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))
-#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */
-/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */
-#define GMAC_HRB_ADDR_Pos 0
-#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */
-#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))
-/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */
-#define GMAC_HRT_ADDR_Pos 0
-#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */
-#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))
-/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */
-#define GMAC_SAB1_ADDR_Pos 0
-#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */
-#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))
-/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */
-#define GMAC_SAT1_ADDR_Pos 0
-#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */
-#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))
-/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */
-#define GMAC_SAB2_ADDR_Pos 0
-#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */
-#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))
-/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */
-#define GMAC_SAT2_ADDR_Pos 0
-#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */
-#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))
-/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */
-#define GMAC_SAB3_ADDR_Pos 0
-#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */
-#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))
-/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */
-#define GMAC_SAT3_ADDR_Pos 0
-#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */
-#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))
-/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */
-#define GMAC_SAB4_ADDR_Pos 0
-#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */
-#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))
-/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */
-#define GMAC_SAT4_ADDR_Pos 0
-#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */
-#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))
-/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */
-#define GMAC_TIDM_TID_Pos 0
-#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */
-#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))
-/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */
-#define GMAC_WOL_IP_Pos 0
-#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */
-#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))
-#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */
-#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */
-#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */
-#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */
-/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */
-#define GMAC_IPGS_FL_Pos 0
-#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */
-#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))
-/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */
-#define GMAC_SVLAN_VLAN_TYPE_Pos 0
-#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */
-#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))
-#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */
-/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */
-#define GMAC_TPFCP_PEV_Pos 0
-#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */
-#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))
-#define GMAC_TPFCP_PQ_Pos 8
-#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */
-#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))
-/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */
-#define GMAC_SAMB1_ADDR_Pos 0
-#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */
-#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))
-/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */
-#define GMAC_SAMT1_ADDR_Pos 0
-#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */
-#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))
-/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */
-#define GMAC_OTLO_TXO_Pos 0
-#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */
-/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */
-#define GMAC_OTHI_TXO_Pos 0
-#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */
-/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */
-#define GMAC_FT_FTX_Pos 0
-#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */
-/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */
-#define GMAC_BCFT_BFTX_Pos 0
-#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */
-/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */
-#define GMAC_MFT_MFTX_Pos 0
-#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */
-/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */
-#define GMAC_PFT_PFTX_Pos 0
-#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */
-/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */
-#define GMAC_BFT64_NFTX_Pos 0
-#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT127_NFTX_Pos 0
-#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT255_NFTX_Pos 0
-#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT511_NFTX_Pos 0
-#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT1023_NFTX_Pos 0
-#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT1518_NFTX_Pos 0
-#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */
-/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */
-#define GMAC_GTBFT1518_NFTX_Pos 0
-#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */
-/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */
-#define GMAC_TUR_TXUNR_Pos 0
-#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */
-/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */
-#define GMAC_SCF_SCOL_Pos 0
-#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */
-/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */
-#define GMAC_MCF_MCOL_Pos 0
-#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */
-/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */
-#define GMAC_EC_XCOL_Pos 0
-#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */
-/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */
-#define GMAC_LC_LCOL_Pos 0
-#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */
-/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */
-#define GMAC_DTF_DEFT_Pos 0
-#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */
-/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */
-#define GMAC_CSE_CSR_Pos 0
-#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */
-/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */
-#define GMAC_ORLO_RXO_Pos 0
-#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */
-/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */
-#define GMAC_ORHI_RXO_Pos 0
-#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */
-/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */
-#define GMAC_FR_FRX_Pos 0
-#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */
-/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */
-#define GMAC_BCFR_BFRX_Pos 0
-#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */
-/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */
-#define GMAC_MFR_MFRX_Pos 0
-#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */
-/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */
-#define GMAC_PFR_PFRX_Pos 0
-#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */
-/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */
-#define GMAC_BFR64_NFRX_Pos 0
-#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */
-/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */
-#define GMAC_TBFR127_NFRX_Pos 0
-#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */
-/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */
-#define GMAC_TBFR255_NFRX_Pos 0
-#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */
-/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */
-#define GMAC_TBFR511_NFRX_Pos 0
-#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */
-/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */
-#define GMAC_TBFR1023_NFRX_Pos 0
-#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */
-/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */
-#define GMAC_TBFR1518_NFRX_Pos 0
-#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */
-/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */
-#define GMAC_TMXBFR_NFRX_Pos 0
-#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */
-/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */
-#define GMAC_UFR_UFRX_Pos 0
-#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */
-/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */
-#define GMAC_OFR_OFRX_Pos 0
-#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */
-/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */
-#define GMAC_JR_JRX_Pos 0
-#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */
-/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */
-#define GMAC_FCSE_FCKR_Pos 0
-#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */
-/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */
-#define GMAC_LFFE_LFER_Pos 0
-#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */
-/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */
-#define GMAC_RSE_RXSE_Pos 0
-#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */
-/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */
-#define GMAC_AE_AER_Pos 0
-#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */
-/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */
-#define GMAC_RRE_RXRER_Pos 0
-#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */
-/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */
-#define GMAC_ROE_RXOVR_Pos 0
-#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */
-/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */
-#define GMAC_IHCE_HCKER_Pos 0
-#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */
-/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */
-#define GMAC_TCE_TCKER_Pos 0
-#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */
-/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */
-#define GMAC_UCE_UCKER_Pos 0
-#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */
-/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */
-#define GMAC_TSSS_VTS_Pos 0
-#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */
-#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))
-/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */
-#define GMAC_TSSN_VTN_Pos 0
-#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */
-#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))
-/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */
-#define GMAC_TS_TCS_Pos 0
-#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */
-#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))
-/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */
-#define GMAC_TN_TNS_Pos 0
-#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */
-#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))
-/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */
-#define GMAC_TA_ITDT_Pos 0
-#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */
-#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))
-#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */
-/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */
-#define GMAC_TI_CNS_Pos 0
-#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */
-#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))
-#define GMAC_TI_ACNS_Pos 8
-#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */
-#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))
-#define GMAC_TI_NIT_Pos 16
-#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */
-#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))
-/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */
-#define GMAC_EFTS_RUD_Pos 0
-#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */
-/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */
-#define GMAC_EFTN_RUD_Pos 0
-#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */
-/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */
-#define GMAC_EFRS_RUD_Pos 0
-#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */
-/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */
-#define GMAC_EFRN_RUD_Pos 0
-#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */
-/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */
-#define GMAC_PEFTS_RUD_Pos 0
-#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */
-/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */
-#define GMAC_PEFTN_RUD_Pos 0
-#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */
-/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */
-#define GMAC_PEFRS_RUD_Pos 0
-#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */
-/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */
-#define GMAC_PEFRN_RUD_Pos 0
-#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */
-/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */
-#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */
-#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */
-#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */
-#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */
-#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */
-/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */
-#define GMAC_TBQBAPQ_TXBQBA_Pos 2
-#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */
-#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))
-/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */
-#define GMAC_RBQBAPQ_RXBQBA_Pos 2
-#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */
-#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))
-/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */
-#define GMAC_RBSRPQ_RBS_Pos 0
-#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */
-#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))
-/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */
-#define GMAC_ST1RPQ_QNB_Pos 0
-#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */
-#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))
-#define GMAC_ST1RPQ_DSTCM_Pos 4
-#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */
-#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))
-#define GMAC_ST1RPQ_UDPM_Pos 12
-#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */
-#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))
-#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */
-#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */
-/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */
-#define GMAC_ST2RPQ_QNB_Pos 0
-#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */
-#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))
-#define GMAC_ST2RPQ_VLANP_Pos 4
-#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */
-#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))
-#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */
-/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */
-#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */
-#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */
-#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */
-#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */
-#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */
-/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */
-#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */
-#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */
-#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */
-#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */
-#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */
-/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */
-#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */
-#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */
-#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */
-#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */
-#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */
-#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */
-
-/*@}*/
-
-
-#endif /* _SAM4E_GMAC_COMPONENT_ */
+/**\r
+ * \file\r
+ *\r
+ * Copyright (c) 2012 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef _SAM4E_GMAC_COMPONENT_\r
+#define _SAM4E_GMAC_COMPONENT_\r
+\r
+/* ============================================================================= */\r
+/** SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */\r
+/* ============================================================================= */\r
+/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */\r
+/*@{*/\r
+\r
+#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))\r
+/** \brief GmacSa hardware registers */\r
+typedef struct {\r
+ RwReg GMAC_SAB; /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */\r
+ RwReg GMAC_SAT; /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */\r
+} GmacSa;\r
+/** \brief Gmac hardware registers */\r
+#define GMACSA_NUMBER 4\r
+typedef struct {\r
+ RwReg GMAC_NCR; /**< \brief (Gmac Offset: 0x000) Network Control Register */\r
+ RwReg GMAC_NCFGR; /**< \brief (Gmac Offset: 0x004) Network Configuration Register */\r
+ RoReg GMAC_NSR; /**< \brief (Gmac Offset: 0x008) Network Status Register */\r
+ RwReg GMAC_UR; /**< \brief (Gmac Offset: 0x00C) User Register */\r
+ RwReg GMAC_DCFGR; /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */\r
+ RwReg GMAC_TSR; /**< \brief (Gmac Offset: 0x014) Transmit Status Register */\r
+ RwReg GMAC_RBQB; /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */\r
+ RwReg GMAC_TBQB; /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */\r
+ RwReg GMAC_RSR; /**< \brief (Gmac Offset: 0x020) Receive Status Register */\r
+ RoReg GMAC_ISR; /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */\r
+ WoReg GMAC_IER; /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */\r
+ WoReg GMAC_IDR; /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */\r
+ RoReg GMAC_IMR; /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */\r
+ RwReg GMAC_MAN; /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */\r
+ RoReg GMAC_RPQ; /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */\r
+ RwReg GMAC_TPQ; /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */\r
+ RwReg GMAC_TPSF; /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */\r
+ RwReg GMAC_RPSF; /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */\r
+ RoReg Reserved1[14];\r
+ RwReg GMAC_HRB; /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */\r
+ RwReg GMAC_HRT; /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */\r
+ GmacSa GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */\r
+ RwReg GMAC_TIDM[4]; /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */\r
+ RwReg GMAC_WOL; /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */\r
+ RwReg GMAC_IPGS; /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */\r
+ RwReg GMAC_SVLAN; /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */\r
+ RwReg GMAC_TPFCP; /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */\r
+ RwReg GMAC_SAMB1; /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */\r
+ RwReg GMAC_SAMT1; /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */\r
+ RoReg Reserved2[12];\r
+ RoReg GMAC_OTLO; /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */\r
+ RoReg GMAC_OTHI; /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */\r
+ RoReg GMAC_FT; /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */\r
+ RoReg GMAC_BCFT; /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */\r
+ RoReg GMAC_MFT; /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */\r
+ RoReg GMAC_PFT; /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */\r
+ RoReg GMAC_BFT64; /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TBFT127; /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TBFT255; /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TBFT511; /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TBFT1023; /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TBFT1518; /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */\r
+ RoReg GMAC_GTBFT1518; /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */\r
+ RoReg GMAC_TUR; /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */\r
+ RoReg GMAC_SCF; /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */\r
+ RoReg GMAC_MCF; /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */\r
+ RoReg GMAC_EC; /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */\r
+ RoReg GMAC_LC; /**< \brief (Gmac Offset: 0x144) Late Collisions Register */\r
+ RoReg GMAC_DTF; /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */\r
+ RoReg GMAC_CSE; /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */\r
+ RoReg GMAC_ORLO; /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */\r
+ RoReg GMAC_ORHI; /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */\r
+ RoReg GMAC_FR; /**< \brief (Gmac Offset: 0x158) Frames Received Register */\r
+ RoReg GMAC_BCFR; /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */\r
+ RoReg GMAC_MFR; /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */\r
+ RoReg GMAC_PFR; /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */\r
+ RoReg GMAC_BFR64; /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */\r
+ RoReg GMAC_TBFR127; /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */\r
+ RoReg GMAC_TBFR255; /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */\r
+ RoReg GMAC_TBFR511; /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */\r
+ RoReg GMAC_TBFR1023; /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */\r
+ RoReg GMAC_TBFR1518; /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */\r
+ RoReg GMAC_TMXBFR; /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */\r
+ RoReg GMAC_UFR; /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */\r
+ RoReg GMAC_OFR; /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */\r
+ RoReg GMAC_JR; /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */\r
+ RoReg GMAC_FCSE; /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */\r
+ RoReg GMAC_LFFE; /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */\r
+ RoReg GMAC_RSE; /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */\r
+ RoReg GMAC_AE; /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */\r
+ RoReg GMAC_RRE; /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */\r
+ RoReg GMAC_ROE; /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */\r
+ RoReg GMAC_IHCE; /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */\r
+ RoReg GMAC_TCE; /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */\r
+ RoReg GMAC_UCE; /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */\r
+ RoReg Reserved3[5];\r
+ RwReg GMAC_TSSS; /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */\r
+ RwReg GMAC_TSSN; /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */\r
+ RwReg GMAC_TS; /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */\r
+ RwReg GMAC_TN; /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */\r
+ WoReg GMAC_TA; /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */\r
+ RwReg GMAC_TI; /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */\r
+ RoReg GMAC_EFTS; /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */\r
+ RoReg GMAC_EFTN; /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */\r
+ RoReg GMAC_EFRS; /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */\r
+ RoReg GMAC_EFRN; /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */\r
+ RoReg GMAC_PEFTS; /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */\r
+ RoReg GMAC_PEFTN; /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */\r
+ RoReg GMAC_PEFRS; /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */\r
+ RoReg GMAC_PEFRN; /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */\r
+ RoReg Reserved4[128];\r
+ RoReg GMAC_ISRPQ[7]; /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */\r
+ RoReg Reserved5[9];\r
+ RwReg GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */\r
+ RoReg Reserved6[9];\r
+ RwReg GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */\r
+ RoReg Reserved7[1];\r
+ RwReg GMAC_RBSRPQ[7]; /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */\r
+ RoReg Reserved8[17];\r
+ RwReg GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */\r
+ RwReg GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */\r
+ RoReg Reserved9[32];\r
+ WoReg GMAC_IERPQ[7]; /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */\r
+ RoReg Reserved10[1];\r
+ WoReg GMAC_IDRPQ[7]; /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */\r
+ RoReg Reserved11[1];\r
+ RwReg GMAC_IMRPQ[7]; /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */\r
+} Gmac;\r
+#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */\r
+/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */\r
+#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */\r
+#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */\r
+#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */\r
+#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */\r
+#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */\r
+#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */\r
+#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */\r
+#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */\r
+#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */\r
+#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */\r
+#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */\r
+#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */\r
+#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */\r
+#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */\r
+#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */\r
+#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */\r
+#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */\r
+#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */\r
+/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */\r
+#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */\r
+#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */\r
+#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */\r
+#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */\r
+#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */\r
+#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */\r
+#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */\r
+#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */\r
+#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */\r
+#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */\r
+#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */\r
+#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */\r
+#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */\r
+#define GMAC_NCFGR_RXBUFO_Pos 14\r
+#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */\r
+#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))\r
+#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */\r
+#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */\r
+#define GMAC_NCFGR_CLK_Pos 18\r
+#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */\r
+#define GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */\r
+#define GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */\r
+#define GMAC_NCFGR_DBW_Pos 21\r
+#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */\r
+#define GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */\r
+#define GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */\r
+#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */\r
+#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */\r
+#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */\r
+#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */\r
+#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */\r
+#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */\r
+#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */\r
+/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */\r
+#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */\r
+#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */\r
+/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */\r
+#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */\r
+#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */\r
+#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */\r
+/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */\r
+#define GMAC_DCFGR_FBLDO_Pos 0\r
+#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */\r
+#define GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */\r
+#define GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */\r
+#define GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */\r
+#define GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */\r
+#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */\r
+#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */\r
+#define GMAC_DCFGR_RXBMS_Pos 8\r
+#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */\r
+#define GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */\r
+#define GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */\r
+#define GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */\r
+#define GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */\r
+#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */\r
+#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */\r
+#define GMAC_DCFGR_DRBS_Pos 16\r
+#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */\r
+#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))\r
+#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */\r
+/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */\r
+#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */\r
+#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */\r
+#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */\r
+#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */\r
+#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */\r
+#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */\r
+#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */\r
+#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */\r
+/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */\r
+#define GMAC_RBQB_ADDR_Pos 2\r
+#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */\r
+#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))\r
+/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */\r
+#define GMAC_TBQB_ADDR_Pos 2\r
+#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))\r
+/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */\r
+#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */\r
+#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */\r
+#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */\r
+#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */\r
+/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */\r
+#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */\r
+#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */\r
+#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */\r
+#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */\r
+#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */\r
+#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */\r
+#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */\r
+#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */\r
+#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */\r
+#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */\r
+#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */\r
+#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */\r
+#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */\r
+#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */\r
+#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */\r
+#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */\r
+#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */\r
+#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */\r
+#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */\r
+#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */\r
+/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */\r
+#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */\r
+#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */\r
+#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */\r
+#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */\r
+#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */\r
+#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */\r
+#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */\r
+#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */\r
+#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */\r
+#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */\r
+#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */\r
+#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */\r
+#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */\r
+#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */\r
+#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */\r
+#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */\r
+#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */\r
+#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */\r
+#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */\r
+#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */\r
+/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */\r
+#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */\r
+#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */\r
+#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */\r
+#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */\r
+#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */\r
+#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */\r
+#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */\r
+#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */\r
+#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */\r
+#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */\r
+#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */\r
+#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */\r
+#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */\r
+#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */\r
+#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */\r
+#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */\r
+#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */\r
+#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */\r
+#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */\r
+#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */\r
+/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */\r
+#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */\r
+#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */\r
+#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */\r
+#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */\r
+#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */\r
+#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */\r
+#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */\r
+#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */\r
+#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */\r
+#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */\r
+#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */\r
+#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */\r
+#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */\r
+#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */\r
+#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */\r
+#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */\r
+#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */\r
+#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */\r
+/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */\r
+#define GMAC_MAN_DATA_Pos 0\r
+#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */\r
+#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))\r
+#define GMAC_MAN_WTN_Pos 16\r
+#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */\r
+#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))\r
+#define GMAC_MAN_REGA_Pos 18\r
+#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */\r
+#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))\r
+#define GMAC_MAN_PHYA_Pos 23\r
+#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */\r
+#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))\r
+#define GMAC_MAN_OP_Pos 28\r
+#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */\r
+#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))\r
+#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */\r
+#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */\r
+/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */\r
+#define GMAC_RPQ_RPQ_Pos 0\r
+#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */\r
+/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */\r
+#define GMAC_TPQ_TPQ_Pos 0\r
+#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */\r
+#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))\r
+/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */\r
+#define GMAC_TPSF_TPB1ADR_Pos 0\r
+#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */\r
+#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))\r
+#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */\r
+/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */\r
+#define GMAC_RPSF_RPB1ADR_Pos 0\r
+#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */\r
+#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))\r
+#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */\r
+/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */\r
+#define GMAC_HRB_ADDR_Pos 0\r
+#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */\r
+#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))\r
+/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */\r
+#define GMAC_HRT_ADDR_Pos 0\r
+#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */\r
+#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))\r
+/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB1_ADDR_Pos 0\r
+#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */\r
+#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))\r
+/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */\r
+#define GMAC_SAT1_ADDR_Pos 0\r
+#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */\r
+#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))\r
+/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB2_ADDR_Pos 0\r
+#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */\r
+#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))\r
+/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */\r
+#define GMAC_SAT2_ADDR_Pos 0\r
+#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */\r
+#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))\r
+/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB3_ADDR_Pos 0\r
+#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */\r
+#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))\r
+/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */\r
+#define GMAC_SAT3_ADDR_Pos 0\r
+#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */\r
+#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))\r
+/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB4_ADDR_Pos 0\r
+#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */\r
+#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))\r
+/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */\r
+#define GMAC_SAT4_ADDR_Pos 0\r
+#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */\r
+#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))\r
+/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */\r
+#define GMAC_TIDM_TID_Pos 0\r
+#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */\r
+#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))\r
+/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */\r
+#define GMAC_WOL_IP_Pos 0\r
+#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))\r
+#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */\r
+#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */\r
+#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */\r
+/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */\r
+#define GMAC_IPGS_FL_Pos 0\r
+#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */\r
+#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))\r
+/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */\r
+#define GMAC_SVLAN_VLAN_TYPE_Pos 0\r
+#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */\r
+#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))\r
+#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */\r
+/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */\r
+#define GMAC_TPFCP_PEV_Pos 0\r
+#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */\r
+#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))\r
+#define GMAC_TPFCP_PQ_Pos 8\r
+#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */\r
+#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))\r
+/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */\r
+#define GMAC_SAMB1_ADDR_Pos 0\r
+#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */\r
+#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))\r
+/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */\r
+#define GMAC_SAMT1_ADDR_Pos 0\r
+#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */\r
+#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))\r
+/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */\r
+#define GMAC_OTLO_TXO_Pos 0\r
+#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */\r
+/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */\r
+#define GMAC_OTHI_TXO_Pos 0\r
+#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */\r
+/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */\r
+#define GMAC_FT_FTX_Pos 0\r
+#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */\r
+/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */\r
+#define GMAC_BCFT_BFTX_Pos 0\r
+#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */\r
+/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */\r
+#define GMAC_MFT_MFTX_Pos 0\r
+#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */\r
+/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */\r
+#define GMAC_PFT_PFTX_Pos 0\r
+#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */\r
+/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */\r
+#define GMAC_BFT64_NFTX_Pos 0\r
+#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT127_NFTX_Pos 0\r
+#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT255_NFTX_Pos 0\r
+#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT511_NFTX_Pos 0\r
+#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1023_NFTX_Pos 0\r
+#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1518_NFTX_Pos 0\r
+#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_GTBFT1518_NFTX_Pos 0\r
+#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */\r
+#define GMAC_TUR_TXUNR_Pos 0\r
+#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */\r
+/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */\r
+#define GMAC_SCF_SCOL_Pos 0\r
+#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */\r
+/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */\r
+#define GMAC_MCF_MCOL_Pos 0\r
+#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */\r
+/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */\r
+#define GMAC_EC_XCOL_Pos 0\r
+#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */\r
+/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */\r
+#define GMAC_LC_LCOL_Pos 0\r
+#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */\r
+/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */\r
+#define GMAC_DTF_DEFT_Pos 0\r
+#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */\r
+/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */\r
+#define GMAC_CSE_CSR_Pos 0\r
+#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */\r
+/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */\r
+#define GMAC_ORLO_RXO_Pos 0\r
+#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */\r
+/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */\r
+#define GMAC_ORHI_RXO_Pos 0\r
+#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */\r
+/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */\r
+#define GMAC_FR_FRX_Pos 0\r
+#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */\r
+/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */\r
+#define GMAC_BCFR_BFRX_Pos 0\r
+#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */\r
+/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */\r
+#define GMAC_MFR_MFRX_Pos 0\r
+#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */\r
+/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */\r
+#define GMAC_PFR_PFRX_Pos 0\r
+#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */\r
+/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */\r
+#define GMAC_BFR64_NFRX_Pos 0\r
+#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR127_NFRX_Pos 0\r
+#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR255_NFRX_Pos 0\r
+#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */\r
+#define GMAC_TBFR511_NFRX_Pos 0\r
+#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1023_NFRX_Pos 0\r
+#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1518_NFRX_Pos 0\r
+#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */\r
+/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */\r
+#define GMAC_TMXBFR_NFRX_Pos 0\r
+#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */\r
+/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */\r
+#define GMAC_UFR_UFRX_Pos 0\r
+#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */\r
+/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */\r
+#define GMAC_OFR_OFRX_Pos 0\r
+#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */\r
+/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */\r
+#define GMAC_JR_JRX_Pos 0\r
+#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */\r
+/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */\r
+#define GMAC_FCSE_FCKR_Pos 0\r
+#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */\r
+/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */\r
+#define GMAC_LFFE_LFER_Pos 0\r
+#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */\r
+/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */\r
+#define GMAC_RSE_RXSE_Pos 0\r
+#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */\r
+/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */\r
+#define GMAC_AE_AER_Pos 0\r
+#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */\r
+/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */\r
+#define GMAC_RRE_RXRER_Pos 0\r
+#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */\r
+/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */\r
+#define GMAC_ROE_RXOVR_Pos 0\r
+#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */\r
+/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */\r
+#define GMAC_IHCE_HCKER_Pos 0\r
+#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */\r
+/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */\r
+#define GMAC_TCE_TCKER_Pos 0\r
+#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */\r
+/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */\r
+#define GMAC_UCE_UCKER_Pos 0\r
+#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */\r
+/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */\r
+#define GMAC_TSSS_VTS_Pos 0\r
+#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */\r
+#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))\r
+/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */\r
+#define GMAC_TSSN_VTN_Pos 0\r
+#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */\r
+#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))\r
+/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */\r
+#define GMAC_TS_TCS_Pos 0\r
+#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */\r
+#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))\r
+/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */\r
+#define GMAC_TN_TNS_Pos 0\r
+#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */\r
+#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))\r
+/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */\r
+#define GMAC_TA_ITDT_Pos 0\r
+#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */\r
+#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))\r
+#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */\r
+/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */\r
+#define GMAC_TI_CNS_Pos 0\r
+#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */\r
+#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))\r
+#define GMAC_TI_ACNS_Pos 8\r
+#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */\r
+#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))\r
+#define GMAC_TI_NIT_Pos 16\r
+#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */\r
+#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))\r
+/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */\r
+#define GMAC_EFTS_RUD_Pos 0\r
+#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */\r
+/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_EFTN_RUD_Pos 0\r
+#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */\r
+/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */\r
+#define GMAC_EFRS_RUD_Pos 0\r
+#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */\r
+/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */\r
+#define GMAC_EFRN_RUD_Pos 0\r
+#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */\r
+/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */\r
+#define GMAC_PEFTS_RUD_Pos 0\r
+#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */\r
+/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_PEFTN_RUD_Pos 0\r
+#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */\r
+/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */\r
+#define GMAC_PEFRS_RUD_Pos 0\r
+#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */\r
+/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */\r
+#define GMAC_PEFRN_RUD_Pos 0\r
+#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */\r
+/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */\r
+#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */\r
+#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */\r
+#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */\r
+#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */\r
+#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_TBQBAPQ_TXBQBA_Pos 2\r
+#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))\r
+/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_RBQBAPQ_RXBQBA_Pos 2\r
+#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */\r
+#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))\r
+/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */\r
+#define GMAC_RBSRPQ_RBS_Pos 0\r
+#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */\r
+#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))\r
+/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */\r
+#define GMAC_ST1RPQ_QNB_Pos 0\r
+#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))\r
+#define GMAC_ST1RPQ_DSTCM_Pos 4\r
+#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */\r
+#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))\r
+#define GMAC_ST1RPQ_UDPM_Pos 12\r
+#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */\r
+#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))\r
+#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */\r
+#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */\r
+/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */\r
+#define GMAC_ST2RPQ_QNB_Pos 0\r
+#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))\r
+#define GMAC_ST2RPQ_VLANP_Pos 4\r
+#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */\r
+#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))\r
+#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */\r
+/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */\r
+#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */\r
+#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */\r
+#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */\r
+#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */\r
+#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */\r
+#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */\r
+#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */\r
+#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */\r
+#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */\r
+#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */\r
+#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */\r
+#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */\r
+#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */\r
+#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */\r
+\r
+/*@}*/\r
+\r
+\r
+#endif /* _SAM4E_GMAC_COMPONENT_ */\r
- /**
- * \file
- *
- * \brief API driver for KSZ8051MNL PHY component.
- *
- * Copyright (c) 2013 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
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "FreeRTOSIPConfig.h"
-
-#include "ethernet_phy.h"
-#include "instance/gmac.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
- *
- * Driver for the ksz8051mnl component. This driver provides access to the main
- * features of the PHY.
- *
- * \section dependencies Dependencies
- * This driver depends on the following modules:
- * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
- *
- * @{
- */
-
-SPhyProps phyProps;
-
-/* Max PHY number */
-#define ETH_PHY_MAX_ADDR 31
-
-/* Ethernet PHY operation max retry count */
-#define ETH_PHY_RETRY_MAX 1000000
-
-/* Ethernet PHY operation timeout */
-#define ETH_PHY_TIMEOUT 10
-
-/**
- * \brief Find a valid PHY Address ( from addrStart to 31 ).
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_start_addr Start address of the PHY to be searched.
- *
- * \return 0xFF when no valid PHY address is found.
- */
-int ethernet_phy_addr = 0;
-static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
- uint8_t uc_start_addr)
-{
- uint32_t ul_value = 0;
- uint8_t uc_cnt;
- uint8_t uc_phy_address = uc_phy_addr;
-
- gmac_enable_management(p_gmac, true);
-/*
-#define GMII_OUI_MSB 0x0022
-#define GMII_OUI_LSB 0x05
-
-PHYID1 = 0x0022
-PHYID2 = 0x1550
-0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
-*/
- /* Check the current PHY address */
- gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
-
- /* Find another one */
- if (ul_value != GMII_OUI_MSB) {
- ethernet_phy_addr = 0xFF;
- for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
- uc_phy_address = (uc_phy_address + 1) & 0x1F;
- ul_value = 0;
- gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
- if (ul_value == GMII_OUI_MSB) {
- ethernet_phy_addr = uc_phy_address;
- break;
- }
- }
- }
-
- gmac_enable_management(p_gmac, false);
-
- if (ethernet_phy_addr != 0xFF) {
- gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
- }
- return ethernet_phy_addr;
-}
-
-
-/**
- * \brief Perform a HW initialization to the PHY and set up clocks.
- *
- * This should be called only once to initialize the PHY pre-settings.
- * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
- * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
- * The RXDV pin is used to select test mode on reset (pulled up for test mode).
- * The above pins should be predefined for corresponding settings in resetPins.
- * The GMAC peripheral pins are configured after the reset is done.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param ul_mck GMAC MCK.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
-{
- uint8_t uc_rc = GMAC_TIMEOUT;
- uint8_t uc_phy;
-
- ethernet_phy_reset(GMAC,uc_phy_addr);
-
- /* Configure GMAC runtime clock */
- uc_rc = gmac_set_mdc_clock(p_gmac, mck);
- if (uc_rc != GMAC_OK) {
- return 0;
- }
-
- /* Check PHY Address */
- uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
- if (uc_phy == 0xFF) {
- return 0;
- }
- if (uc_phy != uc_phy_addr) {
- ethernet_phy_reset(p_gmac, uc_phy_addr);
- }
- phy_props.phy_chn = uc_phy;
- return uc_phy;
-}
-
-
-/**
- * \brief Get the Link & speed settings, and automatically set up the GMAC with the
- * settings.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
- uint8_t uc_apply_setting_flag)
-{
- uint32_t ul_stat1;
- uint32_t ul_stat2;
- uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
- uint8_t uc_rc = GMAC_TIMEOUT;
-
- gmac_enable_management(p_gmac, true);
-
- uc_phy_address = uc_phy_addr;
-
- uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
- if (uc_rc != GMAC_OK) {
- /* Disable PHY management and start the GMAC transfer */
- gmac_enable_management(p_gmac, false);
-
- return uc_rc;
- }
- if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
- /* Disable PHY management and start the GMAC transfer */
- gmac_enable_management(p_gmac, false);
-
- return GMAC_INVALID;
- }
-
- if (uc_apply_setting_flag == 0) {
- /* Disable PHY management and start the GMAC transfer */
- gmac_enable_management(p_gmac, false);
-
- return uc_rc;
- }
-
- /* Read advertisement */
- uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
-phy_props.phy_stat1 = ul_stat1;
-phy_props.phy_stat2 = ul_stat2;
- if (uc_rc != GMAC_OK) {
- /* Disable PHY management and start the GMAC transfer */
- gmac_enable_management(p_gmac, false);
-
- return uc_rc;
- }
-
- if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
- /* Set GMAC for 100BaseTX and Full Duplex */
- uc_speed = true;
- uc_fd = true;
- } else
- if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
- /* Set MII for 100BaseTX and Half Duplex */
- uc_speed = true;
- uc_fd = false;
- } else
- if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
- /* Set MII for 10BaseT and Full Duplex */
- uc_speed = false;
- uc_fd = true;
- } else
- if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
- /* Set MII for 10BaseT and Half Duplex */
- uc_speed = false;
- uc_fd = false;
- }
-
- gmac_set_speed(p_gmac, uc_speed);
- gmac_enable_full_duplex(p_gmac, uc_fd);
-
- /* Start the GMAC transfers */
- gmac_enable_management(p_gmac, false);
- return uc_rc;
-}
-
-PhyProps_t phy_props;
-
-/**
- * \brief Issue an auto negotiation of the PHY.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
- uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
- uint32_t ul_value;
- uint32_t ul_phy_anar;
- uint32_t ul_retry_count = 0;
- uint8_t uc_speed = 0;
- uint8_t uc_fd=0;
- uint8_t uc_rc = GMAC_TIMEOUT;
-
- gmac_enable_management(p_gmac, true);
-
- /* Set up control register */
- uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -1;
- return uc_rc;
- }
-
- ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
- ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
- ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
- uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -2;
- return uc_rc;
- }
-
- /*
- * Set the Auto_negotiation Advertisement Register.
- * MII advertising for Next page.
- * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
- */
- ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
- GMII_AN_IEEE_802_3;
- uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -3;
- return uc_rc;
- }
-
- /* Read & modify control register */
- uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -4;
- return uc_rc;
- }
-
- ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
- uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -5;
- return uc_rc;
- }
-
- /* Restart auto negotiation */
- ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
- ul_value &= ~(uint32_t)GMII_ISOLATE;
- uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -6;
- return uc_rc;
- }
-
- /* Check if auto negotiation is completed */
- while (1) {
- uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -7;
- return uc_rc;
- }
- /* Done successfully */
- if (ul_value & GMII_AUTONEG_COMP) {
- break;
- }
-
- /* Timeout check */
- if (ul_retry_max) {
- if (++ul_retry_count >= ul_retry_max) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -8;
- return GMAC_TIMEOUT;
- }
- }
- }
-
- /* Get the auto negotiate link partner base page */
- uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
- if (uc_rc != GMAC_OK) {
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -9;
- return uc_rc;
- }
-
-
- /* Set up the GMAC link speed */
- if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
- /* Set MII for 100BaseTX and Full Duplex */
- uc_speed = true;
- uc_fd = true;
- } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
- /* Set MII for 10BaseT and Full Duplex */
- uc_speed = false;
- uc_fd = true;
- } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
- /* Set MII for 100BaseTX and half Duplex */
- uc_speed = true;
- uc_fd = false;
- } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
- /* Set MII for 10BaseT and half Duplex */
- uc_speed = false;
- uc_fd = false;
- }
-
- gmac_set_speed(p_gmac, uc_speed);
- gmac_enable_full_duplex(p_gmac, uc_fd);
-
- /* Select Media Independent Interface type */
- gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
-
- gmac_enable_transmit(GMAC, true);
- gmac_enable_receive(GMAC, true);
-
- gmac_enable_management(p_gmac, false);
-phy_props.phy_result = 1;
- return uc_rc;
-}
-
-/**
- * \brief Issue a SW reset to reset all registers of the PHY.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
- uint32_t ul_bmcr = GMII_RESET;
- uint8_t uc_phy_address = uc_phy_addr;
- uint32_t ul_timeout = ETH_PHY_TIMEOUT;
- uint8_t uc_rc = GMAC_TIMEOUT;
-
- gmac_enable_management(p_gmac, true);
-
- ul_bmcr = GMII_RESET;
- gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
-
- do {
- gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
- ul_timeout--;
- } while ((ul_bmcr & GMII_RESET) && ul_timeout);
-
- gmac_enable_management(p_gmac, false);
-
- if (!ul_timeout) {
- uc_rc = GMAC_OK;
- }
-
- return (uc_rc);
-}
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \}
- */
+ /**\r
+ * \file\r
+ *\r
+ * \brief API driver for KSZ8051MNL PHY component.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "ethernet_phy.h"\r
+#include "instance/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)\r
+ *\r
+ * Driver for the ksz8051mnl component. This driver provides access to the main\r
+ * features of the PHY.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver depends on the following modules:\r
+ * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.\r
+ *\r
+ * @{\r
+ */\r
+\r
+SPhyProps phyProps;\r
+\r
+/* Max PHY number */\r
+#define ETH_PHY_MAX_ADDR 31\r
+\r
+/* Ethernet PHY operation max retry count */\r
+#define ETH_PHY_RETRY_MAX 1000000\r
+\r
+/* Ethernet PHY operation timeout */\r
+#define ETH_PHY_TIMEOUT 10\r
+\r
+/**\r
+ * \brief Find a valid PHY Address ( from addrStart to 31 ).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_start_addr Start address of the PHY to be searched.\r
+ *\r
+ * \return 0xFF when no valid PHY address is found.\r
+ */\r
+int ethernet_phy_addr = 0;\r
+static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+ uint8_t uc_start_addr)\r
+{\r
+ uint32_t ul_value = 0;\r
+ uint8_t uc_cnt;\r
+ uint8_t uc_phy_address = uc_phy_addr;\r
+\r
+ gmac_enable_management(p_gmac, true);\r
+/*\r
+#define GMII_OUI_MSB 0x0022\r
+#define GMII_OUI_LSB 0x05\r
+\r
+PHYID1 = 0x0022\r
+PHYID2 = 0x1550\r
+0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0\r
+*/\r
+ /* Check the current PHY address */\r
+ gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);\r
+\r
+ /* Find another one */\r
+ if (ul_value != GMII_OUI_MSB) {\r
+ ethernet_phy_addr = 0xFF;\r
+ for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {\r
+ uc_phy_address = (uc_phy_address + 1) & 0x1F;\r
+ ul_value = 0;\r
+ gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);\r
+ if (ul_value == GMII_OUI_MSB) {\r
+ ethernet_phy_addr = uc_phy_address;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ if (ethernet_phy_addr != 0xFF) {\r
+ gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);\r
+ }\r
+ return ethernet_phy_addr;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)\r
+{\r
+ uint8_t uc_rc = GMAC_TIMEOUT;\r
+ uint8_t uc_phy;\r
+\r
+ ethernet_phy_reset(GMAC,uc_phy_addr);\r
+\r
+ /* Configure GMAC runtime clock */\r
+ uc_rc = gmac_set_mdc_clock(p_gmac, mck);\r
+ if (uc_rc != GMAC_OK) {\r
+ return 0;\r
+ }\r
+\r
+ /* Check PHY Address */\r
+ uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);\r
+ if (uc_phy == 0xFF) {\r
+ return 0;\r
+ }\r
+ if (uc_phy != uc_phy_addr) {\r
+ ethernet_phy_reset(p_gmac, uc_phy_addr);\r
+ }\r
+ phy_props.phy_chn = uc_phy;\r
+ return uc_phy;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+ uint8_t uc_apply_setting_flag)\r
+{\r
+ uint32_t ul_stat1;\r
+ uint32_t ul_stat2;\r
+ uint8_t uc_phy_address, uc_speed = true, uc_fd = true;\r
+ uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+ gmac_enable_management(p_gmac, true);\r
+\r
+ uc_phy_address = uc_phy_addr;\r
+\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);\r
+ if (uc_rc != GMAC_OK) {\r
+ /* Disable PHY management and start the GMAC transfer */\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ return uc_rc;\r
+ }\r
+ if ((ul_stat1 & GMII_LINK_STATUS) == 0) {\r
+ /* Disable PHY management and start the GMAC transfer */\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ return GMAC_INVALID;\r
+ }\r
+\r
+ if (uc_apply_setting_flag == 0) {\r
+ /* Disable PHY management and start the GMAC transfer */\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ return uc_rc;\r
+ }\r
+\r
+ /* Read advertisement */\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);\r
+phy_props.phy_stat1 = ul_stat1;\r
+phy_props.phy_stat2 = ul_stat2;\r
+ if (uc_rc != GMAC_OK) {\r
+ /* Disable PHY management and start the GMAC transfer */\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ return uc_rc;\r
+ }\r
+\r
+ if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {\r
+ /* Set GMAC for 100BaseTX and Full Duplex */\r
+ uc_speed = true;\r
+ uc_fd = true;\r
+ } else\r
+ if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {\r
+ /* Set MII for 100BaseTX and Half Duplex */\r
+ uc_speed = true;\r
+ uc_fd = false;\r
+ } else\r
+ if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {\r
+ /* Set MII for 10BaseT and Full Duplex */\r
+ uc_speed = false;\r
+ uc_fd = true;\r
+ } else\r
+ if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {\r
+ /* Set MII for 10BaseT and Half Duplex */\r
+ uc_speed = false;\r
+ uc_fd = false;\r
+ }\r
+\r
+ gmac_set_speed(p_gmac, uc_speed);\r
+ gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+ /* Start the GMAC transfers */\r
+ gmac_enable_management(p_gmac, false);\r
+ return uc_rc;\r
+}\r
+\r
+PhyProps_t phy_props;\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+ uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;\r
+ uint32_t ul_value;\r
+ uint32_t ul_phy_anar;\r
+ uint32_t ul_retry_count = 0;\r
+ uint8_t uc_speed = 0;\r
+ uint8_t uc_fd=0;\r
+ uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+ gmac_enable_management(p_gmac, true);\r
+\r
+ /* Set up control register */\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -1;\r
+ return uc_rc;\r
+ }\r
+\r
+ ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */\r
+ ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);\r
+ ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */\r
+ uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -2;\r
+ return uc_rc;\r
+ }\r
+\r
+ /*\r
+ * Set the Auto_negotiation Advertisement Register.\r
+ * MII advertising for Next page.\r
+ * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.\r
+ */\r
+ ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |\r
+ GMII_AN_IEEE_802_3;\r
+ uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -3;\r
+ return uc_rc;\r
+ }\r
+\r
+ /* Read & modify control register */\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -4;\r
+ return uc_rc;\r
+ }\r
+\r
+ ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;\r
+ uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -5;\r
+ return uc_rc;\r
+ }\r
+\r
+ /* Restart auto negotiation */\r
+ ul_value |= (uint32_t)GMII_RESTART_AUTONEG;\r
+ ul_value &= ~(uint32_t)GMII_ISOLATE;\r
+ uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -6;\r
+ return uc_rc;\r
+ }\r
+\r
+ /* Check if auto negotiation is completed */\r
+ while (1) {\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -7;\r
+ return uc_rc;\r
+ }\r
+ /* Done successfully */\r
+ if (ul_value & GMII_AUTONEG_COMP) {\r
+ break;\r
+ }\r
+\r
+ /* Timeout check */\r
+ if (ul_retry_max) {\r
+ if (++ul_retry_count >= ul_retry_max) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -8;\r
+ return GMAC_TIMEOUT;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Get the auto negotiate link partner base page */\r
+ uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);\r
+ if (uc_rc != GMAC_OK) {\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -9;\r
+ return uc_rc;\r
+ }\r
+\r
+\r
+ /* Set up the GMAC link speed */\r
+ if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {\r
+ /* Set MII for 100BaseTX and Full Duplex */\r
+ uc_speed = true;\r
+ uc_fd = true;\r
+ } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {\r
+ /* Set MII for 10BaseT and Full Duplex */\r
+ uc_speed = false;\r
+ uc_fd = true;\r
+ } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {\r
+ /* Set MII for 100BaseTX and half Duplex */\r
+ uc_speed = true;\r
+ uc_fd = false;\r
+ } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {\r
+ /* Set MII for 10BaseT and half Duplex */\r
+ uc_speed = false;\r
+ uc_fd = false;\r
+ }\r
+\r
+ gmac_set_speed(p_gmac, uc_speed);\r
+ gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+ /* Select Media Independent Interface type */\r
+ gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);\r
+\r
+ gmac_enable_transmit(GMAC, true);\r
+ gmac_enable_receive(GMAC, true);\r
+\r
+ gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = 1;\r
+ return uc_rc;\r
+}\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+ uint32_t ul_bmcr = GMII_RESET;\r
+ uint8_t uc_phy_address = uc_phy_addr;\r
+ uint32_t ul_timeout = ETH_PHY_TIMEOUT;\r
+ uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+ gmac_enable_management(p_gmac, true);\r
+\r
+ ul_bmcr = GMII_RESET;\r
+ gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);\r
+\r
+ do {\r
+ gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);\r
+ ul_timeout--;\r
+ } while ((ul_bmcr & GMII_RESET) && ul_timeout);\r
+\r
+ gmac_enable_management(p_gmac, false);\r
+\r
+ if (!ul_timeout) {\r
+ uc_rc = GMAC_OK;\r
+ }\r
+\r
+ return (uc_rc);\r
+}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \}\r
+ */\r
-/**
- * \file
- *
- * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
- *
- * Copyright (c) 2013 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
- *
- */
-
-#ifndef ETHERNET_PHY_H_INCLUDED
-#define ETHERNET_PHY_H_INCLUDED
-
-#include "compiler.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// IEEE defined Registers
-#define GMII_BMCR 0x00 // Basic Control
-#define GMII_BMSR 0x01 // Basic Status
-#define GMII_PHYID1 0x02 // PHY Idendifier 1
-#define GMII_PHYID2 0x03 // PHY Idendifier 2
-#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement
-#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability
-#define GMII_ANER 0x06 // Auto-negotiation Expansion
-#define GMII_ANNPR 0x07 // Auto-negotiation Next Page
-#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability
-//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved
-//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved
-#define GMII_AFECR1 0x11 // AFE Control 1
-//#define GMII_ERDWR 12 // Extend Register - Data Write Register
-//#define GMII_ERDRR 13 // Extend Register - Data Read Register
-//14 reserved
-#define GMII_RXERCR 0x15 // RXER Counter
-
- #define PHY_REG_01_BMSR 0x01 // Basic mode status register
- #define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
- #define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
- #define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
- #define PHY_REG_05_LPA 0x05 // Link partner ability reg
- #define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
- #define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
- #define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
-
- #define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register
- #define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register
- #define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register
- #define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED
- #define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register
- #define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register
- #define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register
- #define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register
- #define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register
- #define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register
- #define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register
- #define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register
- #define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control
- #define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED
- #define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register
- #define PHY_REG_1E_RESERVED3 0x1E //
- #define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED
-
- #define PHY_REG_1E_PHYCR_1 0x1E //
- #define PHY_REG_1F_PHYCR_2 0x1F //
-
- #define PHY_SPEED_10 1
- #define PHY_SPEED_100 2
- #define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)
-
- #define PHY_MDIX_DIRECT 1
- #define PHY_MDIX_CROSSED 2
- #define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
-
- #define PHY_DUPLEX_HALF 1
- #define PHY_DUPLEX_FULL 2
- #define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
-
- typedef struct _SPhyProps {
- unsigned char speed;
- unsigned char mdix;
- unsigned char duplex;
- unsigned char spare;
- } SPhyProps;
-
- const char *phyPrintable (const SPhyProps *apProps);
-
- extern SPhyProps phyProps;
-
-#define GMII_OMSOR 0x16 // Operation Mode Strap Override
-#define GMII_OMSSR 0x17 // Operation Mode Strap Status
-#define GMII_ECR 0x18 // Expanded Control
-//#define GMII_DPPSR 19 // Digital PMA/PCS Status
-//20 reserved
-//#define GMII_RXERCR 21 // RXER Counter Register
-//22-26 reserved
-#define GMII_ICSR 0x1B // Interrupt Control/Status
-//#define GMII_DDC1R 28 // Digital Debug Control 1 Register
-#define GMII_LCSR 0x1D // LinkMD Control/Status
-
-//29-30 reserved
-#define GMII_PCR1 0x1E // PHY Control 1
-#define GMII_PCR2 0x1F // PHY Control 2
-
-/*
-//Extend Registers
-#define GMII_CCR 256 // Common Control Register
-#define GMII_SSR 257 // Strap Status Register
-#define GMII_OMSOR 258 // Operation Mode Strap Override Register
-#define GMII_OMSSR 259 // Operation Mode Strap Status Register
-#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register
-#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register
-#define GMII_ATR 263 // Analog Test Register
-*/
-
-
-// Bit definitions: GMII_BMCR 0x00 Basic Control
-#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
-#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
-#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps
-#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
-#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
-#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
-#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
-#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
-#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test
-//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved
-// Reserved 6 to 0 // Read as 0, ignore on write
-
-// Bit definitions: GMII_BMSR 0x01 Basic Status
-#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
-#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
-#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
-#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
-#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
-// Reserved 10 to79 // Read as 0, ignore on write
-//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
-// Reserved 7
-#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
-#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
-#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
-#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
-#define GMII_LINK_STATUS (1 << 2) // Link Status
-#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
-#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
-
-
-// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
-// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
-#define GMII_LSB_MASK 0x3F
-#define GMII_OUI_MSB 0x0022
-#define GMII_OUI_LSB 0x05
-
-
-// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement
-// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
-#define GMII_NP (1 << 15) // Next page Indication
-// Reserved 7
-#define GMII_RF (1 << 13) // Remote Fault
-// Reserved 12 // Write as 0, ignore on read
-#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
- // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
-#define GMII_100T4 (1 << 9) // 100BASE-T4 Support
-#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
-#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support
-#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
-#define GMII_10_HDX (1 << 5) // 10BASE-T Support
-// Selector 4 to 0 // Protocol Selection Bits
-#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3
-
-
-// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
-// Reserved 15 to 5 // Read as 0, ignore on write
-#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault
-#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able
-#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able
-#define GMII_PAGE_RX (1 << 1) // New Page Received
-#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able
-
-/**
- * \brief Perform a HW initialization to the PHY and set up clocks.
- *
- * This should be called only once to initialize the PHY pre-settings.
- * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
- * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
- * The RXDV pin is used to select test mode on reset (pulled up for test mode).
- * The above pins should be predefined for corresponding settings in resetPins.
- * The GMAC peripheral pins are configured after the reset is done.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param ul_mck GMAC MCK.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
-
-
-/**
- * \brief Get the Link & speed settings, and automatically set up the GMAC with the
- * settings.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
- uint8_t uc_apply_setting_flag);
-
-
-/**
- * \brief Issue an auto negotiation of the PHY.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
-
-/**
- * \brief Issue a SW reset to reset all registers of the PHY.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
-
-typedef struct xPHY_PROPS {
- signed char phy_result;
- uint32_t phy_params;
- uint32_t phy_stat1;
- uint32_t phy_stat2;
- unsigned char phy_chn;
-} PhyProps_t;
-extern PhyProps_t phy_props;
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */
-
+/**\r
+ * \file\r
+ *\r
+ * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef ETHERNET_PHY_H_INCLUDED\r
+#define ETHERNET_PHY_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+// IEEE defined Registers\r
+#define GMII_BMCR 0x00 // Basic Control\r
+#define GMII_BMSR 0x01 // Basic Status\r
+#define GMII_PHYID1 0x02 // PHY Idendifier 1\r
+#define GMII_PHYID2 0x03 // PHY Idendifier 2\r
+#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement\r
+#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability\r
+#define GMII_ANER 0x06 // Auto-negotiation Expansion\r
+#define GMII_ANNPR 0x07 // Auto-negotiation Next Page\r
+#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability\r
+//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved\r
+//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved\r
+#define GMII_AFECR1 0x11 // AFE Control 1\r
+//#define GMII_ERDWR 12 // Extend Register - Data Write Register\r
+//#define GMII_ERDRR 13 // Extend Register - Data Read Register\r
+//14 reserved\r
+#define GMII_RXERCR 0x15 // RXER Counter\r
+\r
+ #define PHY_REG_01_BMSR 0x01 // Basic mode status register\r
+ #define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1\r
+ #define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2\r
+ #define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg\r
+ #define PHY_REG_05_LPA 0x05 // Link partner ability reg\r
+ #define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register\r
+ #define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX\r
+ #define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED\r
+\r
+ #define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register\r
+ #define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register\r
+ #define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register\r
+ #define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED\r
+ #define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register\r
+ #define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register\r
+ #define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register\r
+ #define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register\r
+ #define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register\r
+ #define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register\r
+ #define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register\r
+ #define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register\r
+ #define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control\r
+ #define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED\r
+ #define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register\r
+ #define PHY_REG_1E_RESERVED3 0x1E //\r
+ #define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED\r
+\r
+ #define PHY_REG_1E_PHYCR_1 0x1E //\r
+ #define PHY_REG_1F_PHYCR_2 0x1F //\r
+\r
+ #define PHY_SPEED_10 1\r
+ #define PHY_SPEED_100 2\r
+ #define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)\r
+\r
+ #define PHY_MDIX_DIRECT 1\r
+ #define PHY_MDIX_CROSSED 2\r
+ #define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)\r
+\r
+ #define PHY_DUPLEX_HALF 1\r
+ #define PHY_DUPLEX_FULL 2\r
+ #define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)\r
+\r
+ typedef struct _SPhyProps {\r
+ unsigned char speed;\r
+ unsigned char mdix;\r
+ unsigned char duplex;\r
+ unsigned char spare;\r
+ } SPhyProps;\r
+\r
+ const char *phyPrintable (const SPhyProps *apProps);\r
+\r
+ extern SPhyProps phyProps;\r
+\r
+#define GMII_OMSOR 0x16 // Operation Mode Strap Override\r
+#define GMII_OMSSR 0x17 // Operation Mode Strap Status\r
+#define GMII_ECR 0x18 // Expanded Control\r
+//#define GMII_DPPSR 19 // Digital PMA/PCS Status\r
+//20 reserved\r
+//#define GMII_RXERCR 21 // RXER Counter Register\r
+//22-26 reserved\r
+#define GMII_ICSR 0x1B // Interrupt Control/Status\r
+//#define GMII_DDC1R 28 // Digital Debug Control 1 Register\r
+#define GMII_LCSR 0x1D // LinkMD Control/Status\r
+\r
+//29-30 reserved\r
+#define GMII_PCR1 0x1E // PHY Control 1\r
+#define GMII_PCR2 0x1F // PHY Control 2\r
+\r
+/*\r
+//Extend Registers\r
+#define GMII_CCR 256 // Common Control Register\r
+#define GMII_SSR 257 // Strap Status Register\r
+#define GMII_OMSOR 258 // Operation Mode Strap Override Register\r
+#define GMII_OMSSR 259 // Operation Mode Strap Status Register\r
+#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register\r
+#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register\r
+#define GMII_ATR 263 // Analog Test Register\r
+*/\r
+\r
+\r
+// Bit definitions: GMII_BMCR 0x00 Basic Control\r
+#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation\r
+#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation\r
+#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps\r
+#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable\r
+#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation\r
+#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation\r
+#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation\r
+#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation\r
+#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test\r
+//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved\r
+// Reserved 6 to 0 // Read as 0, ignore on write\r
+\r
+// Bit definitions: GMII_BMSR 0x01 Basic Status\r
+#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable\r
+#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable\r
+#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable\r
+#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable\r
+#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable\r
+// Reserved 10 to79 // Read as 0, ignore on write\r
+//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15\r
+// Reserved 7\r
+#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression\r
+#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete\r
+#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault\r
+#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability\r
+#define GMII_LINK_STATUS (1 << 2) // Link Status\r
+#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect\r
+#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability\r
+\r
+\r
+// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1\r
+// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2\r
+#define GMII_LSB_MASK 0x3F\r
+#define GMII_OUI_MSB 0x0022\r
+#define GMII_OUI_LSB 0x05\r
+\r
+\r
+// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement\r
+// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability\r
+#define GMII_NP (1 << 15) // Next page Indication\r
+// Reserved 7\r
+#define GMII_RF (1 << 13) // Remote Fault\r
+// Reserved 12 // Write as 0, ignore on read\r
+#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)\r
+ // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)\r
+#define GMII_100T4 (1 << 9) // 100BASE-T4 Support\r
+#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support\r
+#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support\r
+#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support\r
+#define GMII_10_HDX (1 << 5) // 10BASE-T Support\r
+// Selector 4 to 0 // Protocol Selection Bits\r
+#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3\r
+\r
+\r
+// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion\r
+// Reserved 15 to 5 // Read as 0, ignore on write\r
+#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault\r
+#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able\r
+#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able\r
+#define GMII_PAGE_RX (1 << 1) // New Page Received\r
+#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+ uint8_t uc_apply_setting_flag);\r
+\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+typedef struct xPHY_PROPS {\r
+ signed char phy_result;\r
+ uint32_t phy_params;\r
+ uint32_t phy_stat1;\r
+ uint32_t phy_stat2;\r
+ unsigned char phy_chn;\r
+} PhyProps_t;\r
+extern PhyProps_t phy_props;\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */\r
+\r
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 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
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-
-#include "FreeRTOSIPConfig.h"
-
-#include "compiler.h"
-#include "instance/gmac.h"
-#include "ethernet_phy.h"
-
-/// @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
-/**
- * \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.
- *
- * @{
- */
-
-/** TX descriptor lists */
-COMPILER_ALIGNED(8)
-static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];
-#if( GMAC_USES_TX_CALLBACK != 0 )
-/** TX callback lists */
-static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];
-#endif
-/** RX descriptors lists */
-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.
- */
- COMPILER_ALIGNED(8)
- static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
-
-/** Receive Buffer */
-COMPILER_ALIGNED(8)
-static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];
-
-/**
- * GMAC device memory management struct.
- */
-typedef struct gmac_dev_mem {
- /* Pointer to allocated buffer for RX. The address should be 8-byte aligned
- and the size should be GMAC_RX_UNITSIZE * wRxSize. */
- uint8_t *p_rx_buffer;
- /* Pointer to allocated RX descriptor list. */
- gmac_rx_descriptor_t *p_rx_dscr;
- /* RX size, in number of registered units (RX descriptors). */
- /* Increased size from 16- to 32-bits, because it's more efficient */
- uint32_t us_rx_size;
- /* Pointer to allocated buffer for TX. The address should be 8-byte aligned
- and the size should be GMAC_TX_UNITSIZE * wTxSize. */
- uint8_t *p_tx_buffer;
- /* Pointer to allocated TX descriptor list. */
- gmac_tx_descriptor_t *p_tx_dscr;
- /* TX size, in number of registered units (TX descriptors). */
- uint32_t us_tx_size;
-} gmac_dev_mem_t;
-
-/** 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 )
-
-/** 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.
- */
-static 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.
- *
- */
-static void gmac_reset_tx_mem(gmac_device_t* p_dev)
-{
- Gmac *p_hw = p_dev->p_hw;
- uint8_t *p_tx_buff = p_dev->p_tx_buffer;
- gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;
-
- uint32_t ul_index;
- uint32_t ul_address;
-
- /* Disable TX */
- gmac_enable_transmit(p_hw, 0);
-
- /* Set up the TX descriptors */
- CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);
- for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )
- {
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- ul_address = (uint32_t) 0u;
- }
- #else
- {
- ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));
- }
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
- p_td[ul_index].addr = ul_address;
- p_td[ul_index].status.val = GMAC_TXD_USED;
- }
- p_td[p_dev->ul_tx_list_size - 1].status.val =
- GMAC_TXD_USED | GMAC_TXD_WRAP;
-
- /* Set transmit buffer queue */
- gmac_set_tx_queue(p_hw, (uint32_t) p_td);
-}
-
-/**
- * \brief Disable receiver, reset registers and descriptor list.
- *
- * \param p_drv Pointer to GMAC Driver instance.
- */
-static void gmac_reset_rx_mem(gmac_device_t* p_dev)
-{
- Gmac *p_hw = p_dev->p_hw;
- uint8_t *p_rx_buff = p_dev->p_rx_buffer;
- gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;
-
- 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 < p_dev->ul_rx_list_size; ul_index++ )
- {
- ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));
- pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
- pRd[ul_index].status.val = 0;
- }
- pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;
-
- /* Set receive buffer queue */
- gmac_set_rx_queue(p_hw, (uint32_t) pRd);
-}
-
-
-/**
- * \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.
- * \param p_tx_cb Pointer to allocated TX callback list.
- *
- * \return GMAC_OK or GMAC_PARAM.
- */
-static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
- gmac_dev_mem_t* p_dev_mm
-#if( GMAC_USES_TX_CALLBACK != 0 )
- , gmac_dev_tx_cb_t* p_tx_cb
-#endif
- )
-{
- if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1
-#if( GMAC_USES_TX_CALLBACK != 0 )
- || p_tx_cb == NULL
-#endif
- ) {
- return GMAC_PARAM;
- }
-
- /* Assign RX buffers */
- if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)
- || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {
- p_dev_mm->us_rx_size--;
- }
- p_gmac_dev->p_rx_buffer =
- (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);
- p_gmac_dev->p_rx_dscr =
- (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr
- & 0xFFFFFFF8);
- p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;
-
- /* Assign TX buffers */
- if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)
- || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
- p_dev_mm->us_tx_size--;
- }
- p_gmac_dev->p_tx_buffer =
- (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);
- p_gmac_dev->p_tx_dscr =
- (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr
- & 0xFFFFFFF8);
- p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;
-#if( GMAC_USES_TX_CALLBACK != 0 )
- p_gmac_dev->func_tx_cb_list = p_tx_cb;
-#endif
- /* Reset TX & RX */
- 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_RXUBR | /* Enable receive used bit read interrupt. */
- GMAC_IER_TUR | /* Enable transmit underrun interrupt. */
- GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */
- GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */
- GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
- GMAC_IER_ROVR | /* Enable receive overrun 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. */
-
- return GMAC_OK;
-}
-
-/**
- * \brief Read the PHY register.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_address PHY address.
- * \param uc_address Register address.
- * \param p_value Pointer to a 32-bit location to store read data.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
- uint32_t* p_value)
-{
- gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);
-
- if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
- return GMAC_TIMEOUT;
- }
- *p_value = gmac_get_phy_data(p_gmac);
- return GMAC_OK;
-}
-
-/**
- * \brief Write the PHY register.
- *
- * \param p_gmac Pointer to the GMAC instance.
- * \param uc_phy_address PHY Address.
- * \param uc_address Register Address.
- * \param ul_value Data to write, actually 16-bit data.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
- uint8_t uc_address, uint32_t ul_value)
-{
- gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);
-
- if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
- return GMAC_TIMEOUT;
- }
- 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)
-{
- gmac_dev_mem_t gmac_dev_mm;
-
- /* 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);
-
- /* 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_configure(p_gmac,
- ( gmac_get_configure(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 ) |
- GMAC_RXD_RXCOEN );
-
- /*
- * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
- * Note: tha SAM4E does have RX checksum offloading
- * but TX checksum offloading has NOT been implemented.
- */
-
- gmac_set_dma(p_gmac,
- gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );
-
- gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
- gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);
-
- /* Fill in GMAC device memory management */
- gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
- gmac_dev_mm.p_rx_dscr = gs_rx_desc;
- gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;
-
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- gmac_dev_mm.p_tx_buffer = NULL;
- }
- #else
- {
- gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
- }
- #endif
- gmac_dev_mm.p_tx_dscr = gs_tx_desc;
- gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;
-
- gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm
-#if( GMAC_USES_TX_CALLBACK != 0 )
- , gs_tx_callback
-#endif
- );
-
- 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 = &p_gmac_dev->p_rx_dscr[ulIndex];
-
- /* 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, p_gmac_dev->ul_rx_list_size);
- pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
- p_gmac_dev->ul_rx_idx = ulIndex;
- #if( GMAC_STATS != 0 )
- {
- gmacStats.incompCount++;
- }
- #endif
- }
-
- while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {
- if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {
- /* Here a complete frame has been seen with SOF and EOF */
- ulReturn = pxHead->status.bm.len;
- break;
- }
- circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);
- pxHead = &p_gmac_dev->p_rx_dscr[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 = &p_gmac_dev->p_rx_dscr[ulPrev];
- do {
- pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
- circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);
- pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];
- #if( GMAC_STATS != 0 )
- {
- gmacStats.truncCount++;
- }
- #endif
- } while (ulPrev != ulIndex);
- p_gmac_dev->ul_rx_idx = ulIndex;
- }
- }
- 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)
-{
- 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_NULL;
- }
-
- /* 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 );
-
- /* 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 = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
- left = bytesLeft;
- toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;
- if(toCopy > left )
- {
- toCopy = left;
- }
- memcpy (p_frame, source, toCopy);
- left -= toCopy;
-
- if( left != 0ul )
- {
- memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);
- }
- }
-
- do
- {
- pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];
- pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
- circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);
- } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);
-
- p_gmac_dev->ul_rx_idx = nextIdx;
-
- *p_rcv_size = bytesLeft;
-
- return GMAC_OK;
-}
-
-
-extern void vGMACGenerateChecksum( uint8_t *apBuffer );
-
-/**
- * \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.
- * \param func_tx_cb Transmit callback function.
- *
- * \return Length sent.
- */
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
- uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)
-{
-
- volatile gmac_tx_descriptor_t *p_tx_td;
-#if( GMAC_USES_TX_CALLBACK != 0 )
- volatile gmac_dev_tx_cb_t *p_func_tx_cb;
-#endif
-
- Gmac *p_hw = p_gmac_dev->p_hw;
-
-#if( GMAC_USES_TX_CALLBACK == 0 )
- ( void )func_tx_cb;
-#endif
-
- /* Check parameter */
- if (ul_size > GMAC_TX_UNITSIZE) {
- return GMAC_PARAM;
- }
-
- /* Pointers to the current transmit descriptor */
- p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];
-
- /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
-// if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
-// p_gmac_dev->ul_tx_list_size) == 0)
- {
- if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
- return GMAC_TX_BUSY;
- }
-#if( GMAC_USES_TX_CALLBACK != 0 )
- /* Pointers to the current Tx callback */
- p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];
-#endif
-
- /* 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 );
- }
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
- /* Tx callback */
- *p_func_tx_cb = func_tx_cb;
-#endif
-
- /* 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 )( p_gmac_dev->ul_tx_list_size - 1 ) )
- {
- /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */
- p_tx_td->status.val =
- ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
- } else {
- p_tx_td->status.val =
- ul_size | GMAC_TXD_LAST;
- }
-
- circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );
-
- /* 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.
- */
-#if( GMAC_USES_TX_CALLBACK != 0 )
-/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */
-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, p_gmac_dev->ul_tx_list_size);
-}
-#endif
-
-/**
- * \brief Register/Clear RX callback. Callback will be invoked after the next received
- * frame.
- *
- * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls
- * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.
- * The callback is in charge to resume the task once a new frame has been
- * received. The next time gmac_dev_read() is called, it will be successful.
- *
- * This function is usually invoked from the RX callback itself with NULL
- * callback, 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 the GMAC device instance.
- * \param func_tx_cb Receive callback function.
- */
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
- gmac_dev_rx_cb_t func_rx_cb)
-{
- Gmac *p_hw = p_gmac_dev->p_hw;
-
- if (func_rx_cb == NULL) {
- gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);
- p_gmac_dev->func_rx_cb = NULL;
- } else {
- p_gmac_dev->func_rx_cb = func_rx_cb;
- gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);
- }
-}
-
-/**
- * \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 <= p_gmac_dev->ul_tx_list_size) {
- p_gmac_dev->func_wakeup_cb = func_wakeup_cb;
- p_gmac_dev->uc_wakeup_threshold = 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;
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
- gmac_tx_descriptor_t *p_tx_td;
- gmac_dev_tx_cb_t *p_tx_cb = NULL;
- uint32_t ul_tx_status_flag;
-#endif
-#if( GMAC_STATS != 0 )
- int index;
-#endif
-
- /* volatile */ uint32_t ul_isr;
- /* volatile */ uint32_t ul_rsr;
- /* volatile */ uint32_t ul_tsr;
-
- ul_isr = gmac_get_interrupt_status(p_hw);
- ul_rsr = gmac_get_rx_status(p_hw);
- ul_tsr = gmac_get_tx_status(p_hw);
-
-/* Why clear bits that are ignored anyway ? */
-/* ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */
- #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 */
- if (p_gmac_dev->func_rx_cb) {
- p_gmac_dev->func_rx_cb(ul_rsr);
- }
- }
-
- /* TX packet */
- if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
- ul_tx_status_flag = GMAC_TSR_TXCOMP;
-#endif
- /* A frame transmitted */
-
- /* Check RLE */
- if (ul_tsr & GMAC_TSR_RLE) {
- /* Status RLE & Number of discarded buffers */
-#if( GMAC_USES_TX_CALLBACK != 0 )
- ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,
- p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
- p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];
-#endif
- gmac_reset_tx_mem(p_gmac_dev);
- gmac_enable_transmit(p_hw, 1);
- }
- /* Clear status */
- gmac_clear_tx_status(p_hw, ul_tsr);
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
- if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {
- /* Check the buffers */
- do {
- p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];
- p_tx_cb = &p_gmac_dev->func_tx_cb_list[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 */
- if (*p_tx_cb) {
- (*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- p_tx_td->addr = 0ul;
- }
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
- }
-
- circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
- } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
- p_gmac_dev->ul_tx_list_size));
- }
-
- if (ul_tsr & GMAC_TSR_RLE) {
- /* Notify upper layer RLE */
- if (*p_tx_cb) {
- (*p_tx_cb) (ul_tx_status_flag, NULL);
- }
- }
-#endif /* GMAC_USES_TX_CALLBACK */
-
-#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,
- p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_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
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "compiler.h"\r
+#include "instance/gmac.h"\r
+#include "ethernet_phy.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x) (int)( sizeof(x) / sizeof(x)[0] )\r
+#endif\r
+/**\r
+ * \defgroup gmac_group Ethernet Media Access Controller\r
+ *\r
+ * See \ref gmac_quickstart.\r
+ *\r
+ * Driver for the GMAC (Ethernet Media Access Controller).\r
+ * This file contains basic functions for the GMAC, with support for all modes, settings\r
+ * and clock speeds.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver does not depend on other modules.\r
+ *\r
+ * @{\r
+ */\r
+\r
+/** TX descriptor lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/** TX callback lists */\r
+static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];\r
+#endif\r
+/** RX descriptors lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+ /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the\r
+ * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits\r
+ * of the address shall be set to 0.\r
+ */\r
+ COMPILER_ALIGNED(8)\r
+ static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/** Receive Buffer */\r
+COMPILER_ALIGNED(8)\r
+static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];\r
+\r
+/**\r
+ * GMAC device memory management struct.\r
+ */\r
+typedef struct gmac_dev_mem {\r
+ /* Pointer to allocated buffer for RX. The address should be 8-byte aligned\r
+ and the size should be GMAC_RX_UNITSIZE * wRxSize. */\r
+ uint8_t *p_rx_buffer;\r
+ /* Pointer to allocated RX descriptor list. */\r
+ gmac_rx_descriptor_t *p_rx_dscr;\r
+ /* RX size, in number of registered units (RX descriptors). */\r
+ /* Increased size from 16- to 32-bits, because it's more efficient */\r
+ uint32_t us_rx_size;\r
+ /* Pointer to allocated buffer for TX. The address should be 8-byte aligned\r
+ and the size should be GMAC_TX_UNITSIZE * wTxSize. */\r
+ uint8_t *p_tx_buffer;\r
+ /* Pointer to allocated TX descriptor list. */\r
+ gmac_tx_descriptor_t *p_tx_dscr;\r
+ /* TX size, in number of registered units (TX descriptors). */\r
+ uint32_t us_tx_size;\r
+} gmac_dev_mem_t;\r
+\r
+/** Return count in buffer */\r
+#define CIRC_CNT( head, tail, size ) ( ( ( head ) - ( tail ) ) % ( size ) )\r
+\r
+/*\r
+ * Return space available, from 0 to size-1.\r
+ * Always leave one free char as a completely full buffer that has (head == tail),\r
+ * which is the same as empty.\r
+ */\r
+#define CIRC_SPACE( head, tail, size ) CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )\r
+\r
+/** Circular buffer is empty ? */\r
+#define CIRC_EMPTY( head, tail ) ( head == tail )\r
+/** Clear circular buffer */\r
+#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )\r
+\r
+/** Increment head or tail */\r
+static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )\r
+{\r
+ ( *lHeadOrTail ) ++;\r
+ if( ( *lHeadOrTail ) >= ( int32_t )ulSize )\r
+ {\r
+ ( *lHeadOrTail ) = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Wait PHY operation to be completed.\r
+ *\r
+ * \param p_gmac HW controller address.\r
+ * \param ul_retry The retry times, 0 to wait forever until completeness.\r
+ *\r
+ * Return GMAC_OK if the operation is completed successfully.\r
+ */\r
+static uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)\r
+{\r
+ volatile uint32_t ul_retry_count = 0;\r
+ const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );\r
+\r
+ while (!gmac_is_phy_idle(p_gmac)) {\r
+ if (ul_retry == 0) {\r
+ continue;\r
+ }\r
+\r
+ ul_retry_count++;\r
+\r
+ if (ul_retry_count >= ul_retry) {\r
+ return GMAC_TIMEOUT;\r
+ }\r
+\r
+ /* Block the task to allow other tasks to execute while the PHY\r
+ is not connected. */\r
+ vTaskDelay( xPHYPollDelay );\r
+ }\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Disable transfer, reset registers and descriptor lists.\r
+ *\r
+ * \param p_dev Pointer to GMAC driver instance.\r
+ *\r
+ */\r
+static void gmac_reset_tx_mem(gmac_device_t* p_dev)\r
+{\r
+ Gmac *p_hw = p_dev->p_hw;\r
+ uint8_t *p_tx_buff = p_dev->p_tx_buffer;\r
+ gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;\r
+\r
+ uint32_t ul_index;\r
+ uint32_t ul_address;\r
+\r
+ /* Disable TX */\r
+ gmac_enable_transmit(p_hw, 0);\r
+\r
+ /* Set up the TX descriptors */\r
+ CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);\r
+ for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )\r
+ {\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ ul_address = (uint32_t) 0u;\r
+ }\r
+ #else\r
+ {\r
+ ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+ p_td[ul_index].addr = ul_address;\r
+ p_td[ul_index].status.val = GMAC_TXD_USED;\r
+ }\r
+ p_td[p_dev->ul_tx_list_size - 1].status.val =\r
+ GMAC_TXD_USED | GMAC_TXD_WRAP;\r
+\r
+ /* Set transmit buffer queue */\r
+ gmac_set_tx_queue(p_hw, (uint32_t) p_td);\r
+}\r
+\r
+/**\r
+ * \brief Disable receiver, reset registers and descriptor list.\r
+ *\r
+ * \param p_drv Pointer to GMAC Driver instance.\r
+ */\r
+static void gmac_reset_rx_mem(gmac_device_t* p_dev)\r
+{\r
+ Gmac *p_hw = p_dev->p_hw;\r
+ uint8_t *p_rx_buff = p_dev->p_rx_buffer;\r
+ gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;\r
+\r
+ uint32_t ul_index;\r
+ uint32_t ul_address;\r
+\r
+ /* Disable RX */\r
+ gmac_enable_receive(p_hw, 0);\r
+\r
+ /* Set up the RX descriptors */\r
+ p_dev->ul_rx_idx = 0;\r
+ for( ul_index = 0; ul_index < p_dev->ul_rx_list_size; ul_index++ )\r
+ {\r
+ ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));\r
+ pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;\r
+ pRd[ul_index].status.val = 0;\r
+ }\r
+ pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;\r
+\r
+ /* Set receive buffer queue */\r
+ gmac_set_rx_queue(p_hw, (uint32_t) pRd);\r
+}\r
+\r
+\r
+/**\r
+ * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.\r
+ * Must be invoked after gmac_dev_init() but before RX/TX starts.\r
+ *\r
+ * \note If input address is not 8-byte aligned, the address is automatically\r
+ * adjusted and the list size is reduced by one.\r
+ *\r
+ * \param p_gmac Pointer to GMAC instance.\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ * \param p_dev_mm Pointer to the GMAC memory management control block.\r
+ * \param p_tx_cb Pointer to allocated TX callback list.\r
+ *\r
+ * \return GMAC_OK or GMAC_PARAM.\r
+ */\r
+static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+ gmac_dev_mem_t* p_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ , gmac_dev_tx_cb_t* p_tx_cb\r
+#endif\r
+ )\r
+{\r
+ if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ || p_tx_cb == NULL\r
+#endif\r
+ ) {\r
+ return GMAC_PARAM;\r
+ }\r
+\r
+ /* Assign RX buffers */\r
+ if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)\r
+ || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {\r
+ p_dev_mm->us_rx_size--;\r
+ }\r
+ p_gmac_dev->p_rx_buffer =\r
+ (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);\r
+ p_gmac_dev->p_rx_dscr =\r
+ (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr\r
+ & 0xFFFFFFF8);\r
+ p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;\r
+\r
+ /* Assign TX buffers */\r
+ if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)\r
+ || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {\r
+ p_dev_mm->us_tx_size--;\r
+ }\r
+ p_gmac_dev->p_tx_buffer =\r
+ (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);\r
+ p_gmac_dev->p_tx_dscr =\r
+ (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr\r
+ & 0xFFFFFFF8);\r
+ p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ p_gmac_dev->func_tx_cb_list = p_tx_cb;\r
+#endif\r
+ /* Reset TX & RX */\r
+ gmac_reset_rx_mem(p_gmac_dev);\r
+ gmac_reset_tx_mem(p_gmac_dev);\r
+\r
+ /* Enable Rx and Tx, plus the statistics register */\r
+ gmac_enable_transmit(p_gmac, true);\r
+ gmac_enable_receive(p_gmac, true);\r
+ gmac_enable_statistics_write(p_gmac, true);\r
+\r
+ /* Set up the interrupts for transmission and errors */\r
+ gmac_enable_interrupt(p_gmac,\r
+ GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */\r
+ GMAC_IER_TUR | /* Enable transmit underrun interrupt. */\r
+ GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */\r
+ GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+ GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */\r
+ GMAC_IER_ROVR | /* Enable receive overrun interrupt. */\r
+ GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */\r
+ GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */\r
+ GMAC_IER_PTZ); /* Enable pause time zero interrupt. */\r
+\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Read the PHY register.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY address.\r
+ * \param uc_address Register address.\r
+ * \param p_value Pointer to a 32-bit location to store read data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+ uint32_t* p_value)\r
+{\r
+ gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);\r
+\r
+ if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+ return GMAC_TIMEOUT;\r
+ }\r
+ *p_value = gmac_get_phy_data(p_gmac);\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Write the PHY register.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY Address.\r
+ * \param uc_address Register Address.\r
+ * \param ul_value Data to write, actually 16-bit data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+ uint8_t uc_address, uint32_t ul_value)\r
+{\r
+ gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);\r
+\r
+ if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+ return GMAC_TIMEOUT;\r
+ }\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Initialize the GMAC driver.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_opt GMAC configure options.\r
+ */\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+ gmac_options_t* p_opt)\r
+{\r
+ gmac_dev_mem_t gmac_dev_mm;\r
+\r
+ /* Disable TX & RX and more */\r
+ gmac_network_control(p_gmac, 0);\r
+ gmac_disable_interrupt(p_gmac, ~0u);\r
+\r
+\r
+ gmac_clear_statistics(p_gmac);\r
+\r
+ /* Clear all status bits in the receive status register. */\r
+ gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);\r
+\r
+ /* Clear all status bits in the transmit status register */\r
+ gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE\r
+ | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);\r
+\r
+ /* Clear interrupts */\r
+ gmac_get_interrupt_status(p_gmac);\r
+#if !defined(ETHERNET_CONF_DATA_OFFSET)\r
+ /* Receive Buffer Offset\r
+ * Indicates the number of bytes by which the received data\r
+ * is offset from the start of the receive buffer\r
+ * which can be handy for alignment reasons */\r
+ /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */\r
+ #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0\r
+#endif\r
+ /* Enable the copy of data into the buffers\r
+ ignore broadcasts, and not copy FCS. */\r
+\r
+ gmac_set_configure(p_gmac,\r
+ ( gmac_get_configure(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |\r
+ GMAC_NCFGR_RFCS | /* Remove FCS, frame check sequence (last 4 bytes) */\r
+ GMAC_NCFGR_PEN | /* Pause Enable */\r
+ GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |\r
+ GMAC_RXD_RXCOEN );\r
+\r
+ /*\r
+ * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.\r
+ * Note: tha SAM4E does have RX checksum offloading\r
+ * but TX checksum offloading has NOT been implemented.\r
+ */\r
+\r
+ gmac_set_dma(p_gmac,\r
+ gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );\r
+\r
+ gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);\r
+ gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);\r
+\r
+ /* Fill in GMAC device memory management */\r
+ gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;\r
+ gmac_dev_mm.p_rx_dscr = gs_rx_desc;\r
+ gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;\r
+\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ gmac_dev_mm.p_tx_buffer = NULL;\r
+ }\r
+ #else\r
+ {\r
+ gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;\r
+ }\r
+ #endif\r
+ gmac_dev_mm.p_tx_dscr = gs_tx_desc;\r
+ gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;\r
+\r
+ gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ , gs_tx_callback\r
+#endif\r
+ );\r
+\r
+ gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ *\r
+ * Returns > 0 if a complete frame is available\r
+ * It also it cleans up incomplete older frames\r
+ */\r
+\r
+static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)\r
+{\r
+ uint32_t ulReturn = 0;\r
+ int32_t ulIndex = p_gmac_dev->ul_rx_idx;\r
+ gmac_rx_descriptor_t *pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+\r
+ /* Discard any incomplete frames */\r
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&\r
+ (pxHead->status.val & GMAC_RXD_SOF) == 0) {\r
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+ circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+ pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+ p_gmac_dev->ul_rx_idx = ulIndex;\r
+ #if( GMAC_STATS != 0 )\r
+ {\r
+ gmacStats.incompCount++;\r
+ }\r
+ #endif\r
+ }\r
+\r
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {\r
+ if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {\r
+ /* Here a complete frame has been seen with SOF and EOF */\r
+ ulReturn = pxHead->status.bm.len;\r
+ break;\r
+ }\r
+ circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+ pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+ if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {\r
+ /* CPU is not the owner (yet) */\r
+ break;\r
+ }\r
+ if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {\r
+ /* Strange, we found a new Start Of Frame\r
+ * discard previous segments */\r
+ int32_t ulPrev = p_gmac_dev->ul_rx_idx;\r
+ pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+ do {\r
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+ circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);\r
+ pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+ #if( GMAC_STATS != 0 )\r
+ {\r
+ gmacStats.truncCount++;\r
+ }\r
+ #endif\r
+ } while (ulPrev != ulIndex);\r
+ p_gmac_dev->ul_rx_idx = ulIndex;\r
+ }\r
+ }\r
+ return ulReturn;\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.\r
+ * p_rcv_size is the size of the entire frame. Generally gmac_read\r
+ * will be repeatedly called until the sum of all the ul_frame_size equals\r
+ * the value of p_rcv_size.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_frame Address of the frame buffer.\r
+ * \param ul_frame_size Length of the frame.\r
+ * \param p_rcv_size Received frame size.\r
+ *\r
+ * \return GMAC_OK if receiving frame successfully, otherwise failed.\r
+ */\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+ uint32_t ul_frame_size, uint32_t* p_rcv_size)\r
+{\r
+ int32_t nextIdx; /* A copy of the Rx-index 'ul_rx_idx' */\r
+ int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);\r
+ gmac_rx_descriptor_t *pxHead;\r
+\r
+ if (bytesLeft == 0 )\r
+ {\r
+ return GMAC_RX_NULL;\r
+ }\r
+\r
+ /* gmac_dev_poll has confirmed that there is a complete frame at\r
+ * the current position 'ul_rx_idx'\r
+ */\r
+ nextIdx = p_gmac_dev->ul_rx_idx;\r
+\r
+ /* Read +2 bytes because buffers are aligned at -2 bytes */\r
+ bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );\r
+\r
+ /* The frame will be copied in 1 or 2 memcpy's */\r
+ if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )\r
+ {\r
+ const uint8_t *source;\r
+ int32_t left;\r
+ int32_t toCopy;\r
+\r
+ source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;\r
+ left = bytesLeft;\r
+ toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;\r
+ if(toCopy > left )\r
+ {\r
+ toCopy = left;\r
+ }\r
+ memcpy (p_frame, source, toCopy);\r
+ left -= toCopy;\r
+\r
+ if( left != 0ul )\r
+ {\r
+ memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);\r
+ }\r
+ }\r
+\r
+ do\r
+ {\r
+ pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];\r
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+ circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);\r
+ } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);\r
+\r
+ p_gmac_dev->ul_rx_idx = nextIdx;\r
+\r
+ *p_rcv_size = bytesLeft;\r
+\r
+ return GMAC_OK;\r
+}\r
+\r
+\r
+extern void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+\r
+/**\r
+ * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the\r
+ * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.\r
+ * If lEndOfFrame is true then the data being copied is the end of the frame\r
+ * and the frame can be transmitted.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_buffer Pointer to the data buffer.\r
+ * \param ul_size Length of the frame.\r
+ * \param func_tx_cb Transmit callback function.\r
+ *\r
+ * \return Length sent.\r
+ */\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+ uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)\r
+{\r
+\r
+ volatile gmac_tx_descriptor_t *p_tx_td;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ volatile gmac_dev_tx_cb_t *p_func_tx_cb;\r
+#endif\r
+\r
+ Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK == 0 )\r
+ ( void )func_tx_cb;\r
+#endif\r
+\r
+ /* Check parameter */\r
+ if (ul_size > GMAC_TX_UNITSIZE) {\r
+ return GMAC_PARAM;\r
+ }\r
+\r
+ /* Pointers to the current transmit descriptor */\r
+ p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];\r
+\r
+ /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */\r
+// if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+// p_gmac_dev->ul_tx_list_size) == 0)\r
+ {\r
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)\r
+ return GMAC_TX_BUSY;\r
+ }\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ /* Pointers to the current Tx callback */\r
+ p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];\r
+#endif\r
+\r
+ /* Set up/copy data to transmission buffer */\r
+ if (p_buffer && ul_size) {\r
+ /* Driver manages the ring buffer */\r
+ /* Calculating the checksum here is faster than calculating it from the GMAC buffer\r
+ * because withing p_buffer, it is well aligned */\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* Zero-copy... */\r
+ p_tx_td->addr = ( uint32_t ) p_buffer;\r
+ }\r
+ #else\r
+ {\r
+ /* Or Memcopy... */\r
+ memcpy((void *)p_tx_td->addr, p_buffer, ul_size);\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+ vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );\r
+ }\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ /* Tx callback */\r
+ *p_func_tx_cb = func_tx_cb;\r
+#endif\r
+\r
+ /* Update transmit descriptor status */\r
+\r
+ /* The buffer size defined is the length of ethernet frame,\r
+ so it's always the last buffer of the frame. */\r
+ if( p_gmac_dev->l_tx_head == ( int32_t )( p_gmac_dev->ul_tx_list_size - 1 ) )\r
+ {\r
+ /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */\r
+ p_tx_td->status.val =\r
+ ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;\r
+ } else {\r
+ p_tx_td->status.val =\r
+ ul_size | GMAC_TXD_LAST;\r
+ }\r
+\r
+ circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );\r
+\r
+ /* Now start to transmit if it is still not done */\r
+ gmac_start_transmission(p_hw);\r
+\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Get current load of transmit.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ *\r
+ * \return Current load of transmit.\r
+ */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)\r
+{\r
+ uint16_t us_head = p_gmac_dev->l_tx_head;\r
+ uint16_t us_tail = p_gmac_dev->l_tx_tail;\r
+ return CIRC_CNT(us_head, us_tail, p_gmac_dev->ul_tx_list_size);\r
+}\r
+#endif\r
+\r
+/**\r
+ * \brief Register/Clear RX callback. Callback will be invoked after the next received\r
+ * frame.\r
+ *\r
+ * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls\r
+ * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.\r
+ * The callback is in charge to resume the task once a new frame has been\r
+ * received. The next time gmac_dev_read() is called, it will be successful.\r
+ *\r
+ * This function is usually invoked from the RX callback itself with NULL\r
+ * callback, to unregister. Once the callback has resumed the application task,\r
+ * there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param func_tx_cb Receive callback function.\r
+ */\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_rx_cb_t func_rx_cb)\r
+{\r
+ Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+ if (func_rx_cb == NULL) {\r
+ gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);\r
+ p_gmac_dev->func_rx_cb = NULL;\r
+ } else {\r
+ p_gmac_dev->func_rx_cb = func_rx_cb;\r
+ gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Register/Clear TX wakeup callback.\r
+ *\r
+ * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application\r
+ * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and\r
+ * enters suspend state. The callback is in charge to resume the task once\r
+ * several transmit descriptors have been released. The next time gmac_dev_write() will be called,\r
+ * it shall be successful.\r
+ *\r
+ * This function is usually invoked with NULL callback from the TX wakeup\r
+ * callback itself, to unregister. Once the callback has resumed the\r
+ * application task, there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ * \param func_wakeup Pointer to wakeup callback function.\r
+ * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.\r
+ *\r
+ * \return GMAC_OK, GMAC_PARAM on parameter error.\r
+ */\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)\r
+{\r
+ if (func_wakeup_cb == NULL) {\r
+ p_gmac_dev->func_wakeup_cb = NULL;\r
+ } else {\r
+ if (uc_threshold <= p_gmac_dev->ul_tx_list_size) {\r
+ p_gmac_dev->func_wakeup_cb = func_wakeup_cb;\r
+ p_gmac_dev->uc_wakeup_threshold = uc_threshold;\r
+ } else {\r
+ return GMAC_PARAM;\r
+ }\r
+ }\r
+\r
+ return GMAC_OK;\r
+}\r
+#endif /* GMAC_USES_WAKEUP_CALLBACK */\r
+\r
+/**\r
+ * \brief Reset TX & RX queue & statistics.\r
+ *\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ */\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev)\r
+{\r
+ Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+ gmac_reset_rx_mem(p_gmac_dev);\r
+ gmac_reset_tx_mem(p_gmac_dev);\r
+ gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN\r
+ | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+}\r
+\r
+void gmac_dev_halt(Gmac* p_gmac);\r
+\r
+void gmac_dev_halt(Gmac* p_gmac)\r
+{\r
+ gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+ gmac_disable_interrupt(p_gmac, ~0u);\r
+}\r
+\r
+\r
+/**\r
+ * \brief GMAC Interrupt handler.\r
+ *\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ */\r
+\r
+#if( GMAC_STATS != 0 )\r
+ extern int logPrintf( const char *pcFormat, ... );\r
+\r
+ void gmac_show_irq_counts ()\r
+ {\r
+ int index;\r
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+ if (gmacStats.intStatus[intPairs[index].index]) {\r
+ logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+void gmac_handler(gmac_device_t* p_gmac_dev)\r
+{\r
+ Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ gmac_tx_descriptor_t *p_tx_td;\r
+ gmac_dev_tx_cb_t *p_tx_cb = NULL;\r
+ uint32_t ul_tx_status_flag;\r
+#endif\r
+#if( GMAC_STATS != 0 )\r
+ int index;\r
+#endif\r
+\r
+ /* volatile */ uint32_t ul_isr;\r
+ /* volatile */ uint32_t ul_rsr;\r
+ /* volatile */ uint32_t ul_tsr;\r
+\r
+ ul_isr = gmac_get_interrupt_status(p_hw);\r
+ ul_rsr = gmac_get_rx_status(p_hw);\r
+ ul_tsr = gmac_get_tx_status(p_hw);\r
+\r
+/* Why clear bits that are ignored anyway ? */\r
+/* ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */\r
+ #if( GMAC_STATS != 0 )\r
+ {\r
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+ if (ul_isr & intPairs[index].mask)\r
+ gmacStats.intStatus[intPairs[index].index]++;\r
+ }\r
+ }\r
+ #endif /* GMAC_STATS != 0 */\r
+\r
+ /* RX packet */\r
+ if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {\r
+ /* Clear status */\r
+ gmac_clear_rx_status(p_hw, ul_rsr);\r
+\r
+ if (ul_isr & GMAC_ISR_RCOMP)\r
+ ul_rsr |= GMAC_RSR_REC;\r
+ /* Invoke callbacks which can be useful to wake op a task */\r
+ if (p_gmac_dev->func_rx_cb) {\r
+ p_gmac_dev->func_rx_cb(ul_rsr);\r
+ }\r
+ }\r
+\r
+ /* TX packet */\r
+ if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ ul_tx_status_flag = GMAC_TSR_TXCOMP;\r
+#endif\r
+ /* A frame transmitted */\r
+\r
+ /* Check RLE */\r
+ if (ul_tsr & GMAC_TSR_RLE) {\r
+ /* Status RLE & Number of discarded buffers */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,\r
+ p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+ p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+#endif\r
+ gmac_reset_tx_mem(p_gmac_dev);\r
+ gmac_enable_transmit(p_hw, 1);\r
+ }\r
+ /* Clear status */\r
+ gmac_clear_tx_status(p_hw, ul_tsr);\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {\r
+ /* Check the buffers */\r
+ do {\r
+ p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];\r
+ p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+ /* Any error? Exit if buffer has not been sent yet */\r
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {\r
+ break;\r
+ }\r
+\r
+ /* Notify upper layer that a packet has been sent */\r
+ if (*p_tx_cb) {\r
+ (*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ p_tx_td->addr = 0ul;\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+ }\r
+\r
+ circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+ } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+ p_gmac_dev->ul_tx_list_size));\r
+ }\r
+\r
+ if (ul_tsr & GMAC_TSR_RLE) {\r
+ /* Notify upper layer RLE */\r
+ if (*p_tx_cb) {\r
+ (*p_tx_cb) (ul_tx_status_flag, NULL);\r
+ }\r
+ }\r
+#endif /* GMAC_USES_TX_CALLBACK */\r
+\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+ /* If a wakeup has been scheduled, notify upper layer that it can\r
+ send other packets, and the sending will be successful. */\r
+ if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+ p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)\r
+ && p_gmac_dev->func_wakeup_cb) {\r
+ p_gmac_dev->func_wakeup_cb();\r
+ }\r
+#endif\r
+ }\r
+}\r
+\r
+//@}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 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
- *
- */
-
-#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_TX_UNITSIZE 1518 /**< 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_NULL, /** 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_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;
-
-/** 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 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 */
- 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 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;
-
-/** RX callback */
-typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);
-/** 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.
- */
- uint8_t *p_tx_buffer;
- /** Pointer to allocated RX buffer */
- uint8_t *p_rx_buffer;
- /** Pointer to Rx TDs (must be 8-byte aligned) */
- gmac_rx_descriptor_t *p_rx_dscr;
- /** Pointer to Tx TDs (must be 8-byte aligned) */
- gmac_tx_descriptor_t *p_tx_dscr;
- /** Optional callback to be invoked once a frame has been received */
- gmac_dev_tx_cb_t func_rx_cb;
-#if( GMAC_USES_WAKEUP_CALLBACK )
- /** Optional callback to be invoked once several TDs have been released */
- gmac_dev_wakeup_cb_t func_wakeup_cb;
-#endif
-#if( GMAC_USES_TX_CALLBACK != 0 )
- /** Optional callback list to be invoked once TD has been processed */
- gmac_dev_tx_cb_t *func_tx_cb_list;
-#endif
- /** RX TD list size */
- uint32_t ul_rx_list_size;
- /** RX index for current processing TD */
- uint32_t ul_rx_idx;
- /** TX TD list size */
- uint32_t ul_tx_list_size;
- /** 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 uc_wakeup_threshold;
-} gmac_device_t;
-
-/**
- * \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)
-{
- 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 Read snapshot.
- *
- * \param p_gmac Pointer to the GMAC instance.
- */
-static inline void gmac_read_snapshot(Gmac* p_gmac)
-{
- p_gmac->GMAC_NCR |= GMAC_NCR_RDS;
-}
-
-/**
- * \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_configure(Gmac* p_gmac, uint32_t ul_cfg)
-{
- p_gmac->GMAC_NCFGR = ul_cfg;
-}
-
-/**
- * \brief Get network configuration.
- *
- * \param p_gmac Pointer to the GMAC instance.
- *
- * \return Network configuration.
- */
-static inline uint32_t gmac_get_configure(Gmac* p_gmac)
-{
- return p_gmac->GMAC_NCFGR;
-}
-
-
-/* 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 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;
-
- 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;
- }
- ;
- p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;
- 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 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,
- 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.
- */
-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;
- }
-}
-
-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);
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
- uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
- gmac_dev_tx_cb_t func_rx_cb);
-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);
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \page gmac_quickstart Quickstart guide for GMAC driver.
- *
- * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",
- * with step-by-step instructions on how to configure and use the driver in a
- * selection of use cases.
- *
- * The use cases contain several code fragments. The code fragments in the
- * steps for setup can be copied into a custom initialization function, while
- * the steps for usage can be copied into, e.g., the main application function.
- *
- * \section gmac_basic_use_case Basic use case
- * In the basic use case, the GMAC driver are configured for:
- * - PHY component KSZ8051MNL is used
- * - GMAC uses MII mode
- * - The number of receive buffer is 16
- * - The number of transfer buffer is 8
- * - MAC address is set to 00-04-25-1c-a0-02
- * - IP address is set to 192.168.0.2
- * - IP address is set to 192.168.0.2
- * - Gateway is set to 192.168.0.1
- * - Network mask is 255.255.255.0
- * - PHY operation max retry count is 1000000
- * - GMAC is configured to not support copy all frame and support broadcast
- * - The data will be read from the ethernet
- *
- * \section gmac_basic_use_case_setup Setup steps
- *
- * \subsection gmac_basic_use_case_setup_prereq Prerequisites
- * -# \ref sysclk_group "System Clock Management (sysclock)"
- * -# \ref pmc_group "Power Management Controller (pmc)"
- * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"
- *
- * \subsection gmac_basic_use_case_setup_code Example code
- * Content of conf_eth.h
- * \code
- * #define GMAC_RX_BUFFERS 16
- * #define GMAC_TX_BUFFERS 8
- * #define MAC_PHY_RETRY_MAX 1000000
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR1 0x04
- * #define ETHERNET_CONF_ETHADDR2 0x25
- * #define ETHERNET_CONF_ETHADDR3 0x1C
- * #define ETHERNET_CONF_ETHADDR4 0xA0
- * #define ETHERNET_CONF_ETHADDR5 0x02
- * #define ETHERNET_CONF_IPADDR0 192
- * #define ETHERNET_CONF_IPADDR1 168
- * #define ETHERNET_CONF_IPADDR2 0
- * #define ETHERNET_CONF_IPADDR3 2
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1
- * #define ETHERNET_CONF_NET_MASK0 255
- * #define ETHERNET_CONF_NET_MASK1 255
- * #define ETHERNET_CONF_NET_MASK2 255
- * #define ETHERNET_CONF_NET_MASK3 0
- * #define ETH_PHY_MODE ETH_PHY_MODE
- * \endcode
- *
- * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined
- * to trace the actual size of the data received.
- * \code
- * static gmac_device_t gs_gmac_dev;
- * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];
- *
- * uint32_t ul_frm_size;
- * \endcode
- *
- * Add to application C-file:
- * \code
- * void gmac_init(void)
- * {
- * sysclk_init();
- *
- * board_init();
- *
- * pmc_enable_periph_clk(ID_GMAC);
- *
- * gmac_option.uc_copy_all_frame = 0;
- * gmac_option.uc_no_boardcast = 0;
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- * gs_gmac_dev.p_hw = GMAC;
- *
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- *
- * NVIC_EnableIRQ(GMAC_IRQn);
- *
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- *
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- *
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \subsection gmac_basic_use_case_setup_flow Workflow
- * - Ensure that conf_eth.h is present and contains the
- * following configuration symbol. This configuration file is used
- * by the driver and should not be included by the application.
- * -# Define the receiving buffer size used in the internal GMAC driver.
- * The buffer size used for RX is GMAC_RX_BUFFERS * 128.
- * If it was supposed receiving a large number of frame, the
- * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept
- * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least
- * (2048/128)=16, and as there are additional frames coming, a preferred
- * number is 24 depending on a normal Ethernet throughput.
- * - \code
- * #define GMAC_RX_BUFFERS 16
- * \endcode
- * -# Define the transmitting buffer size used in the internal GMAC driver.
- * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.
- * - \code
- * #define GMAC_TX_BUFFERS 8
- * \endcode
- * -# Define maximum retry time for a PHY read/write operation.
- * - \code
- * #define MAC_PHY_RETRY_MAX 1000000
- * \endcode
- * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved
- * for ATMEL, application should always change this address to its' own.
- * - \code
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR1 0x04
- * #define ETHERNET_CONF_ETHADDR2 0x25
- * #define ETHERNET_CONF_ETHADDR3 0x1C
- * #define ETHERNET_CONF_ETHADDR4 0xA0
- * #define ETHERNET_CONF_ETHADDR5 0x02
- * \endcode
- * -# Define the IP address configration used in the application. When DHCP
- * is enabled, this configuration is not effected.
- * - \code
- * #define ETHERNET_CONF_IPADDR0 192
- * #define ETHERNET_CONF_IPADDR1 168
- * #define ETHERNET_CONF_IPADDR2 0
- * #define ETHERNET_CONF_IPADDR3 2
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1
- * #define ETHERNET_CONF_NET_MASK0 255
- * #define ETHERNET_CONF_NET_MASK1 255
- * #define ETHERNET_CONF_NET_MASK2 255
- * #define ETHERNET_CONF_NET_MASK3 0
- * \endcode
- * -# Configure the PHY maintainance interface.
- * - \code
- * #define ETH_PHY_MODE GMAC_PHY_MII
- * \endcode
- * -# Enable the system clock:
- * - \code sysclk_init(); \endcode
- * -# Enable PIO configurations for GMAC:
- * - \code board_init(); \endcode
- * -# Enable PMC clock for GMAC:
- * - \code pmc_enable_periph_clk(ID_GMAC); \endcode
- * -# Set the GMAC options; it's set to copy all frame and support broadcast:
- * - \code
- * gmac_option.uc_copy_all_frame = 0;
- * gmac_option.uc_no_boardcast = 0;
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- * gs_gmac_dev.p_hw = GMAC;
- * \endcode
- * -# Initialize GMAC device with the filled option:
- * - \code
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- * \endcode
- * -# Enable the interrupt service for GMAC:
- * - \code
- * NVIC_EnableIRQ(GMAC_IRQn);
- * \endcode
- * -# Initialize the PHY component:
- * - \code
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- * \endcode
- * -# The link will be established based on auto negotiation.
- * - \code
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- * \endcode
- * -# Establish the ethernet link; the network can be worked from now on:
- * - \code
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \section gmac_basic_use_case_usage Usage steps
- * \subsection gmac_basic_use_case_usage_code Example code
- * Add to, e.g., main loop in application C-file:
- * \code
- * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
- * \endcode
- *
- * \subsection gmac_basic_use_case_usage_flow Workflow
- * -# Start reading the data from the ethernet:
- * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
- */
-
-# 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 */
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+ last few bits are zero. These bits have special meaning for the GMAC\r
+ peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC\r
+#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */\r
+#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX 1536\r
+\r
+#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */\r
+#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M 0\r
+#define GMAC_SPEED_100M 1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+ GMAC_OK = 0, /** 0 Operation OK */\r
+ GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */\r
+ GMAC_TX_BUSY, /** 2 TX in progress */\r
+ GMAC_RX_NULL, /** 3 No data received */\r
+ GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */\r
+ GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */\r
+ GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+ GMAC_PHY_MII = 0, /** MII mode */\r
+ GMAC_PHY_RMII = 1, /** Reduced MII mode */\r
+ GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+ union gmac_rx_addr {\r
+ uint32_t val;\r
+ struct gmac_rx_addr_bm {\r
+ uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+ b_wrap:1, /**< Marks last descriptor in receive buffer */\r
+ addr_dw:30; /**< Address in number of DW */\r
+ } bm;\r
+ } addr; /**< Address, Wrap & Ownership */\r
+ union gmac_rx_status {\r
+ uint32_t val;\r
+ struct gmac_rx_status_bm {\r
+ uint32_t len:13, /** 0..12 Length of frame including FCS */\r
+ b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */\r
+ b_sof:1, /** 14 Start of frame */\r
+ b_eof:1, /** 15 End of frame */\r
+ b_cfi:1, /** 16 Concatenation Format Indicator */\r
+ vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */\r
+ b_priority_detected:1, /** 20 Priority tag detected */\r
+ b_vlan_detected:1, /** 21 VLAN tag detected */\r
+ b_type_id_match:2, /** 22..23 Type ID match */\r
+ b_checksumoffload:1, /** 24 Checksum offload specific function */\r
+ b_addrmatch:2, /** 25..26 Address register match */\r
+ b_ext_addr_match:1, /** 27 External address match found */\r
+ reserved:1, /** 28 */\r
+ b_uni_hash_match:1, /** 29 Unicast hash match */\r
+ b_multi_hash_match:1, /** 30 Multicast hash match */\r
+ b_boardcast_detect:1; /** 31 Global broadcast address detected */\r
+ } bm;\r
+ } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+ uint32_t addr;\r
+ union gmac_tx_status {\r
+ uint32_t val;\r
+ struct gmac_tx_status_bm {\r
+ uint32_t len:14, /** 0..13 Length of buffer */\r
+ reserved:1, /** 14 */\r
+ b_last_buffer:1, /** 15 Last buffer (in the current frame) */\r
+ b_no_crc:1, /** 16 No CRC */\r
+ reserved1:3, /** 17..19 */\r
+ b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+ reserved2:3, /** 23..25 */\r
+ b_lco:1, /** 26 Late collision, transmit error detected */\r
+ b_exhausted:1, /** 27 Buffer exhausted in mid frame */\r
+ b_underrun:1, /** 28 Transmit underrun */\r
+ b_error:1, /** 29 Retry limit exceeded, error detected */\r
+ b_wrap:1, /** 30 Marks last descriptor in TD list */\r
+ b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+ } bm;\r
+ } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+ /* Enable/Disable CopyAllFrame */\r
+ uint8_t uc_copy_all_frame;\r
+ /* Enable/Disable NoBroadCast */\r
+ uint8_t uc_no_boardcast;\r
+ /* MAC address */\r
+ uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** RX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+ /** Pointer to HW register base */\r
+ Gmac *p_hw;\r
+ /**\r
+ * Pointer to allocated TX buffer.\r
+ * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+ * 1K Boundaries.\r
+ * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+ * of the address shall be set to 0.\r
+ */\r
+ uint8_t *p_tx_buffer;\r
+ /** Pointer to allocated RX buffer */\r
+ uint8_t *p_rx_buffer;\r
+ /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+ gmac_rx_descriptor_t *p_rx_dscr;\r
+ /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+ gmac_tx_descriptor_t *p_tx_dscr;\r
+ /** Optional callback to be invoked once a frame has been received */\r
+ gmac_dev_tx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+ /** Optional callback to be invoked once several TDs have been released */\r
+ gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ /** Optional callback list to be invoked once TD has been processed */\r
+ gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+ /** RX TD list size */\r
+ uint32_t ul_rx_list_size;\r
+ /** RX index for current processing TD */\r
+ uint32_t ul_rx_idx;\r
+ /** TX TD list size */\r
+ uint32_t ul_tx_list_size;\r
+ /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+ int32_t l_tx_head;\r
+ /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+ int32_t l_tx_tail;\r
+\r
+ /** Number of free TD before wakeup callback is invoked */\r
+ uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_ncr Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+ p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+ uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_cfg Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+ p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+ p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+ if (uc_speed) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+ uint32_t ul_clk;\r
+ \r
+ if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+ return GMAC_INVALID;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+ } else {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+ }\r
+ ;\r
+ p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return 1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_status Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+ p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_status Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+ p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_addr Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+ p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_addr Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+ p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_source Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+ p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_source Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+ p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_reg_addr Register address.\r
+ * \param uc_rw 1 to Read, 0 to write.\r
+ * \param us_data Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+ uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+ uint16_t us_data)\r
+{\r
+ /* Wait until bus idle */\r
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+ /* Write maintain register */\r
+ p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+ | GMAC_MAN_CLTTO \r
+ | GMAC_MAN_PHYA(uc_phy_addr)\r
+ | GMAC_MAN_REGA(uc_reg_addr)\r
+ | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+ | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+ /* Wait until bus idle */\r
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+ /* Return data */\r
+ return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_hash_top Hash top.\r
+ * \param ul_hash_bottom Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+ uint32_t ul_hash_bottom)\r
+{\r
+ p_gmac->GMAC_HRB = ul_hash_bottom;\r
+ p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ull_hash 64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+ p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+ p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param p_mac_addr GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+ uint8_t* p_mac_addr)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+ | (p_mac_addr[2] << 16)\r
+ | (p_mac_addr[1] << 8)\r
+ | (p_mac_addr[0]);\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+ | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param ul_mac_top GMAC top address.\r
+ * \param ul_mac_bottom GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+ uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param ull_mac 64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+ uint64_t ull_mac)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param mode Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+ switch (mode) {\r
+ case GMAC_PHY_MII:\r
+ case GMAC_PHY_RMII:\r
+ p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+ break;\r
+\r
+ default:\r
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+ break;\r
+ }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+ uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+ uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+ gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+ uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+ uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_tx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS 16\r
+ * #define GMAC_TX_BUFFERS 8\r
+ * #define MAC_PHY_RETRY_MAX 1000000\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR1 0x04\r
+ * #define ETHERNET_CONF_ETHADDR2 0x25\r
+ * #define ETHERNET_CONF_ETHADDR3 0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4 0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5 0x02\r
+ * #define ETHERNET_CONF_IPADDR0 192\r
+ * #define ETHERNET_CONF_IPADDR1 168\r
+ * #define ETHERNET_CONF_IPADDR2 0\r
+ * #define ETHERNET_CONF_IPADDR3 2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
+ * #define ETHERNET_CONF_NET_MASK0 255\r
+ * #define ETHERNET_CONF_NET_MASK1 255\r
+ * #define ETHERNET_CONF_NET_MASK2 255\r
+ * #define ETHERNET_CONF_NET_MASK3 0\r
+ * #define ETH_PHY_MODE ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ * void gmac_init(void)\r
+ * {\r
+ * sysclk_init();\r
+ *\r
+ * board_init();\r
+ *\r
+ * pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ * gmac_option.uc_copy_all_frame = 0;\r
+ * gmac_option.uc_no_boardcast = 0;\r
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ * gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ * NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \r
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least \r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ * - \code\r
+ * #define GMAC_RX_BUFFERS 16\r
+ * \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ * - \code\r
+ * #define GMAC_TX_BUFFERS 8\r
+ * \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ * - \code\r
+ * #define MAC_PHY_RETRY_MAX 1000000\r
+ * \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ * - \code\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR1 0x04\r
+ * #define ETHERNET_CONF_ETHADDR2 0x25\r
+ * #define ETHERNET_CONF_ETHADDR3 0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4 0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5 0x02\r
+ * \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ * is enabled, this configuration is not effected.\r
+ * - \code\r
+ * #define ETHERNET_CONF_IPADDR0 192\r
+ * #define ETHERNET_CONF_IPADDR1 168\r
+ * #define ETHERNET_CONF_IPADDR2 0\r
+ * #define ETHERNET_CONF_IPADDR3 2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
+ * #define ETHERNET_CONF_NET_MASK0 255\r
+ * #define ETHERNET_CONF_NET_MASK1 255\r
+ * #define ETHERNET_CONF_NET_MASK2 255\r
+ * #define ETHERNET_CONF_NET_MASK3 0\r
+ * \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ * - \code\r
+ * #define ETH_PHY_MODE GMAC_PHY_MII\r
+ * \endcode\r
+ * -# Enable the system clock:\r
+ * - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ * - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ * - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ * - \code\r
+ * gmac_option.uc_copy_all_frame = 0;\r
+ * gmac_option.uc_no_boardcast = 0;\r
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ * gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ * - \code\r
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ * - \code\r
+ * NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ * - \code\r
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+ * -# The link will be established based on auto negotiation.\r
+ * - \code\r
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ * - \code\r
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+# define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+ /* Here below some code to study the types and\r
+ frequencies of GMAC interrupts. */\r
+ #define GMAC_IDX_RXUBR 0\r
+ #define GMAC_IDX_TUR 1\r
+ #define GMAC_IDX_RLEX 2\r
+ #define GMAC_IDX_TFC 3\r
+ #define GMAC_IDX_RCOMP 4\r
+ #define GMAC_IDX_TCOMP 5\r
+ #define GMAC_IDX_ROVR 6\r
+ #define GMAC_IDX_HRESP 7\r
+ #define GMAC_IDX_PFNZ 8\r
+ #define GMAC_IDX_PTZ 9\r
+\r
+ struct SGmacStats {\r
+ unsigned recvCount;\r
+ unsigned rovrCount;\r
+ unsigned bnaCount;\r
+ unsigned sendCount;\r
+ unsigned sovrCount;\r
+ unsigned incompCount;\r
+ unsigned truncCount;\r
+\r
+ unsigned intStatus[10];\r
+ };\r
+ extern struct SGmacStats gmacStats;\r
+\r
+ struct SIntPair {\r
+ const char *name;\r
+ unsigned mask;\r
+ int index;\r
+ };\r
+\r
+ #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+ static const struct SIntPair intPairs[] = {\r
+ { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+ { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */\r
+ { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */\r
+ { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+ { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+ { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+ { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */\r
+ { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+ { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */\r
+ { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */\r
+ };\r
+\r
+ void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 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
- *
- */
-
-#ifndef GMAC_H_INCLUDED
-#define GMAC_H_INCLUDED
-
-#include "compiler.h"
-#include "component/gmac.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_TX_UNITSIZE 1518 /**< 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_NULL, /** 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_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;
-
-/** 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 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 */
- 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 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;
-
-/** TX callback */
-typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status, uint8_t *puc_buffer);
-/** RX callback */
-typedef void (*gmac_dev_rx_cb_t) (uint32_t ul_status);
-/** 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.
- */
- uint8_t *p_tx_buffer;
- /** Pointer to allocated RX buffer */
- uint8_t *p_rx_buffer;
- /** Pointer to Rx TDs (must be 8-byte aligned) */
- gmac_rx_descriptor_t *p_rx_dscr;
- /** Pointer to Tx TDs (must be 8-byte aligned) */
- gmac_tx_descriptor_t *p_tx_dscr;
- /** Optional callback to be invoked once a frame has been received */
- gmac_dev_rx_cb_t func_rx_cb;
-#if( GMAC_USES_WAKEUP_CALLBACK )
- /** Optional callback to be invoked once several TDs have been released */
- gmac_dev_wakeup_cb_t func_wakeup_cb;
-#endif
-#if( GMAC_USES_TX_CALLBACK != 0 )
- /** Optional callback list to be invoked once TD has been processed */
- gmac_dev_tx_cb_t *func_tx_cb_list;
-#endif
- /** RX TD list size */
- uint32_t ul_rx_list_size;
- /** RX index for current processing TD */
- uint32_t ul_rx_idx;
- /** TX TD list size */
- uint32_t ul_tx_list_size;
- /** 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 uc_wakeup_threshold;
-} gmac_device_t;
-
-/**
- * \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)
-{
- 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 Read snapshot.
- *
- * \param p_gmac Pointer to the GMAC instance.
- */
-static inline void gmac_read_snapshot(Gmac* p_gmac)
-{
- p_gmac->GMAC_NCR |= GMAC_NCR_RDS;
-}
-
-/**
- * \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_configure(Gmac* p_gmac, uint32_t ul_cfg)
-{
- p_gmac->GMAC_NCFGR = ul_cfg;
-}
-
-/**
- * \brief Get network configuration.
- *
- * \param p_gmac Pointer to the GMAC instance.
- *
- * \return Network configuration.
- */
-static inline uint32_t gmac_get_configure(Gmac* p_gmac)
-{
- return p_gmac->GMAC_NCFGR;
-}
-
-
-/* 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 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;
-
- 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;
- }
- ;
- p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;
- 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 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,
- 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.
- */
-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;
- }
-}
-
-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);
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
- uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
- gmac_dev_rx_cb_t func_rx_cb);
-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);
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \page gmac_quickstart Quickstart guide for GMAC driver.
- *
- * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",
- * with step-by-step instructions on how to configure and use the driver in a
- * selection of use cases.
- *
- * The use cases contain several code fragments. The code fragments in the
- * steps for setup can be copied into a custom initialization function, while
- * the steps for usage can be copied into, e.g., the main application function.
- *
- * \section gmac_basic_use_case Basic use case
- * In the basic use case, the GMAC driver are configured for:
- * - PHY component KSZ8051MNL is used
- * - GMAC uses MII mode
- * - The number of receive buffer is 16
- * - The number of transfer buffer is 8
- * - MAC address is set to 00-04-25-1c-a0-02
- * - IP address is set to 192.168.0.2
- * - IP address is set to 192.168.0.2
- * - Gateway is set to 192.168.0.1
- * - Network mask is 255.255.255.0
- * - PHY operation max retry count is 1000000
- * - GMAC is configured to not support copy all frame and support broadcast
- * - The data will be read from the ethernet
- *
- * \section gmac_basic_use_case_setup Setup steps
- *
- * \subsection gmac_basic_use_case_setup_prereq Prerequisites
- * -# \ref sysclk_group "System Clock Management (sysclock)"
- * -# \ref pmc_group "Power Management Controller (pmc)"
- * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"
- *
- * \subsection gmac_basic_use_case_setup_code Example code
- * Content of conf_eth.h
- * \code
- * #define GMAC_RX_BUFFERS 16
- * #define GMAC_TX_BUFFERS 8
- * #define MAC_PHY_RETRY_MAX 1000000
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR1 0x04
- * #define ETHERNET_CONF_ETHADDR2 0x25
- * #define ETHERNET_CONF_ETHADDR3 0x1C
- * #define ETHERNET_CONF_ETHADDR4 0xA0
- * #define ETHERNET_CONF_ETHADDR5 0x02
- * #define ETHERNET_CONF_IPADDR0 192
- * #define ETHERNET_CONF_IPADDR1 168
- * #define ETHERNET_CONF_IPADDR2 0
- * #define ETHERNET_CONF_IPADDR3 2
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1
- * #define ETHERNET_CONF_NET_MASK0 255
- * #define ETHERNET_CONF_NET_MASK1 255
- * #define ETHERNET_CONF_NET_MASK2 255
- * #define ETHERNET_CONF_NET_MASK3 0
- * #define ETH_PHY_MODE ETH_PHY_MODE
- * \endcode
- *
- * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined
- * to trace the actual size of the data received.
- * \code
- * static gmac_device_t gs_gmac_dev;
- * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];
- *
- * uint32_t ul_frm_size;
- * \endcode
- *
- * Add to application C-file:
- * \code
- * void gmac_init(void)
- * {
- * sysclk_init();
- *
- * board_init();
- *
- * pmc_enable_periph_clk(ID_GMAC);
- *
- * gmac_option.uc_copy_all_frame = 0;
- * gmac_option.uc_no_boardcast = 0;
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- * gs_gmac_dev.p_hw = GMAC;
- *
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- *
- * NVIC_EnableIRQ(GMAC_IRQn);
- *
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- *
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- *
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \subsection gmac_basic_use_case_setup_flow Workflow
- * - Ensure that conf_eth.h is present and contains the
- * following configuration symbol. This configuration file is used
- * by the driver and should not be included by the application.
- * -# Define the receiving buffer size used in the internal GMAC driver.
- * The buffer size used for RX is GMAC_RX_BUFFERS * 128.
- * If it was supposed receiving a large number of frame, the
- * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept
- * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least
- * (2048/128)=16, and as there are additional frames coming, a preferred
- * number is 24 depending on a normal Ethernet throughput.
- * - \code
- * #define GMAC_RX_BUFFERS 16
- * \endcode
- * -# Define the transmitting buffer size used in the internal GMAC driver.
- * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.
- * - \code
- * #define GMAC_TX_BUFFERS 8
- * \endcode
- * -# Define maximum retry time for a PHY read/write operation.
- * - \code
- * #define MAC_PHY_RETRY_MAX 1000000
- * \endcode
- * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved
- * for ATMEL, application should always change this address to its' own.
- * - \code
- * #define ETHERNET_CONF_ETHADDR0 0x00
- * #define ETHERNET_CONF_ETHADDR1 0x04
- * #define ETHERNET_CONF_ETHADDR2 0x25
- * #define ETHERNET_CONF_ETHADDR3 0x1C
- * #define ETHERNET_CONF_ETHADDR4 0xA0
- * #define ETHERNET_CONF_ETHADDR5 0x02
- * \endcode
- * -# Define the IP address configration used in the application. When DHCP
- * is enabled, this configuration is not effected.
- * - \code
- * #define ETHERNET_CONF_IPADDR0 192
- * #define ETHERNET_CONF_IPADDR1 168
- * #define ETHERNET_CONF_IPADDR2 0
- * #define ETHERNET_CONF_IPADDR3 2
- * #define ETHERNET_CONF_GATEWAY_ADDR0 192
- * #define ETHERNET_CONF_GATEWAY_ADDR1 168
- * #define ETHERNET_CONF_GATEWAY_ADDR2 0
- * #define ETHERNET_CONF_GATEWAY_ADDR3 1
- * #define ETHERNET_CONF_NET_MASK0 255
- * #define ETHERNET_CONF_NET_MASK1 255
- * #define ETHERNET_CONF_NET_MASK2 255
- * #define ETHERNET_CONF_NET_MASK3 0
- * \endcode
- * -# Configure the PHY maintainance interface.
- * - \code
- * #define ETH_PHY_MODE GMAC_PHY_MII
- * \endcode
- * -# Enable the system clock:
- * - \code sysclk_init(); \endcode
- * -# Enable PIO configurations for GMAC:
- * - \code board_init(); \endcode
- * -# Enable PMC clock for GMAC:
- * - \code pmc_enable_periph_clk(ID_GMAC); \endcode
- * -# Set the GMAC options; it's set to copy all frame and support broadcast:
- * - \code
- * gmac_option.uc_copy_all_frame = 0;
- * gmac_option.uc_no_boardcast = 0;
- * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- * gs_gmac_dev.p_hw = GMAC;
- * \endcode
- * -# Initialize GMAC device with the filled option:
- * - \code
- * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- * \endcode
- * -# Enable the interrupt service for GMAC:
- * - \code
- * NVIC_EnableIRQ(GMAC_IRQn);
- * \endcode
- * -# Initialize the PHY component:
- * - \code
- * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- * \endcode
- * -# The link will be established based on auto negotiation.
- * - \code
- * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- * \endcode
- * -# Establish the ethernet link; the network can be worked from now on:
- * - \code
- * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \section gmac_basic_use_case_usage Usage steps
- * \subsection gmac_basic_use_case_usage_code Example code
- * Add to, e.g., main loop in application C-file:
- * \code
- * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
- * \endcode
- *
- * \subsection gmac_basic_use_case_usage_flow Workflow
- * -# Start reading the data from the ethernet:
- * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
- */
-
-# 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 */
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ * Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+#include "component/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+ last few bits are zero. These bits have special meaning for the GMAC\r
+ peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC\r
+#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */\r
+#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX 1536\r
+\r
+#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */\r
+#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M 0\r
+#define GMAC_SPEED_100M 1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+ GMAC_OK = 0, /** 0 Operation OK */\r
+ GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */\r
+ GMAC_TX_BUSY, /** 2 TX in progress */\r
+ GMAC_RX_NULL, /** 3 No data received */\r
+ GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */\r
+ GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */\r
+ GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+ GMAC_PHY_MII = 0, /** MII mode */\r
+ GMAC_PHY_RMII = 1, /** Reduced MII mode */\r
+ GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+ union gmac_rx_addr {\r
+ uint32_t val;\r
+ struct gmac_rx_addr_bm {\r
+ uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+ b_wrap:1, /**< Marks last descriptor in receive buffer */\r
+ addr_dw:30; /**< Address in number of DW */\r
+ } bm;\r
+ } addr; /**< Address, Wrap & Ownership */\r
+ union gmac_rx_status {\r
+ uint32_t val;\r
+ struct gmac_rx_status_bm {\r
+ uint32_t len:13, /** 0..12 Length of frame including FCS */\r
+ b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */\r
+ b_sof:1, /** 14 Start of frame */\r
+ b_eof:1, /** 15 End of frame */\r
+ b_cfi:1, /** 16 Concatenation Format Indicator */\r
+ vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */\r
+ b_priority_detected:1, /** 20 Priority tag detected */\r
+ b_vlan_detected:1, /** 21 VLAN tag detected */\r
+ b_type_id_match:2, /** 22..23 Type ID match */\r
+ b_checksumoffload:1, /** 24 Checksum offload specific function */\r
+ b_addrmatch:2, /** 25..26 Address register match */\r
+ b_ext_addr_match:1, /** 27 External address match found */\r
+ reserved:1, /** 28 */\r
+ b_uni_hash_match:1, /** 29 Unicast hash match */\r
+ b_multi_hash_match:1, /** 30 Multicast hash match */\r
+ b_boardcast_detect:1; /** 31 Global broadcast address detected */\r
+ } bm;\r
+ } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+ uint32_t addr;\r
+ union gmac_tx_status {\r
+ uint32_t val;\r
+ struct gmac_tx_status_bm {\r
+ uint32_t len:14, /** 0..13 Length of buffer */\r
+ reserved:1, /** 14 */\r
+ b_last_buffer:1, /** 15 Last buffer (in the current frame) */\r
+ b_no_crc:1, /** 16 No CRC */\r
+ reserved1:3, /** 17..19 */\r
+ b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+ reserved2:3, /** 23..25 */\r
+ b_lco:1, /** 26 Late collision, transmit error detected */\r
+ b_exhausted:1, /** 27 Buffer exhausted in mid frame */\r
+ b_underrun:1, /** 28 Transmit underrun */\r
+ b_error:1, /** 29 Retry limit exceeded, error detected */\r
+ b_wrap:1, /** 30 Marks last descriptor in TD list */\r
+ b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+ } bm;\r
+ } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+ /* Enable/Disable CopyAllFrame */\r
+ uint8_t uc_copy_all_frame;\r
+ /* Enable/Disable NoBroadCast */\r
+ uint8_t uc_no_boardcast;\r
+ /* MAC address */\r
+ uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** TX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status, uint8_t *puc_buffer);\r
+/** RX callback */\r
+typedef void (*gmac_dev_rx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+ /** Pointer to HW register base */\r
+ Gmac *p_hw;\r
+ /**\r
+ * Pointer to allocated TX buffer.\r
+ * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+ * 1K Boundaries.\r
+ * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+ * of the address shall be set to 0.\r
+ */\r
+ uint8_t *p_tx_buffer;\r
+ /** Pointer to allocated RX buffer */\r
+ uint8_t *p_rx_buffer;\r
+ /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+ gmac_rx_descriptor_t *p_rx_dscr;\r
+ /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+ gmac_tx_descriptor_t *p_tx_dscr;\r
+ /** Optional callback to be invoked once a frame has been received */\r
+ gmac_dev_rx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+ /** Optional callback to be invoked once several TDs have been released */\r
+ gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+ /** Optional callback list to be invoked once TD has been processed */\r
+ gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+ /** RX TD list size */\r
+ uint32_t ul_rx_list_size;\r
+ /** RX index for current processing TD */\r
+ uint32_t ul_rx_idx;\r
+ /** TX TD list size */\r
+ uint32_t ul_tx_list_size;\r
+ /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+ int32_t l_tx_head;\r
+ /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+ int32_t l_tx_tail;\r
+\r
+ /** Number of free TD before wakeup callback is invoked */\r
+ uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_ncr Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+ p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+ uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+ } else {\r
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+ p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_cfg Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+ p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+ p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+ if (uc_speed) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+ uint32_t ul_clk;\r
+\r
+ if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+ return GMAC_INVALID;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+ } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+ } else {\r
+ ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+ }\r
+ ;\r
+ p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+ return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_enable 0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+ if (uc_enable) {\r
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+ } else {\r
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+ }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return 1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_status Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+ p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_status Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+ p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_addr Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+ p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_addr Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+ p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_source Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+ p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_source Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+ p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+ return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_reg_addr Register address.\r
+ * \param uc_rw 1 to Read, 0 to write.\r
+ * \param us_data Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+ uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+ uint16_t us_data)\r
+{\r
+ /* Wait until bus idle */\r
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+ /* Write maintain register */\r
+ p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+ | GMAC_MAN_CLTTO\r
+ | GMAC_MAN_PHYA(uc_phy_addr)\r
+ | GMAC_MAN_REGA(uc_reg_addr)\r
+ | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+ | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+ /* Wait until bus idle */\r
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+ /* Return data */\r
+ return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ul_hash_top Hash top.\r
+ * \param ul_hash_bottom Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+ uint32_t ul_hash_bottom)\r
+{\r
+ p_gmac->GMAC_HRB = ul_hash_bottom;\r
+ p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param ull_hash 64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+ p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+ p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param p_mac_addr GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+ uint8_t* p_mac_addr)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+ | (p_mac_addr[2] << 16)\r
+ | (p_mac_addr[1] << 8)\r
+ | (p_mac_addr[0]);\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+ | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param ul_mac_top GMAC top address.\r
+ * \param ul_mac_bottom GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+ uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param uc_index GMAC specific address register index.\r
+ * \param ull_mac 64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+ uint64_t ull_mac)\r
+{\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac Pointer to the GMAC instance.\r
+ * \param mode Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+ switch (mode) {\r
+ case GMAC_PHY_MII:\r
+ case GMAC_PHY_RMII:\r
+ p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+ break;\r
+\r
+ default:\r
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+ break;\r
+ }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+ uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+ uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+ gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+ uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+ uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_rx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+ gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS 16\r
+ * #define GMAC_TX_BUFFERS 8\r
+ * #define MAC_PHY_RETRY_MAX 1000000\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR1 0x04\r
+ * #define ETHERNET_CONF_ETHADDR2 0x25\r
+ * #define ETHERNET_CONF_ETHADDR3 0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4 0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5 0x02\r
+ * #define ETHERNET_CONF_IPADDR0 192\r
+ * #define ETHERNET_CONF_IPADDR1 168\r
+ * #define ETHERNET_CONF_IPADDR2 0\r
+ * #define ETHERNET_CONF_IPADDR3 2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
+ * #define ETHERNET_CONF_NET_MASK0 255\r
+ * #define ETHERNET_CONF_NET_MASK1 255\r
+ * #define ETHERNET_CONF_NET_MASK2 255\r
+ * #define ETHERNET_CONF_NET_MASK3 0\r
+ * #define ETH_PHY_MODE ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ * void gmac_init(void)\r
+ * {\r
+ * sysclk_init();\r
+ *\r
+ * board_init();\r
+ *\r
+ * pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ * gmac_option.uc_copy_all_frame = 0;\r
+ * gmac_option.uc_no_boardcast = 0;\r
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ * gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ * NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ *\r
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least\r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ * - \code\r
+ * #define GMAC_RX_BUFFERS 16\r
+ * \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ * - \code\r
+ * #define GMAC_TX_BUFFERS 8\r
+ * \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ * - \code\r
+ * #define MAC_PHY_RETRY_MAX 1000000\r
+ * \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ * - \code\r
+ * #define ETHERNET_CONF_ETHADDR0 0x00\r
+ * #define ETHERNET_CONF_ETHADDR1 0x04\r
+ * #define ETHERNET_CONF_ETHADDR2 0x25\r
+ * #define ETHERNET_CONF_ETHADDR3 0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4 0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5 0x02\r
+ * \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ * is enabled, this configuration is not effected.\r
+ * - \code\r
+ * #define ETHERNET_CONF_IPADDR0 192\r
+ * #define ETHERNET_CONF_IPADDR1 168\r
+ * #define ETHERNET_CONF_IPADDR2 0\r
+ * #define ETHERNET_CONF_IPADDR3 2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0 192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1 168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2 0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3 1\r
+ * #define ETHERNET_CONF_NET_MASK0 255\r
+ * #define ETHERNET_CONF_NET_MASK1 255\r
+ * #define ETHERNET_CONF_NET_MASK2 255\r
+ * #define ETHERNET_CONF_NET_MASK3 0\r
+ * \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ * - \code\r
+ * #define ETH_PHY_MODE GMAC_PHY_MII\r
+ * \endcode\r
+ * -# Enable the system clock:\r
+ * - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ * - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ * - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ * - \code\r
+ * gmac_option.uc_copy_all_frame = 0;\r
+ * gmac_option.uc_no_boardcast = 0;\r
+ * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ * gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ * - \code\r
+ * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ * - \code\r
+ * NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ * - \code\r
+ * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+ * -# The link will be established based on auto negotiation.\r
+ * - \code\r
+ * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ * - \code\r
+ * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+# define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+ /* Here below some code to study the types and\r
+ frequencies of GMAC interrupts. */\r
+ #define GMAC_IDX_RXUBR 0\r
+ #define GMAC_IDX_TUR 1\r
+ #define GMAC_IDX_RLEX 2\r
+ #define GMAC_IDX_TFC 3\r
+ #define GMAC_IDX_RCOMP 4\r
+ #define GMAC_IDX_TCOMP 5\r
+ #define GMAC_IDX_ROVR 6\r
+ #define GMAC_IDX_HRESP 7\r
+ #define GMAC_IDX_PFNZ 8\r
+ #define GMAC_IDX_PTZ 9\r
+\r
+ struct SGmacStats {\r
+ unsigned recvCount;\r
+ unsigned rovrCount;\r
+ unsigned bnaCount;\r
+ unsigned sendCount;\r
+ unsigned sovrCount;\r
+ unsigned incompCount;\r
+ unsigned truncCount;\r
+\r
+ unsigned intStatus[10];\r
+ };\r
+ extern struct SGmacStats gmacStats;\r
+\r
+ struct SIntPair {\r
+ const char *name;\r
+ unsigned mask;\r
+ int index;\r
+ };\r
+\r
+ #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+ static const struct SIntPair intPairs[] = {\r
+ { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+ { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */\r
+ { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */\r
+ { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+ { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+ { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+ { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */\r
+ { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+ { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */\r
+ { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */\r
+ };\r
+\r
+ void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
-/*
-FreeRTOS+TCP V2.0.11
-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>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* Hardware abstraction. */
-#include "FreeRTOS_IO.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "NetworkBufferManagement.h"
-
-/* Driver includes. */
-#include "lpc17xx_emac.h"
-#include "lpc17xx_pinsel.h"
-
-/* Demo includes. */
-#include "NetworkInterface.h"
-
-#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* When a packet is ready to be sent, if it cannot be sent immediately then the
-task performing the transmit will block for niTX_BUFFER_FREE_WAIT
-milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
-up. */
-#define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) )
-#define niMAX_TX_ATTEMPTS ( 5 )
-
-/* The length of the queue used to send interrupt status words from the
-interrupt handler to the deferred handler task. */
-#define niINTERRUPT_QUEUE_LENGTH ( 10 )
-
-/*-----------------------------------------------------------*/
-
-/*
- * A deferred interrupt handler task that processes
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* The queue used to communicate Ethernet events with the IP task. */
-extern QueueHandle_t xNetworkEventQueue;
-
-/* The semaphore used to wake the deferred interrupt handler task when an Rx
-interrupt is received. */
-static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-EMAC_CFG_Type Emac_Config;
-PINSEL_CFG_Type xPinConfig;
-BaseType_t xStatus, xReturn;
-extern uint8_t ucMACAddress[ 6 ];
-
- /* Enable Ethernet Pins */
- boardCONFIGURE_ENET_PINS( xPinConfig );
-
- Emac_Config.Mode = EMAC_MODE_AUTO;
- Emac_Config.pbEMAC_Addr = ucMACAddress;
- xStatus = EMAC_Init( &Emac_Config );
-
- LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
-
- if( xStatus != ERROR )
- {
- vSemaphoreCreateBinary( xEMACRxEventSemaphore );
- configASSERT( xEMACRxEventSemaphore );
-
- /* The handler task is created at the highest possible priority to
- ensure the interrupt handler can return directly to it. */
- xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
-
- /* Enable the interrupt and set its priority to the minimum
- interrupt priority. */
- NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
- NVIC_EnableIRQ( ENET_IRQn );
-
- xReturn = pdPASS;
- }
- else
- {
- xReturn = pdFAIL;
- }
-
- configASSERT( xStatus != ERROR );
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
-BaseType_t xReturn = pdFAIL;
-int32_t x;
-extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
-extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
-
-
- /* Attempt to obtain access to a Tx buffer. */
- for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
- {
- if( EMAC_CheckTransmitIndex() == TRUE )
- {
- /* Will the data fit in the Tx buffer? */
- if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
- {
- /* Assign the buffer to the Tx descriptor that is now known to
- be free. */
- EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
-
- /* The EMAC now owns the buffer. */
- pxNetworkBuffer->pucBuffer = NULL;
-
- /* Initiate the Tx. */
- EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
- iptraceNETWORK_INTERFACE_TRANSMIT();
-
- /* The Tx has been initiated. */
- xReturn = pdPASS;
- }
- break;
- }
- else
- {
- vTaskDelay( niTX_BUFFER_FREE_WAIT );
- }
- }
-
- /* Finished with the network buffer. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void ENET_IRQHandler( void )
-{
-uint32_t ulInterruptCause;
-
- while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
- {
- /* Clear the interrupt. */
- LPC_EMAC->IntClear = ulInterruptCause;
-
- /* Clear fatal error conditions. NOTE: The driver does not clear all
- errors, only those actually experienced. For future reference, range
- errors are not actually errors so can be ignored. */
- if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
- {
- LPC_EMAC->Command |= EMAC_CR_TX_RES;
- }
-
- /* Unblock the deferred interrupt handler task if the event was an
- Rx. */
- if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
- {
- xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
- }
- }
-
- /* ulInterruptCause is used for convenience here. A context switch is
- wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
- compiler warning. */
- portEND_SWITCHING_ISR( ulInterruptCause );
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-size_t xDataLength;
-const uint16_t usCRCLength = 4;
-NetworkBufferDescriptor_t *pxNetworkBuffer;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
-/* This is not included in the header file for some reason. */
-extern uint8_t *EMAC_NextPacketToRead( void );
-
- ( void ) pvParameters;
- configASSERT( xEMACRxEventSemaphore );
-
- for( ;; )
- {
- /* Wait for the EMAC interrupt to indicate that another packet has been
- received. The while() loop is only needed if INCLUDE_vTaskSuspend is
- set to 0 in FreeRTOSConfig.h. */
- while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
-
- /* At least one packet has been received. */
- while( EMAC_CheckReceiveIndex() != FALSE )
- {
- /* Obtain the length, minus the CRC. The CRC is four bytes
- but the length is already minus 1. */
- xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
-
- if( xDataLength > 0U )
- {
- /* Obtain a network buffer to pass this data into the
- stack. No storage is required as the network buffer
- will point directly to the buffer that already holds
- the received data. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );
-
- if( pxNetworkBuffer != NULL )
- {
- pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
- pxNetworkBuffer->xDataLength = xDataLength;
- 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 )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- iptraceETHERNET_RX_EVENT_LOST();
- }
- }
- else
- {
- iptraceETHERNET_RX_EVENT_LOST();
- }
-
- iptraceNETWORK_INTERFACE_RECEIVE();
- }
-
- /* Release the frame. */
- EMAC_UpdateRxConsumeIndex();
- }
- }
-}
-/*-----------------------------------------------------------*/
-
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware abstraction. */\r
+#include "FreeRTOS_IO.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Driver includes. */\r
+#include "lpc17xx_emac.h"\r
+#include "lpc17xx_pinsel.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) )\r
+#define niMAX_TX_ATTEMPTS ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+EMAC_CFG_Type Emac_Config;\r
+PINSEL_CFG_Type xPinConfig;\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+ /* Enable Ethernet Pins */\r
+ boardCONFIGURE_ENET_PINS( xPinConfig );\r
+\r
+ Emac_Config.Mode = EMAC_MODE_AUTO;\r
+ Emac_Config.pbEMAC_Addr = ucMACAddress;\r
+ xStatus = EMAC_Init( &Emac_Config );\r
+\r
+ LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );\r
+\r
+ if( xStatus != ERROR )\r
+ {\r
+ vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+ configASSERT( xEMACRxEventSemaphore );\r
+\r
+ /* The handler task is created at the highest possible priority to\r
+ ensure the interrupt handler can return directly to it. */\r
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+\r
+ /* Enable the interrupt and set its priority to the minimum\r
+ interrupt priority. */\r
+ NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+ NVIC_EnableIRQ( ENET_IRQn );\r
+\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ configASSERT( xStatus != ERROR );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+int32_t x;\r
+extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );\r
+extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );\r
+\r
+\r
+ /* Attempt to obtain access to a Tx buffer. */\r
+ for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )\r
+ {\r
+ if( EMAC_CheckTransmitIndex() == TRUE )\r
+ {\r
+ /* Will the data fit in the Tx buffer? */\r
+ if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */\r
+ {\r
+ /* Assign the buffer to the Tx descriptor that is now known to\r
+ be free. */\r
+ EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );\r
+\r
+ /* The EMAC now owns the buffer. */\r
+ pxNetworkBuffer->pucBuffer = NULL;\r
+\r
+ /* Initiate the Tx. */\r
+ EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+ /* The Tx has been initiated. */\r
+ xReturn = pdPASS;\r
+ }\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ vTaskDelay( niTX_BUFFER_FREE_WAIT );\r
+ }\r
+ }\r
+\r
+ /* Finished with the network buffer. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void ENET_IRQHandler( void )\r
+{\r
+uint32_t ulInterruptCause;\r
+\r
+ while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )\r
+ {\r
+ /* Clear the interrupt. */\r
+ LPC_EMAC->IntClear = ulInterruptCause;\r
+\r
+ /* Clear fatal error conditions. NOTE: The driver does not clear all\r
+ errors, only those actually experienced. For future reference, range\r
+ errors are not actually errors so can be ignored. */\r
+ if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )\r
+ {\r
+ LPC_EMAC->Command |= EMAC_CR_TX_RES;\r
+ }\r
+\r
+ /* Unblock the deferred interrupt handler task if the event was an\r
+ Rx. */\r
+ if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )\r
+ {\r
+ xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );\r
+ }\r
+ }\r
+\r
+ /* ulInterruptCause is used for convenience here. A context switch is\r
+ wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a\r
+ compiler warning. */\r
+ portEND_SWITCHING_ISR( ulInterruptCause );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+size_t xDataLength;\r
+const uint16_t usCRCLength = 4;\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+/* This is not included in the header file for some reason. */\r
+extern uint8_t *EMAC_NextPacketToRead( void );\r
+\r
+ ( void ) pvParameters;\r
+ configASSERT( xEMACRxEventSemaphore );\r
+\r
+ for( ;; )\r
+ {\r
+ /* Wait for the EMAC interrupt to indicate that another packet has been\r
+ received. The while() loop is only needed if INCLUDE_vTaskSuspend is\r
+ set to 0 in FreeRTOSConfig.h. */\r
+ while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );\r
+\r
+ /* At least one packet has been received. */\r
+ while( EMAC_CheckReceiveIndex() != FALSE )\r
+ {\r
+ /* Obtain the length, minus the CRC. The CRC is four bytes\r
+ but the length is already minus 1. */\r
+ xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );\r
+\r
+ if( xDataLength > 0U )\r
+ {\r
+ /* Obtain a network buffer to pass this data into the\r
+ stack. No storage is required as the network buffer\r
+ will point directly to the buffer that already holds\r
+ the received data. */\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );\r
+\r
+ if( pxNetworkBuffer != NULL )\r
+ {\r
+ pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();\r
+ pxNetworkBuffer->xDataLength = xDataLength;\r
+ xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+ /* Data was received and stored. Send a message to the IP\r
+ task to let it know. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ }\r
+\r
+ /* Release the frame. */\r
+ EMAC_UpdateRxConsumeIndex();\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
-/*
-FreeRTOS+TCP V2.0.11
-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 "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* LPCOpen includes. */
-#include "chip.h"
-#include "lpc_phy.h"
-
-/* The size of the stack allocated to the task that handles Rx packets. */
-#define nwRX_TASK_STACK_SIZE 140
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
- receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 15000
-#endif
-
-#ifndef PHY_LS_LOW_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still low every second. */
- #define PHY_LS_LOW_CHECK_TIME_MS 1000
-#endif
-
-#ifndef configUSE_RMII
- #define configUSE_RMII 1
-#endif
-
-#ifndef configNUM_RX_DESCRIPTORS
- #error please define configNUM_RX_DESCRIPTORS in your FreeRTOSIPConfig.h
-#endif
-
-#ifndef configNUM_TX_DESCRIPTORS
- #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h
-#endif
-
-#ifndef NETWORK_IRQHandler
- #error NETWORK_IRQHandler must be defined to the name of the function that is installed in the interrupt vector table to handle Ethernet interrupts.
-#endif
-
-#if !defined( MAC_FF_HMC )
- /* Hash for multicast. */
- #define MAC_FF_HMC ( 1UL << 2UL )
-#endif
-
-#ifndef iptraceEMAC_TASK_STARTING
- #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
-#endif
-
-/* Define the bits of .STATUS that indicate a reception error. */
-#define nwRX_STATUS_ERROR_BITS \
- ( RDES_CE /* CRC Error */ | \
- RDES_RE /* Receive Error */ | \
- RDES_DE /* Descriptor Error */ | \
- RDES_RWT /* Receive Watchdog Timeout */ | \
- RDES_LC /* Late Collision */ | \
- RDES_OE /* Overflow Error */ | \
- RDES_SAF /* Source Address Filter Fail */ | \
- RDES_AFM /* Destination Address Filter Fail */ | \
- RDES_LE /* Length Error */ )
-
-/* Define the EMAC status bits that should trigger an interrupt. */
-#define nwDMA_INTERRUPT_MASK \
- ( DMA_IE_TIE /* Transmit interrupt enable */ | \
- DMA_IE_TSE /* Transmit stopped enable */ | \
- DMA_IE_OVE /* Overflow interrupt enable */ | \
- DMA_IE_RIE /* Receive interrupt enable */ | \
- DMA_IE_NIE /* Normal interrupt summary enable */ | \
- DMA_IE_AIE /* Abnormal interrupt summary enable */ | \
- DMA_IE_RUE /* Receive buffer unavailable enable */ | \
- DMA_IE_UNE /* Underflow interrupt enable. */ | \
- DMA_IE_TJE /* Transmit jabber timeout enable */ | \
- DMA_IE_RSE /* Received stopped enable */ | \
- DMA_IE_RWE /* Receive watchdog timeout enable */ | \
- DMA_IE_FBE )/* Fatal bus error enable */
-
-/* Interrupt events to process. Currently only the RX/TX events are 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 )
-
- /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
- driver will filter incoming packets and only pass the stack those packets it
- considers need processing. */
- #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
- #else
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
- #endif
-
-#if( ipconfigZERO_COPY_RX_DRIVER == 0 ) || ( ipconfigZERO_COPY_TX_DRIVER == 0 )
- #warning It is adviced to enable both macros
-#endif
-
-#ifndef configPLACE_IN_SECTION_RAM
- #define configPLACE_IN_SECTION_RAM
-/*
- #define configPLACE_IN_SECTION_RAM __attribute__ ((section(".ramfunc")))
-*/
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Delay function passed into the library. The implementation uses FreeRTOS
- * calls so the scheduler must be started before the driver can be used.
- */
-static void prvDelay( uint32_t ulMilliSeconds );
-
-/*
- * Initialises the Tx and Rx descriptors respectively.
- */
-static void prvSetupTxDescriptors( void );
-static void prvSetupRxDescriptors( void );
-
-/*
- * A task that processes received frames.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*
- * Sets up the MAC with the results of an auto-negotiation.
- */
-static BaseType_t prvSetLinkSpeed( void );
-
-/*
- * Generates a CRC for a MAC address that is then used to generate a hash index.
- */
-static uint32_t prvGenerateCRC32( const uint8_t *ucAddress );
-
-/*
- * Generates a hash index when setting a filter to permit a MAC address.
- */
-static uint32_t prvGetHashIndex( const uint8_t *ucAddress );
-
-/*
- * Update the hash table to allow a MAC address.
- */
-static void prvAddMACAddress( const uint8_t* ucMacAddress );
-
-/*
- * Sometimes the DMA will report received data as being longer than the actual
- * received from length. This function checks the reported length and corrects
- * if if necessary.
- */
-static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor );
-
-/*-----------------------------------------------------------*/
-
-/* Bit map of outstanding ETH interrupt events for processing. Currently only
-the Rx and Tx 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 uint32_t ulPHYLinkStatus = 0;
-
-/* Tx descriptors and index. */
-static ENET_ENHTXDESC_T xDMATxDescriptors[ configNUM_TX_DESCRIPTORS ];
-
-/* ulNextFreeTxDescriptor is declared volatile, because it is accessed from
-to different tasks. */
-static volatile uint32_t ulNextFreeTxDescriptor;
-static uint32_t ulTxDescriptorToClear;
-
-/* Rx descriptors and index. */
-static ENET_ENHRXDESC_T xDMARxDescriptors[ configNUM_RX_DESCRIPTORS ];
-static uint32_t ulNextRxDescriptorToProcess;
-
-/* Must be defined externally - the demo applications define this in main.c. */
-extern uint8_t ucMACAddress[ 6 ];
-
-/* The handle of the task that processes Rx packets. The handle is required so
-the task can be notified when new packets arrive. */
-static TaskHandle_t xRxHanderTask = NULL;
-
-#if( ipconfigUSE_LLMNR == 1 )
- static const uint8_t xLLMNR_MACAddress[] = { '\x01', '\x00', '\x5E', '\x00', '\x00', '\xFC' };
-#endif /* ipconfigUSE_LLMNR == 1 */
-
-/* xTXDescriptorSemaphore is a counting semaphore with
-a maximum count of ETH_TXBUFNB, which is the number of
-DMA TX descriptors. */
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-
-/*-----------------------------------------------------------*/
-
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xReturn = pdPASS;
-
- /* The interrupt will be turned on when a link is established. */
- NVIC_DisableIRQ( ETHERNET_IRQn );
-
- /* Disable receive and transmit DMA processes. */
- LPC_ETHERNET->DMA_OP_MODE &= ~( DMA_OM_ST | DMA_OM_SR );
-
- /* Disable packet reception. */
- LPC_ETHERNET->MAC_CONFIG &= ~( MAC_CFG_RE | MAC_CFG_TE );
-
- /* Call the LPCOpen function to initialise the hardware. */
- Chip_ENET_Init( LPC_ETHERNET );
-
- /* Save MAC address. */
- Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );
-
- /* Clear all MAC address hash entries. */
- LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;
- LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;
-
- #if( ipconfigUSE_LLMNR == 1 )
- {
- prvAddMACAddress( xLLMNR_MACAddress );
- }
- #endif /* ipconfigUSE_LLMNR == 1 */
-
- /* Promiscuous flag (PR) and Receive All flag (RA) set to zero. The
- registers MAC_HASHTABLE_[LOW|HIGH] will be loaded to allow certain
- multi-cast addresses. */
- LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_HMC;
-
- #if( configUSE_RMII == 1 )
- {
- if( lpc_phy_init( pdTRUE, prvDelay ) != SUCCESS )
- {
- xReturn = pdFAIL;
- }
- }
- #else
- {
- #warning This path has not been tested.
- if( lpc_phy_init( pdFALSE, prvDelay ) != SUCCESS )
- {
- xReturn = pdFAIL;
- }
- }
- #endif
-
- if( xReturn == pdPASS )
- {
- /* Guard against the task being created more than once and the
- descriptors being initialised more than once. */
- if( xRxHanderTask == NULL )
- {
- xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
- configASSERT( xReturn );
- }
-
- if( xTXDescriptorSemaphore == NULL )
- {
- /* 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 );
- }
-
- /* Enable MAC interrupts. */
- LPC_ETHERNET->DMA_INT_EN = nwDMA_INTERRUPT_MASK;
- }
-
- if( xReturn != pdFAIL )
- {
- /* Auto-negotiate was already started. Wait for it to complete. */
- xReturn = prvSetLinkSpeed();
-
- if( xReturn == pdPASS )
- {
- /* Initialise the descriptors. */
- prvSetupTxDescriptors();
- prvSetupRxDescriptors();
-
- /* Clear all interrupts. */
- LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;
-
- /* Enable receive and transmit DMA processes. */
- LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;
-
- /* Set Receiver / Transmitter Enable. */
- LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;
-
- /* Start receive polling. */
- LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
-
- /* Enable interrupts in the NVIC. */
- NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
- NVIC_EnableIRQ( ETHERNET_IRQn );
- }
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-#define niBUFFER_1_PACKET_SIZE 1536
-
-static __attribute__ ((section("._ramAHB32"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-
-uint8_t *ucRAMBuffer = ucNetworkPackets;
-uint32_t ul;
-
- for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
- {
- pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
- *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
- ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
- }
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-static void vClearTXBuffers()
-{
-uint32_t ulLastDescriptor = ulNextFreeTxDescriptor;
-size_t uxCount = ( ( size_t ) configNUM_TX_DESCRIPTORS ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- NetworkBufferDescriptor_t *pxNetworkBuffer;
- uint8_t *ucPayLoad;
-#endif
-
- /* This function is called after a TX-completion interrupt.
- It will release each Network Buffer used in xNetworkInterfaceOutput().
- 'uxCount' represents the number of descriptors given to DMA for transmission.
- After sending a packet, the DMA will clear the 'TDES_OWN' bit. */
- while( ( uxCount > ( size_t ) 0u ) && ( ( xDMATxDescriptors[ ulTxDescriptorToClear ].CTRLSTAT & TDES_OWN ) == 0 ) )
- {
- if( ( ulTxDescriptorToClear == ulLastDescriptor ) && ( uxCount != ( size_t ) configNUM_TX_DESCRIPTORS ) )
- {
- break;
- }
-
-
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- ucPayLoad = ( uint8_t * )xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD;
- if( ucPayLoad != NULL )
- {
- /* B1ADD points to a pucEthernetBuffer of a Network Buffer descriptor. */
- pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
-
- configASSERT( pxNetworkBuffer != NULL );
-
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
- xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD = ( uint32_t )0u;
- }
- }
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
-
- /* Move onto the next descriptor, wrapping if necessary. */
- ulTxDescriptorToClear++;
- if( ulTxDescriptorToClear >= configNUM_TX_DESCRIPTORS )
- {
- ulTxDescriptorToClear = 0;
- }
-
- uxCount--;
- /* Tell the counting semaphore that one more TX descriptor is available. */
- xSemaphoreGive( xTXDescriptorSemaphore );
- }
-}
-
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
-{
-BaseType_t xReturn = pdFAIL;
-const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 );
-
- /* Attempt to obtain access to a Tx descriptor. */
- do
- {
- if( xTXDescriptorSemaphore == NULL )
- {
- break;
- }
- if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
- {
- /* Time-out waiting for a free TX descriptor. */
- break;
- }
-
- /* If the descriptor is still owned by the DMA it can't be used. */
- if( ( xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT & TDES_OWN ) != 0 )
- {
- /* The semaphore was taken, the TX DMA-descriptor is still not available.
- Actually that should not occur, the 'TDES_OWN' was already confirmed low in vClearTXBuffers(). */
- xSemaphoreGive( xTXDescriptorSemaphore );
- }
- else
- {
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- /* bReleaseAfterSend should always be set when using the zero
- copy driver. */
- configASSERT( bReleaseAfterSend != pdFALSE );
-
- /* The DMA's descriptor to point directly to the data in the
- network buffer descriptor. The data is not copied. */
- xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD = ( uint32_t ) pxDescriptor->pucEthernetBuffer;
-
- /* The DMA descriptor will 'own' this Network Buffer,
- until it has been sent. So don't release it now. */
- bReleaseAfterSend = false;
- }
- #else
- {
- /* The data is copied from the network buffer descriptor into
- the DMA's descriptor. */
- memcpy( ( void * ) xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );
- }
- #endif
-
- xDMATxDescriptors[ ulNextFreeTxDescriptor ].BSIZE = ( uint32_t ) TDES_ENH_BS1( pxDescriptor->xDataLength );
-
- /* This descriptor is given back to the DMA. */
- xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT |= TDES_OWN;
-
- /* Ensure the DMA is polling Tx descriptors. */
- LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
-
- iptraceNETWORK_INTERFACE_TRANSMIT();
-
- /* Move onto the next descriptor, wrapping if necessary. */
- ulNextFreeTxDescriptor++;
- if( ulNextFreeTxDescriptor >= configNUM_TX_DESCRIPTORS )
- {
- ulNextFreeTxDescriptor = 0;
- }
-
- /* The Tx has been initiated. */
- xReturn = pdPASS;
- }
- } while( 0 );
-
- /* The buffer has been sent so can be released. */
- if( bReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvDelay( uint32_t ulMilliSeconds )
-{
- /* Ensure the scheduler was started before attempting to use the scheduler to
- create a delay. */
- configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING );
-
- vTaskDelay( pdMS_TO_TICKS( ulMilliSeconds ) );
-}
-/*-----------------------------------------------------------*/
-
-static void prvSetupTxDescriptors( void )
-{
-BaseType_t x;
-
- /* Start with Tx descriptors clear. */
- memset( ( void * ) xDMATxDescriptors, 0, sizeof( xDMATxDescriptors ) );
-
- /* Index to the next Tx descriptor to use. */
- ulNextFreeTxDescriptor = 0ul;
-
- /* Index to the next Tx descriptor to clear ( after transmission ). */
- ulTxDescriptorToClear = 0ul;
-
- for( x = 0; x < configNUM_TX_DESCRIPTORS; x++ )
- {
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- /* Nothing to do, B1ADD will be set when data is ready to transmit.
- Currently the memset above will have set it to NULL. */
- }
- #else
- {
- /* Allocate a buffer to the Tx descriptor. This is the most basic
- way of creating a driver as the data is then copied into the
- buffer. */
- xDMATxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );
-
- /* 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 );
- }
- #endif
-
- /* Buffers hold an entire frame so all buffers are both the start and
- end of a frame. */
- /* TDES_ENH_TCH Second Address Chained. */
- /* TDES_ENH_CIC(n) Checksum Insertion Control, tried but it does not work for the LPC18xx... */
- /* TDES_ENH_FS First Segment. */
- /* TDES_ENH_LS Last Segment. */
- /* TDES_ENH_IC Interrupt on Completion. */
- xDMATxDescriptors[ x ].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC( 3 ) | TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_IC;
- xDMATxDescriptors[ x ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ x + 1 ];
- }
-
- xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].CTRLSTAT |= TDES_ENH_TER;
- xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ 0 ];
-
- /* Point the DMA to the base of the descriptor list. */
- LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xDMATxDescriptors;
-}
-/*-----------------------------------------------------------*/
-
-static void prvSetupRxDescriptors( void )
-{
-BaseType_t x;
-#if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- NetworkBufferDescriptor_t *pxNetworkBuffer;
-#endif
-
- /* Index to the next Rx descriptor to use. */
- ulNextRxDescriptorToProcess = 0;
-
- /* Clear RX descriptor list. */
- memset( ( void * ) xDMARxDescriptors, 0, sizeof( xDMARxDescriptors ) );
-
- for( x = 0; x < configNUM_RX_DESCRIPTORS; x++ )
- {
- /* Allocate a buffer of the largest possible frame size as it is not
- known what size received frames will be. */
-
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- {
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 );
-
- /* During start-up there should be enough Network Buffers available,
- so it is safe to use configASSERT().
- In case this assert fails, please check: configNUM_RX_DESCRIPTORS,
- ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, and in case BufferAllocation_2.c
- is included, check the amount of available heap. */
- configASSERT( pxNetworkBuffer != NULL );
-
- /* Pass the actual buffer to DMA. */
- xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;
- }
- #else
- {
- /* All DMA descriptors are populated with permanent memory blocks.
- Their contents will be copy to Network Buffers. */
- xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );
- }
- #endif /* ipconfigZERO_COPY_RX_DRIVER */
-
- /* 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 );
-
- xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );
- xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;
-
- /* The descriptor is available for use by the DMA. */
- xDMARxDescriptors[ x ].STATUS = RDES_OWN;
- }
-
- /* RDES_ENH_RER Receive End of Ring. */
- xDMARxDescriptors[ ( configNUM_RX_DESCRIPTORS - 1 ) ].CTRL |= RDES_ENH_RER;
- xDMARxDescriptors[ configNUM_RX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ 0 ] );
-
- /* Point the DMA to the base of the descriptor list. */
- LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xDMARxDescriptors;
-}
-/*-----------------------------------------------------------*/
-configPLACE_IN_SECTION_RAM
-static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor )
-{
-size_t xExpectedLength;
-IPPacket_t *pxIPPacket;
-
- pxIPPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;
- /* Look at the actual length of the packet, translate it to a host-endial notation. */
- xExpectedLength = sizeof( EthernetHeader_t ) + ( size_t ) FreeRTOS_htons( pxIPPacket->xIPHeader.usLength );
-
- if( xExpectedLength == ( pxDescriptor->xDataLength + 4 ) )
- {
- pxDescriptor->xDataLength -= 4;
- }
- else
- {
- if( pxDescriptor->xDataLength > xExpectedLength )
- {
- pxDescriptor->xDataLength = ( size_t ) xExpectedLength;
- }
- }
-}
-/*-----------------------------------------------------------*/
-configPLACE_IN_SECTION_RAM
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xReturn;
-
- if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )
- {
- xReturn = pdFALSE;
- }
- else
- {
- xReturn = pdTRUE;
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-uint32_t ulDataAvailable;
-
-configPLACE_IN_SECTION_RAM
-static BaseType_t prvNetworkInterfaceInput()
-{
-BaseType_t xResult = pdFALSE;
-uint32_t ulStatus;
-eFrameProcessingResult_t eResult;
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
-const UBaseType_t uxMinimumBuffersRemaining = 3UL;
-uint16_t usLength;
-NetworkBufferDescriptor_t *pxDescriptor;
-#if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- NetworkBufferDescriptor_t *pxNewDescriptor;
-#endif /* ipconfigZERO_COPY_RX_DRIVER */
-#if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )
- IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-#endif
-
- /* Process each descriptor that is not still in use by the DMA. */
- ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;
- if( ( ulStatus & RDES_OWN ) == 0 )
- {
- /* Check packet for errors */
- if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 )
- {
- /* There is some reception error. */
- intCount[ 3 ]++;
- /* Clear error bits. */
- ulStatus &= ~( ( uint32_t )nwRX_STATUS_ERROR_BITS );
- }
- else
- {
- xResult++;
-
- eResult = ipCONSIDER_FRAME_FOR_PROCESSING( ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD ) );
- if( eResult == eProcessBuffer )
- {
- if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )
- {
- ulPHYLinkStatus |= PHY_LINK_CONNECTED;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (message received)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );
- }
-
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )
- {
- pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xDescriptorWaitTime );
- }
- else
- {
- /* Too risky to allocate a new Network Buffer. */
- pxNewDescriptor = NULL;
- }
- if( pxNewDescriptor != NULL )
- #else
- if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )
- #endif /* ipconfigZERO_COPY_RX_DRIVER */
- {
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- const uint8_t *pucBuffer;
- #endif
-
- /* Get the actual length. */
- usLength = RDES_FLMSK( ulStatus );
-
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
- {
- /* Replace the character buffer 'B1ADD'. */
- pucBuffer = ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD );
- xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer;
-
- /* 'B1ADD' contained the address of a 'pucEthernetBuffer' that
- belongs to a Network Buffer. Find the original Network Buffer. */
- pxDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
- /* This zero-copy driver makes sure that every 'xDMARxDescriptors' contains
- a reference to a Network Buffer at any time.
- In case it runs out of Network Buffers, a DMA buffer won't be replaced,
- and the received messages is dropped. */
- configASSERT( pxDescriptor != NULL );
- }
- #else
- {
- /* Create a buffer of exactly the required length. */
- pxDescriptor = pxGetNetworkBufferWithDescriptor( usLength, xDescriptorWaitTime );
- }
- #endif /* ipconfigZERO_COPY_RX_DRIVER */
-
- if( pxDescriptor != NULL )
- {
- pxDescriptor->xDataLength = ( size_t ) usLength;
- #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
- {
- /* Copy the data into the allocated buffer. */
- memcpy( ( void * ) pxDescriptor->pucEthernetBuffer, ( void * ) xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD, usLength );
- }
- #endif /* ipconfigZERO_COPY_RX_DRIVER */
- /* It is possible that more data was copied than
- actually makes up the frame. If this is the case
- adjust the length to remove any trailing bytes. */
- prvRemoveTrailingBytes( pxDescriptor );
-
- /* Pass the data to the TCP/IP task for processing. */
- xRxEvent.pvData = ( void * ) pxDescriptor;
- if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
- {
- /* Could not send the descriptor into the TCP/IP
- stack, it must be released. */
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
- else
- {
- iptraceNETWORK_INTERFACE_RECEIVE();
-
- /* The data that was available at the top of this
- loop has been sent, so is no longer available. */
- ulDataAvailable = pdFALSE;
- }
- }
- }
- }
- else
- {
- /* The packet is discarded as uninteresting. */
- ulDataAvailable = pdFALSE;
- }
- /* Got here because received data was sent to the IP task or the
- data contained an error and was discarded. Give the descriptor
- back to the DMA. */
- xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS = ulStatus | RDES_OWN;
-
- /* Move onto the next descriptor. */
- ulNextRxDescriptorToProcess++;
- if( ulNextRxDescriptorToProcess >= configNUM_RX_DESCRIPTORS )
- {
- ulNextRxDescriptorToProcess = 0;
- }
-
- ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;
- } /* if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 ) */
- } /* if( ( ulStatus & RDES_OWN ) == 0 ) */
-
- /* Restart receive polling. */
- LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
-
- return xResult;
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-void NETWORK_IRQHandler( void )
-{
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-uint32_t ulDMAStatus;
-const uint32_t ulRxInterruptMask =
- DMA_ST_RI | /* Receive interrupt */
- DMA_ST_RU; /* Receive buffer unavailable */
-const uint32_t ulTxInterruptMask =
- DMA_ST_TI | /* Transmit interrupt */
- DMA_ST_TPS; /* Transmit process stopped */
-
- configASSERT( xRxHanderTask );
-
- /* Get pending interrupts. */
- ulDMAStatus = LPC_ETHERNET->DMA_STAT;
-
- /* RX group interrupt(s). */
- if( ( ulDMAStatus & ulRxInterruptMask ) != 0x00 )
- {
- /* Remember that an RX event has happened. */
- ulISREvents |= EMAC_IF_RX_EVENT;
- vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
- intCount[ 0 ]++;
- }
-
- /* TX group interrupt(s). */
- if( ( ulDMAStatus & ulTxInterruptMask ) != 0x00 )
- {
- /* Remember that a TX event has happened. */
- ulISREvents |= EMAC_IF_TX_EVENT;
- vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
- intCount[ 1 ]++;
- }
-
- /* Test for 'Abnormal interrupt summary'. */
- if( ( ulDMAStatus & DMA_ST_AIE ) != 0x00 )
- {
- /* The trace macro must be written such that it can be called from
- an interrupt. */
- iptraceETHERNET_RX_EVENT_LOST();
- }
-
- /* Clear pending interrupts */
- LPC_ETHERNET->DMA_STAT = ulDMAStatus;
-
- /* Context switch needed? */
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvSetLinkSpeed( void )
-{
-BaseType_t xReturn = pdFAIL;
-TickType_t xTimeOnEntering;
-uint32_t ulPhyStatus;
-const TickType_t xAutoNegotiateDelay = pdMS_TO_TICKS( 5000UL );
-
- /* Ensure polling does not starve lower priority tasks by temporarily
- setting the priority of this task to that of the idle task. */
- vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
-
- xTimeOnEntering = xTaskGetTickCount();
- do
- {
- ulPhyStatus = lpcPHYStsPoll();
- if( ( ulPhyStatus & PHY_LINK_CONNECTED ) != 0x00 )
- {
- /* Set interface speed and duplex. */
- if( ( ulPhyStatus & PHY_LINK_SPEED100 ) != 0x00 )
- {
- Chip_ENET_SetSpeed( LPC_ETHERNET, 1 );
- }
- else
- {
- Chip_ENET_SetSpeed( LPC_ETHERNET, 0 );
- }
-
- if( ( ulPhyStatus & PHY_LINK_FULLDUPLX ) != 0x00 )
- {
- Chip_ENET_SetDuplex( LPC_ETHERNET, true );
- }
- else
- {
- Chip_ENET_SetDuplex( LPC_ETHERNET, false );
- }
-
- xReturn = pdPASS;
- break;
- }
- } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xAutoNegotiateDelay );
-
- /* Reset the priority of this task back to its original value. */
- vTaskPrioritySet( NULL, ipconfigIP_TASK_PRIORITY );
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvGenerateCRC32( const uint8_t *ucAddress )
-{
-unsigned int j;
-const uint32_t Polynomial = 0xEDB88320;
-uint32_t crc = ~0ul;
-const uint8_t *pucCurrent = ( const uint8_t * ) ucAddress;
-const uint8_t *pucLast = pucCurrent + 6;
-
- /* Calculate normal CRC32 */
- while( pucCurrent < pucLast )
- {
- crc ^= *( pucCurrent++ );
- for( j = 0; j < 8; j++ )
- {
- if( ( crc & 1 ) != 0 )
- {
- crc = (crc >> 1) ^ Polynomial;
- }
- else
- {
- crc >>= 1;
- }
- }
- }
- return ~crc;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvGetHashIndex( const uint8_t *ucAddress )
-{
-uint32_t ulCrc = prvGenerateCRC32( ucAddress );
-uint32_t ulIndex = 0ul;
-BaseType_t xCount = 6;
-
- /* Take the lowest 6 bits of the CRC32 and reverse them */
- while( xCount-- )
- {
- ulIndex <<= 1;
- ulIndex |= ( ulCrc & 1 );
- ulCrc >>= 1;
- }
-
- /* This is the has value of 'ucAddress' */
- return ulIndex;
-}
-/*-----------------------------------------------------------*/
-
-static void prvAddMACAddress( const uint8_t* ucMacAddress )
-{
-BaseType_t xIndex;
-
- xIndex = prvGetHashIndex( ucMacAddress );
- if( xIndex >= 32 )
- {
- LPC_ETHERNET->MAC_HASHTABLE_HIGH |= ( 1u << ( xIndex - 32 ) );
- }
- else
- {
- LPC_ETHERNET->MAC_HASHTABLE_LOW |= ( 1u << xIndex );
- }
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t ulStatus;
-const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
-
- /* Remove compiler warning about unused parameter. */
- ( void ) pvParameters;
-
- /* A possibility to set some additional task properties. */
- iptraceEMAC_TASK_STARTING();
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
- for( ;; )
- {
- uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
- if( uxLastMinBufferCount != uxCurrentCount )
- {
- /* The logging produced below may be helpful
- while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
- }
-
- #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- {
- static UBaseType_t uxLastMinQueueSpace = 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 */
-
- ulTaskNotifyTake( pdTRUE, xBlockTime );
-
- xResult = ( BaseType_t ) 0;
-
- if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
- {
- /* Code to release TX buffers if zero-copy is used. */
- ulISREvents &= ~EMAC_IF_TX_EVENT;
- {
- /* Check if DMA packets have been delivered. */
- vClearTXBuffers();
- }
- }
-
- if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
- {
- ulISREvents &= ~EMAC_IF_RX_EVENT;
-
- xResult = prvNetworkInterfaceInput();
- if( xResult > 0 )
- {
- while( prvNetworkInterfaceInput() > 0 )
- {
- }
- }
- }
-
- if( xResult > 0 )
- {
- /* A packet was received. No need to check for the PHY status now,
- but set a timer to check it later on. */
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- xResult = 0;
- }
- else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
- {
- ulStatus = lpcPHYStsPoll();
-
- if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != ( ulStatus & PHY_LINK_CONNECTED ) )
- {
- ulPHYLinkStatus = ulStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (polled PHY)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
- if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* LPCOpen includes. */\r
+#include "chip.h"\r
+#include "lpc_phy.h"\r
+\r
+/* The size of the stack allocated to the task that handles Rx packets. */\r
+#define nwRX_TASK_STACK_SIZE 140\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+ receiving packets. */\r
+ #define PHY_LS_HIGH_CHECK_TIME_MS 15000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still low every second. */\r
+ #define PHY_LS_LOW_CHECK_TIME_MS 1000\r
+#endif\r
+\r
+#ifndef configUSE_RMII\r
+ #define configUSE_RMII 1\r
+#endif\r
+\r
+#ifndef configNUM_RX_DESCRIPTORS\r
+ #error please define configNUM_RX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef configNUM_TX_DESCRIPTORS\r
+ #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef NETWORK_IRQHandler\r
+ #error NETWORK_IRQHandler must be defined to the name of the function that is installed in the interrupt vector table to handle Ethernet interrupts.\r
+#endif\r
+\r
+#if !defined( MAC_FF_HMC )\r
+ /* Hash for multicast. */\r
+ #define MAC_FF_HMC ( 1UL << 2UL )\r
+#endif\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+ #define iptraceEMAC_TASK_STARTING() do { } while( 0 )\r
+#endif\r
+\r
+/* Define the bits of .STATUS that indicate a reception error. */\r
+#define nwRX_STATUS_ERROR_BITS \\r
+ ( RDES_CE /* CRC Error */ | \\r
+ RDES_RE /* Receive Error */ | \\r
+ RDES_DE /* Descriptor Error */ | \\r
+ RDES_RWT /* Receive Watchdog Timeout */ | \\r
+ RDES_LC /* Late Collision */ | \\r
+ RDES_OE /* Overflow Error */ | \\r
+ RDES_SAF /* Source Address Filter Fail */ | \\r
+ RDES_AFM /* Destination Address Filter Fail */ | \\r
+ RDES_LE /* Length Error */ )\r
+\r
+/* Define the EMAC status bits that should trigger an interrupt. */\r
+#define nwDMA_INTERRUPT_MASK \\r
+ ( DMA_IE_TIE /* Transmit interrupt enable */ | \\r
+ DMA_IE_TSE /* Transmit stopped enable */ | \\r
+ DMA_IE_OVE /* Overflow interrupt enable */ | \\r
+ DMA_IE_RIE /* Receive interrupt enable */ | \\r
+ DMA_IE_NIE /* Normal interrupt summary enable */ | \\r
+ DMA_IE_AIE /* Abnormal interrupt summary enable */ | \\r
+ DMA_IE_RUE /* Receive buffer unavailable enable */ | \\r
+ DMA_IE_UNE /* Underflow interrupt enable. */ | \\r
+ DMA_IE_TJE /* Transmit jabber timeout enable */ | \\r
+ DMA_IE_RSE /* Received stopped enable */ | \\r
+ DMA_IE_RWE /* Receive watchdog timeout enable */ | \\r
+ DMA_IE_FBE )/* Fatal bus error enable */\r
+\r
+/* Interrupt events to process. Currently only the RX/TX events are processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT 1UL\r
+#define EMAC_IF_TX_EVENT 2UL\r
+#define EMAC_IF_ERR_EVENT 4UL\r
+#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+ /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+ driver will filter incoming packets and only pass the stack those packets it\r
+ considers need processing. */\r
+ #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+ #else\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+ #endif\r
+\r
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 ) || ( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+ #warning It is adviced to enable both macros\r
+#endif\r
+\r
+#ifndef configPLACE_IN_SECTION_RAM\r
+ #define configPLACE_IN_SECTION_RAM\r
+/*\r
+ #define configPLACE_IN_SECTION_RAM __attribute__ ((section(".ramfunc")))\r
+*/\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Delay function passed into the library. The implementation uses FreeRTOS\r
+ * calls so the scheduler must be started before the driver can be used.\r
+ */\r
+static void prvDelay( uint32_t ulMilliSeconds );\r
+\r
+/*\r
+ * Initialises the Tx and Rx descriptors respectively.\r
+ */\r
+static void prvSetupTxDescriptors( void );\r
+static void prvSetupRxDescriptors( void );\r
+\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Sets up the MAC with the results of an auto-negotiation.\r
+ */\r
+static BaseType_t prvSetLinkSpeed( void );\r
+\r
+/*\r
+ * Generates a CRC for a MAC address that is then used to generate a hash index.\r
+ */\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Generates a hash index when setting a filter to permit a MAC address.\r
+ */\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Update the hash table to allow a MAC address.\r
+ */\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress );\r
+\r
+/*\r
+ * Sometimes the DMA will report received data as being longer than the actual\r
+ * received from length. This function checks the reported length and corrects\r
+ * if if necessary.\r
+ */\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing. Currently only\r
+the Rx and Tx interrupt is handled, although code is included for other events\r
+to enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+/* Tx descriptors and index. */\r
+static ENET_ENHTXDESC_T xDMATxDescriptors[ configNUM_TX_DESCRIPTORS ];\r
+\r
+/* ulNextFreeTxDescriptor is declared volatile, because it is accessed from\r
+to different tasks. */\r
+static volatile uint32_t ulNextFreeTxDescriptor;\r
+static uint32_t ulTxDescriptorToClear;\r
+\r
+/* Rx descriptors and index. */\r
+static ENET_ENHRXDESC_T xDMARxDescriptors[ configNUM_RX_DESCRIPTORS ];\r
+static uint32_t ulNextRxDescriptorToProcess;\r
+\r
+/* Must be defined externally - the demo applications define this in main.c. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* The handle of the task that processes Rx packets. The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+ static const uint8_t xLLMNR_MACAddress[] = { '\x01', '\x00', '\x5E', '\x00', '\x00', '\xFC' };\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of ETH_TXBUFNB, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdPASS;\r
+\r
+ /* The interrupt will be turned on when a link is established. */\r
+ NVIC_DisableIRQ( ETHERNET_IRQn );\r
+\r
+ /* Disable receive and transmit DMA processes. */\r
+ LPC_ETHERNET->DMA_OP_MODE &= ~( DMA_OM_ST | DMA_OM_SR );\r
+\r
+ /* Disable packet reception. */\r
+ LPC_ETHERNET->MAC_CONFIG &= ~( MAC_CFG_RE | MAC_CFG_TE );\r
+\r
+ /* Call the LPCOpen function to initialise the hardware. */\r
+ Chip_ENET_Init( LPC_ETHERNET );\r
+\r
+ /* Save MAC address. */\r
+ Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );\r
+\r
+ /* Clear all MAC address hash entries. */\r
+ LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;\r
+ LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;\r
+\r
+ #if( ipconfigUSE_LLMNR == 1 )\r
+ {\r
+ prvAddMACAddress( xLLMNR_MACAddress );\r
+ }\r
+ #endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+ /* Promiscuous flag (PR) and Receive All flag (RA) set to zero. The\r
+ registers MAC_HASHTABLE_[LOW|HIGH] will be loaded to allow certain\r
+ multi-cast addresses. */\r
+ LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_HMC;\r
+\r
+ #if( configUSE_RMII == 1 )\r
+ {\r
+ if( lpc_phy_init( pdTRUE, prvDelay ) != SUCCESS )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+ }\r
+ #else\r
+ {\r
+ #warning This path has not been tested.\r
+ if( lpc_phy_init( pdFALSE, prvDelay ) != SUCCESS )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+ }\r
+ #endif\r
+\r
+ if( xReturn == pdPASS )\r
+ {\r
+ /* Guard against the task being created more than once and the\r
+ descriptors being initialised more than once. */\r
+ if( xRxHanderTask == NULL )\r
+ {\r
+ xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+ configASSERT( xReturn );\r
+ }\r
+\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ /* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'\r
+ and a maximum of 'configNUM_TX_DESCRIPTORS'. */\r
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );\r
+ configASSERT( xTXDescriptorSemaphore );\r
+ }\r
+\r
+ /* Enable MAC interrupts. */\r
+ LPC_ETHERNET->DMA_INT_EN = nwDMA_INTERRUPT_MASK;\r
+ }\r
+\r
+ if( xReturn != pdFAIL )\r
+ {\r
+ /* Auto-negotiate was already started. Wait for it to complete. */\r
+ xReturn = prvSetLinkSpeed();\r
+\r
+ if( xReturn == pdPASS )\r
+ {\r
+ /* Initialise the descriptors. */\r
+ prvSetupTxDescriptors();\r
+ prvSetupRxDescriptors();\r
+\r
+ /* Clear all interrupts. */\r
+ LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;\r
+\r
+ /* Enable receive and transmit DMA processes. */\r
+ LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;\r
+\r
+ /* Set Receiver / Transmitter Enable. */\r
+ LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;\r
+\r
+ /* Start receive polling. */\r
+ LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+ /* Enable interrupts in the NVIC. */\r
+ NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+ NVIC_EnableIRQ( ETHERNET_IRQn );\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#define niBUFFER_1_PACKET_SIZE 1536\r
+\r
+static __attribute__ ((section("._ramAHB32"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+ for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+ {\r
+ pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+ *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+ ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void vClearTXBuffers()\r
+{\r
+uint32_t ulLastDescriptor = ulNextFreeTxDescriptor;\r
+size_t uxCount = ( ( size_t ) configNUM_TX_DESCRIPTORS ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+ uint8_t *ucPayLoad;\r
+#endif\r
+\r
+ /* This function is called after a TX-completion interrupt.\r
+ It will release each Network Buffer used in xNetworkInterfaceOutput().\r
+ 'uxCount' represents the number of descriptors given to DMA for transmission.\r
+ After sending a packet, the DMA will clear the 'TDES_OWN' bit. */\r
+ while( ( uxCount > ( size_t ) 0u ) && ( ( xDMATxDescriptors[ ulTxDescriptorToClear ].CTRLSTAT & TDES_OWN ) == 0 ) )\r
+ {\r
+ if( ( ulTxDescriptorToClear == ulLastDescriptor ) && ( uxCount != ( size_t ) configNUM_TX_DESCRIPTORS ) )\r
+ {\r
+ break;\r
+ }\r
+\r
+\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ ucPayLoad = ( uint8_t * )xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD;\r
+ if( ucPayLoad != NULL )\r
+ {\r
+ /* B1ADD points to a pucEthernetBuffer of a Network Buffer descriptor. */\r
+ pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
+\r
+ configASSERT( pxNetworkBuffer != NULL );\r
+\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
+ xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD = ( uint32_t )0u;\r
+ }\r
+ }\r
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+ /* Move onto the next descriptor, wrapping if necessary. */\r
+ ulTxDescriptorToClear++;\r
+ if( ulTxDescriptorToClear >= configNUM_TX_DESCRIPTORS )\r
+ {\r
+ ulTxDescriptorToClear = 0;\r
+ }\r
+\r
+ uxCount--;\r
+ /* Tell the counting semaphore that one more TX descriptor is available. */\r
+ xSemaphoreGive( xTXDescriptorSemaphore );\r
+ }\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 );\r
+\r
+ /* Attempt to obtain access to a Tx descriptor. */\r
+ do\r
+ {\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ break;\r
+ }\r
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+ {\r
+ /* Time-out waiting for a free TX descriptor. */\r
+ break;\r
+ }\r
+\r
+ /* If the descriptor is still owned by the DMA it can't be used. */\r
+ if( ( xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT & TDES_OWN ) != 0 )\r
+ {\r
+ /* The semaphore was taken, the TX DMA-descriptor is still not available.\r
+ Actually that should not occur, the 'TDES_OWN' was already confirmed low in vClearTXBuffers(). */\r
+ xSemaphoreGive( xTXDescriptorSemaphore );\r
+ }\r
+ else\r
+ {\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* bReleaseAfterSend should always be set when using the zero\r
+ copy driver. */\r
+ configASSERT( bReleaseAfterSend != pdFALSE );\r
+\r
+ /* The DMA's descriptor to point directly to the data in the\r
+ network buffer descriptor. The data is not copied. */\r
+ xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD = ( uint32_t ) pxDescriptor->pucEthernetBuffer;\r
+\r
+ /* The DMA descriptor will 'own' this Network Buffer,\r
+ until it has been sent. So don't release it now. */\r
+ bReleaseAfterSend = false;\r
+ }\r
+ #else\r
+ {\r
+ /* The data is copied from the network buffer descriptor into\r
+ the DMA's descriptor. */\r
+ memcpy( ( void * ) xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );\r
+ }\r
+ #endif\r
+\r
+ xDMATxDescriptors[ ulNextFreeTxDescriptor ].BSIZE = ( uint32_t ) TDES_ENH_BS1( pxDescriptor->xDataLength );\r
+\r
+ /* This descriptor is given back to the DMA. */\r
+ xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT |= TDES_OWN;\r
+\r
+ /* Ensure the DMA is polling Tx descriptors. */\r
+ LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;\r
+\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+ /* Move onto the next descriptor, wrapping if necessary. */\r
+ ulNextFreeTxDescriptor++;\r
+ if( ulNextFreeTxDescriptor >= configNUM_TX_DESCRIPTORS )\r
+ {\r
+ ulNextFreeTxDescriptor = 0;\r
+ }\r
+\r
+ /* The Tx has been initiated. */\r
+ xReturn = pdPASS;\r
+ }\r
+ } while( 0 );\r
+\r
+ /* The buffer has been sent so can be released. */\r
+ if( bReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDelay( uint32_t ulMilliSeconds )\r
+{\r
+ /* Ensure the scheduler was started before attempting to use the scheduler to\r
+ create a delay. */\r
+ configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING );\r
+\r
+ vTaskDelay( pdMS_TO_TICKS( ulMilliSeconds ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+\r
+ /* Start with Tx descriptors clear. */\r
+ memset( ( void * ) xDMATxDescriptors, 0, sizeof( xDMATxDescriptors ) );\r
+\r
+ /* Index to the next Tx descriptor to use. */\r
+ ulNextFreeTxDescriptor = 0ul;\r
+\r
+ /* Index to the next Tx descriptor to clear ( after transmission ). */\r
+ ulTxDescriptorToClear = 0ul;\r
+\r
+ for( x = 0; x < configNUM_TX_DESCRIPTORS; x++ )\r
+ {\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* Nothing to do, B1ADD will be set when data is ready to transmit.\r
+ Currently the memset above will have set it to NULL. */\r
+ }\r
+ #else\r
+ {\r
+ /* Allocate a buffer to the Tx descriptor. This is the most basic\r
+ way of creating a driver as the data is then copied into the\r
+ buffer. */\r
+ xDMATxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+\r
+ /* Use an assert to check the allocation as +TCP applications will\r
+ often not use a malloc() failed hook as the TCP stack will recover\r
+ from allocation failures. */\r
+ configASSERT( xDMATxDescriptors[ x ].B1ADD );\r
+ }\r
+ #endif\r
+\r
+ /* Buffers hold an entire frame so all buffers are both the start and\r
+ end of a frame. */\r
+ /* TDES_ENH_TCH Second Address Chained. */\r
+ /* TDES_ENH_CIC(n) Checksum Insertion Control, tried but it does not work for the LPC18xx... */\r
+ /* TDES_ENH_FS First Segment. */\r
+ /* TDES_ENH_LS Last Segment. */\r
+ /* TDES_ENH_IC Interrupt on Completion. */\r
+ xDMATxDescriptors[ x ].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC( 3 ) | TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_IC;\r
+ xDMATxDescriptors[ x ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ x + 1 ];\r
+ }\r
+\r
+ xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].CTRLSTAT |= TDES_ENH_TER;\r
+ xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ 0 ];\r
+\r
+ /* Point the DMA to the base of the descriptor list. */\r
+ LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xDMATxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupRxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#endif\r
+\r
+ /* Index to the next Rx descriptor to use. */\r
+ ulNextRxDescriptorToProcess = 0;\r
+\r
+ /* Clear RX descriptor list. */\r
+ memset( ( void * ) xDMARxDescriptors, 0, sizeof( xDMARxDescriptors ) );\r
+\r
+ for( x = 0; x < configNUM_RX_DESCRIPTORS; x++ )\r
+ {\r
+ /* Allocate a buffer of the largest possible frame size as it is not\r
+ known what size received frames will be. */\r
+\r
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ {\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 );\r
+\r
+ /* During start-up there should be enough Network Buffers available,\r
+ so it is safe to use configASSERT().\r
+ In case this assert fails, please check: configNUM_RX_DESCRIPTORS,\r
+ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, and in case BufferAllocation_2.c\r
+ is included, check the amount of available heap. */\r
+ configASSERT( pxNetworkBuffer != NULL );\r
+\r
+ /* Pass the actual buffer to DMA. */\r
+ xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;\r
+ }\r
+ #else\r
+ {\r
+ /* All DMA descriptors are populated with permanent memory blocks.\r
+ Their contents will be copy to Network Buffers. */\r
+ xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+ }\r
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+ /* Use an assert to check the allocation as +TCP applications will often\r
+ not use a malloc failed hook as the TCP stack will recover from\r
+ allocation failures. */\r
+ configASSERT( xDMARxDescriptors[ x ].B1ADD );\r
+\r
+ xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );\r
+ xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;\r
+\r
+ /* The descriptor is available for use by the DMA. */\r
+ xDMARxDescriptors[ x ].STATUS = RDES_OWN;\r
+ }\r
+\r
+ /* RDES_ENH_RER Receive End of Ring. */\r
+ xDMARxDescriptors[ ( configNUM_RX_DESCRIPTORS - 1 ) ].CTRL |= RDES_ENH_RER;\r
+ xDMARxDescriptors[ configNUM_RX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ 0 ] );\r
+\r
+ /* Point the DMA to the base of the descriptor list. */\r
+ LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xDMARxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor )\r
+{\r
+size_t xExpectedLength;\r
+IPPacket_t *pxIPPacket;\r
+\r
+ pxIPPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;\r
+ /* Look at the actual length of the packet, translate it to a host-endial notation. */\r
+ xExpectedLength = sizeof( EthernetHeader_t ) + ( size_t ) FreeRTOS_htons( pxIPPacket->xIPHeader.usLength );\r
+\r
+ if( xExpectedLength == ( pxDescriptor->xDataLength + 4 ) )\r
+ {\r
+ pxDescriptor->xDataLength -= 4;\r
+ }\r
+ else\r
+ {\r
+ if( pxDescriptor->xDataLength > xExpectedLength )\r
+ {\r
+ pxDescriptor->xDataLength = ( size_t ) xExpectedLength;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+ if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t ulDataAvailable;\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static BaseType_t prvNetworkInterfaceInput()\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+uint32_t ulStatus;\r
+eFrameProcessingResult_t eResult;\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+const UBaseType_t uxMinimumBuffersRemaining = 3UL;\r
+uint16_t usLength;\r
+NetworkBufferDescriptor_t *pxDescriptor;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ NetworkBufferDescriptor_t *pxNewDescriptor;\r
+#endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+#if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )\r
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+#endif\r
+\r
+ /* Process each descriptor that is not still in use by the DMA. */\r
+ ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+ if( ( ulStatus & RDES_OWN ) == 0 )\r
+ {\r
+ /* Check packet for errors */\r
+ if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 )\r
+ {\r
+ /* There is some reception error. */\r
+ intCount[ 3 ]++;\r
+ /* Clear error bits. */\r
+ ulStatus &= ~( ( uint32_t )nwRX_STATUS_ERROR_BITS );\r
+ }\r
+ else\r
+ {\r
+ xResult++;\r
+\r
+ eResult = ipCONSIDER_FRAME_FOR_PROCESSING( ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD ) );\r
+ if( eResult == eProcessBuffer )\r
+ {\r
+ if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+ {\r
+ ulPHYLinkStatus |= PHY_LINK_CONNECTED;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (message received)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+ }\r
+\r
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+ {\r
+ pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xDescriptorWaitTime );\r
+ }\r
+ else\r
+ {\r
+ /* Too risky to allocate a new Network Buffer. */\r
+ pxNewDescriptor = NULL;\r
+ }\r
+ if( pxNewDescriptor != NULL )\r
+ #else\r
+ if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+ {\r
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ const uint8_t *pucBuffer;\r
+ #endif\r
+\r
+ /* Get the actual length. */\r
+ usLength = RDES_FLMSK( ulStatus );\r
+\r
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ {\r
+ /* Replace the character buffer 'B1ADD'. */\r
+ pucBuffer = ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD );\r
+ xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer;\r
+\r
+ /* 'B1ADD' contained the address of a 'pucEthernetBuffer' that\r
+ belongs to a Network Buffer. Find the original Network Buffer. */\r
+ pxDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+ /* This zero-copy driver makes sure that every 'xDMARxDescriptors' contains\r
+ a reference to a Network Buffer at any time.\r
+ In case it runs out of Network Buffers, a DMA buffer won't be replaced,\r
+ and the received messages is dropped. */\r
+ configASSERT( pxDescriptor != NULL );\r
+ }\r
+ #else\r
+ {\r
+ /* Create a buffer of exactly the required length. */\r
+ pxDescriptor = pxGetNetworkBufferWithDescriptor( usLength, xDescriptorWaitTime );\r
+ }\r
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+ if( pxDescriptor != NULL )\r
+ {\r
+ pxDescriptor->xDataLength = ( size_t ) usLength;\r
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
+ {\r
+ /* Copy the data into the allocated buffer. */\r
+ memcpy( ( void * ) pxDescriptor->pucEthernetBuffer, ( void * ) xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD, usLength );\r
+ }\r
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+ /* It is possible that more data was copied than\r
+ actually makes up the frame. If this is the case\r
+ adjust the length to remove any trailing bytes. */\r
+ prvRemoveTrailingBytes( pxDescriptor );\r
+\r
+ /* Pass the data to the TCP/IP task for processing. */\r
+ xRxEvent.pvData = ( void * ) pxDescriptor;\r
+ if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+ {\r
+ /* Could not send the descriptor into the TCP/IP\r
+ stack, it must be released. */\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+ else\r
+ {\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+\r
+ /* The data that was available at the top of this\r
+ loop has been sent, so is no longer available. */\r
+ ulDataAvailable = pdFALSE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The packet is discarded as uninteresting. */\r
+ ulDataAvailable = pdFALSE;\r
+ }\r
+ /* Got here because received data was sent to the IP task or the\r
+ data contained an error and was discarded. Give the descriptor\r
+ back to the DMA. */\r
+ xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS = ulStatus | RDES_OWN;\r
+\r
+ /* Move onto the next descriptor. */\r
+ ulNextRxDescriptorToProcess++;\r
+ if( ulNextRxDescriptorToProcess >= configNUM_RX_DESCRIPTORS )\r
+ {\r
+ ulNextRxDescriptorToProcess = 0;\r
+ }\r
+\r
+ ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+ } /* if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 ) */\r
+ } /* if( ( ulStatus & RDES_OWN ) == 0 ) */\r
+\r
+ /* Restart receive polling. */\r
+ LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+ return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+void NETWORK_IRQHandler( void )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+uint32_t ulDMAStatus;\r
+const uint32_t ulRxInterruptMask =\r
+ DMA_ST_RI | /* Receive interrupt */\r
+ DMA_ST_RU; /* Receive buffer unavailable */\r
+const uint32_t ulTxInterruptMask =\r
+ DMA_ST_TI | /* Transmit interrupt */\r
+ DMA_ST_TPS; /* Transmit process stopped */\r
+\r
+ configASSERT( xRxHanderTask );\r
+\r
+ /* Get pending interrupts. */\r
+ ulDMAStatus = LPC_ETHERNET->DMA_STAT;\r
+\r
+ /* RX group interrupt(s). */\r
+ if( ( ulDMAStatus & ulRxInterruptMask ) != 0x00 )\r
+ {\r
+ /* Remember that an RX event has happened. */\r
+ ulISREvents |= EMAC_IF_RX_EVENT;\r
+ vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+ intCount[ 0 ]++;\r
+ }\r
+\r
+ /* TX group interrupt(s). */\r
+ if( ( ulDMAStatus & ulTxInterruptMask ) != 0x00 )\r
+ {\r
+ /* Remember that a TX event has happened. */\r
+ ulISREvents |= EMAC_IF_TX_EVENT;\r
+ vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+ intCount[ 1 ]++;\r
+ }\r
+\r
+ /* Test for 'Abnormal interrupt summary'. */\r
+ if( ( ulDMAStatus & DMA_ST_AIE ) != 0x00 )\r
+ {\r
+ /* The trace macro must be written such that it can be called from\r
+ an interrupt. */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+\r
+ /* Clear pending interrupts */\r
+ LPC_ETHERNET->DMA_STAT = ulDMAStatus;\r
+\r
+ /* Context switch needed? */\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSetLinkSpeed( void )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+TickType_t xTimeOnEntering;\r
+uint32_t ulPhyStatus;\r
+const TickType_t xAutoNegotiateDelay = pdMS_TO_TICKS( 5000UL );\r
+\r
+ /* Ensure polling does not starve lower priority tasks by temporarily\r
+ setting the priority of this task to that of the idle task. */\r
+ vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+\r
+ xTimeOnEntering = xTaskGetTickCount();\r
+ do\r
+ {\r
+ ulPhyStatus = lpcPHYStsPoll();\r
+ if( ( ulPhyStatus & PHY_LINK_CONNECTED ) != 0x00 )\r
+ {\r
+ /* Set interface speed and duplex. */\r
+ if( ( ulPhyStatus & PHY_LINK_SPEED100 ) != 0x00 )\r
+ {\r
+ Chip_ENET_SetSpeed( LPC_ETHERNET, 1 );\r
+ }\r
+ else\r
+ {\r
+ Chip_ENET_SetSpeed( LPC_ETHERNET, 0 );\r
+ }\r
+\r
+ if( ( ulPhyStatus & PHY_LINK_FULLDUPLX ) != 0x00 )\r
+ {\r
+ Chip_ENET_SetDuplex( LPC_ETHERNET, true );\r
+ }\r
+ else\r
+ {\r
+ Chip_ENET_SetDuplex( LPC_ETHERNET, false );\r
+ }\r
+\r
+ xReturn = pdPASS;\r
+ break;\r
+ }\r
+ } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xAutoNegotiateDelay );\r
+\r
+ /* Reset the priority of this task back to its original value. */\r
+ vTaskPrioritySet( NULL, ipconfigIP_TASK_PRIORITY );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress )\r
+{\r
+unsigned int j;\r
+const uint32_t Polynomial = 0xEDB88320;\r
+uint32_t crc = ~0ul;\r
+const uint8_t *pucCurrent = ( const uint8_t * ) ucAddress;\r
+const uint8_t *pucLast = pucCurrent + 6;\r
+\r
+ /* Calculate normal CRC32 */\r
+ while( pucCurrent < pucLast )\r
+ {\r
+ crc ^= *( pucCurrent++ );\r
+ for( j = 0; j < 8; j++ )\r
+ {\r
+ if( ( crc & 1 ) != 0 )\r
+ {\r
+ crc = (crc >> 1) ^ Polynomial;\r
+ }\r
+ else\r
+ {\r
+ crc >>= 1;\r
+ }\r
+ }\r
+ }\r
+ return ~crc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress )\r
+{\r
+uint32_t ulCrc = prvGenerateCRC32( ucAddress );\r
+uint32_t ulIndex = 0ul;\r
+BaseType_t xCount = 6;\r
+\r
+ /* Take the lowest 6 bits of the CRC32 and reverse them */\r
+ while( xCount-- )\r
+ {\r
+ ulIndex <<= 1;\r
+ ulIndex |= ( ulCrc & 1 );\r
+ ulCrc >>= 1;\r
+ }\r
+\r
+ /* This is the has value of 'ucAddress' */\r
+ return ulIndex;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress )\r
+{\r
+BaseType_t xIndex;\r
+\r
+ xIndex = prvGetHashIndex( ucMacAddress );\r
+ if( xIndex >= 32 )\r
+ {\r
+ LPC_ETHERNET->MAC_HASHTABLE_HIGH |= ( 1u << ( xIndex - 32 ) );\r
+ }\r
+ else\r
+ {\r
+ LPC_ETHERNET->MAC_HASHTABLE_LOW |= ( 1u << xIndex );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t ulStatus;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+\r
+ /* Remove compiler warning about unused parameter. */\r
+ ( void ) pvParameters;\r
+\r
+ /* A possibility to set some additional task properties. */\r
+ iptraceEMAC_TASK_STARTING();\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+ for( ;; )\r
+ {\r
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+ if( uxLastMinBufferCount != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+ }\r
+\r
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+ if( uxLastMinQueueSpace != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinQueueSpace = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+ }\r
+ }\r
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+ ulTaskNotifyTake( pdTRUE, xBlockTime );\r
+\r
+ xResult = ( BaseType_t ) 0;\r
+\r
+ if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+ {\r
+ /* Code to release TX buffers if zero-copy is used. */\r
+ ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+ {\r
+ /* Check if DMA packets have been delivered. */\r
+ vClearTXBuffers();\r
+ }\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+ {\r
+ ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+ xResult = prvNetworkInterfaceInput();\r
+ if( xResult > 0 )\r
+ {\r
+ while( prvNetworkInterfaceInput() > 0 )\r
+ {\r
+ }\r
+ }\r
+ }\r
+\r
+ if( xResult > 0 )\r
+ {\r
+ /* A packet was received. No need to check for the PHY status now,\r
+ but set a timer to check it later on. */\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ xResult = 0;\r
+ }\r
+ else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+ {\r
+ ulStatus = lpcPHYStsPoll();\r
+\r
+ if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != ( ulStatus & PHY_LINK_CONNECTED ) )\r
+ {\r
+ ulPHYLinkStatus = ulStatus;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (polled PHY)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+ }\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ }\r
+ else\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-#include "queue.h"
-#include "semphr.h"
-#include "task.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-
-#include "m480_eth.h"
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
- #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-
-static SemaphoreHandle_t xTXMutex = NULL;
-
-/* The handle of the task that processes Rx packets. The handle is required so
-the task can be notified when new packets arrive. */
-static TaskHandle_t xRxHanderTask = NULL;
-static TimerHandle_t xPhyHandlerTask = NULL;
-/*
- * A task that processes received frames.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-static void prvPhyTmrCallback( TimerHandle_t xTimer );
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-
-#define niBUFFER_1_PACKET_SIZE 1536
-#ifdef __ICCARM__
-#pragma data_alignment=4
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
-#else
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
-#endif
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
- uint8_t hwaddr[6];
- BaseType_t xReturn = pdPASS;
-
- /* Init ETH */
- numaker_mac_address(hwaddr);
- FreeRTOS_UpdateMACAddress(hwaddr);
- FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
- /* Enable clock & set EMAC configuration */
- /* Enable MAC and DMA transmission and reception */
- if( numaker_eth_init(hwaddr) < 0)
- {
- xReturn = pdFAIL;
- } else {
- xReturn = pdPASS;
- /* Guard against the task being created more than once and the
- descriptors being initialized more than once. */
- /* Timer task to monitor PHY Link status */
- if( xPhyHandlerTask == NULL )
- {
- xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
- configASSERT(xPhyHandlerTask);
- xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
- configASSERT( xReturn );
- }
- /* Rx task */
- if( xRxHanderTask == NULL )
- {
- xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
- configASSERT( xReturn );
- }
-
- if( xTXMutex == NULL )
- {
- xTXMutex = xSemaphoreCreateMutex();
- configASSERT( xTXMutex );
- }
- }
-
- NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
- NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
-
- numaker_eth_enable_interrupts();
-
- FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
-
- return xReturn;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
-{
- uint8_t *buffer=NULL;
-// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
- if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
- {
- FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
- return pdFALSE;
- }
-
- buffer = numaker_eth_get_tx_buf();
- if( buffer == NULL )
- {
- NU_DEBUGF(("Eth TX slots are busy\n"));
- return pdFALSE;
- }
-
- /* Get exclusive access */
- xSemaphoreTake(xTXMutex, portMAX_DELAY);
- NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
- //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
- memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
- numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
- /* Call the standard trace macro to log the send event. */
- iptraceNETWORK_INTERFACE_TRANSMIT();
-
- if( xReleaseAfterSend != pdFALSE )
- {
- /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
- buffer. The Ethernet buffer is therefore no longer needed, and must be
- freed for re-use. */
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
-
- xSemaphoreGive(xTXMutex);
-
- return pdTRUE;
-}
-
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-
- uint8_t *ucRAMBuffer = ucNetworkPackets;
- uint32_t ul;
-
- for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
- {
- pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
- *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
- ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
- }
-}
-
-
-BaseType_t xGetPhyLinkStatus( void )
-{
- BaseType_t xReturn;
-
- if( numaker_eth_link_ok() )
- {
- xReturn = pdPASS;
- }
- else
- {
- xReturn = pdFAIL;
- }
-
- return xReturn;
-}
-
-static void prvPhyTmrCallback( TimerHandle_t xTimer )
-{
- IPStackEvent_t xRxEvent;
- static BaseType_t lastLink = pdFAIL;
- BaseType_t currLink = xGetPhyLinkStatus();
- if( currLink != lastLink )
- {
- FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
- if( !currLink )
- {
- xRxEvent.eEventType = eNetworkDownEvent;
- xSendEventStructToIPTask( &xRxEvent, 0 );
- }
- lastLink = currLink;
- }
-
-}
-
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
- TimeOut_t xPhyTime;
- TickType_t xPhyRemTime;
- UBaseType_t uxLastMinBufferCount = 0;
- UBaseType_t uxCurrentCount;
- BaseType_t xResult = 0;
- uint32_t ulStatus;
- uint16_t dataLength = 0;
- uint8_t *buffer = NULL;
- NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
- IPStackEvent_t xRxEvent;
- const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
-
- /* Remove compiler warnings about unused parameters. */
- ( void ) pvParameters;
- /* A possibility to set some additional task properties. */
-
- for( ;; )
- {
- uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
- if( uxLastMinBufferCount != uxCurrentCount )
- {
- /* The logging produced below may be helpful
- while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
- }
-
- /* No events to process now, wait for the next. */
- ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
- while(1)
- {
- /* get received frame */
- if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
- /* The event was lost because a network buffer was not available.
- Call the standard trace macro to log the occurrence. */
- iptraceETHERNET_RX_EVENT_LOST();
- break;
- }
-
- /* Allocate a network buffer descriptor that points to a buffer
- large enough to hold the received frame. As this is the simple
- rather than efficient example the received data will just be copied
- into this buffer. */
-
- pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );
-
- if( pxBufferDescriptor != NULL )
- {
- memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
-// FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
- pxBufferDescriptor->xDataLength = dataLength;
- } else {
- numaker_eth_rx_next();
- iptraceETHERNET_RX_EVENT_LOST();
- break;
- }
- /* The event about to be sent to the TCP/IP is an Rx event. */
- xRxEvent.eEventType = eNetworkRxEvent;
-
- /* pvData is used to point to the network buffer descriptor that
- now references the received data. */
- xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
- /* Send the data to the TCP/IP stack. */
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
- {
- /* The buffer could not be sent to the IP task so the buffer
- must be released. */
- vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-
- /* Make a call to the standard trace macro to log the
- occurrence. */
-
- iptraceETHERNET_RX_EVENT_LOST();
- } else
- {
- /* The message was successfully sent to the TCP/IP stack.
- Call the standard trace macro to log the occurrence. */
- iptraceNETWORK_INTERFACE_RECEIVE();
- }
- numaker_eth_rx_next();
- }
- numaker_eth_trigger_rx();
- }
-}
-
-void xNetworkCallback(char event)
-{
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- switch (event)
- {
- case 'R': //For RX event
- /* Wakeup the prvEMACHandlerTask. */
- if( xRxHanderTask != NULL )
- {
- vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
- }
- break;
- case 'T': //For TX event
- // ack of tx done, no-op in this stage
- break;
- default:
- break;
- }
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+\r
+#include "m480_eth.h"\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+ #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+\r
+static SemaphoreHandle_t xTXMutex = NULL;\r
+\r
+/* The handle of the task that processes Rx packets. The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+static TimerHandle_t xPhyHandlerTask = NULL;\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer );\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+\r
+#define niBUFFER_1_PACKET_SIZE 1536\r
+#ifdef __ICCARM__\r
+#pragma data_alignment=4\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]\r
+#else\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+ uint8_t hwaddr[6];\r
+ BaseType_t xReturn = pdPASS;\r
+\r
+ /* Init ETH */\r
+ numaker_mac_address(hwaddr);\r
+ FreeRTOS_UpdateMACAddress(hwaddr);\r
+ FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );\r
+ /* Enable clock & set EMAC configuration */\r
+ /* Enable MAC and DMA transmission and reception */\r
+ if( numaker_eth_init(hwaddr) < 0)\r
+ {\r
+ xReturn = pdFAIL;\r
+ } else {\r
+ xReturn = pdPASS;\r
+ /* Guard against the task being created more than once and the\r
+ descriptors being initialized more than once. */\r
+ /* Timer task to monitor PHY Link status */\r
+ if( xPhyHandlerTask == NULL )\r
+ {\r
+ xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );\r
+ configASSERT(xPhyHandlerTask);\r
+ xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;\r
+ configASSERT( xReturn );\r
+ }\r
+ /* Rx task */\r
+ if( xRxHanderTask == NULL )\r
+ {\r
+ xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+ configASSERT( xReturn );\r
+ }\r
+ \r
+ if( xTXMutex == NULL )\r
+ {\r
+ xTXMutex = xSemaphoreCreateMutex();\r
+ configASSERT( xTXMutex );\r
+ } \r
+ }\r
+\r
+ NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+ NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+\r
+ numaker_eth_enable_interrupts();\r
+\r
+ FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );\r
+\r
+ return xReturn;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )\r
+{\r
+ uint8_t *buffer=NULL;\r
+// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));\r
+ if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )\r
+ {\r
+ FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));\r
+ return pdFALSE;\r
+ }\r
+ \r
+ buffer = numaker_eth_get_tx_buf();\r
+ if( buffer == NULL )\r
+ {\r
+ NU_DEBUGF(("Eth TX slots are busy\n"));\r
+ return pdFALSE;\r
+ } \r
+ \r
+ /* Get exclusive access */\r
+ xSemaphoreTake(xTXMutex, portMAX_DELAY);\r
+ NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer)); \r
+ //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength\r
+ memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);\r
+ numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);\r
+ /* Call the standard trace macro to log the send event. */\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+ if( xReleaseAfterSend != pdFALSE )\r
+ {\r
+ /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet\r
+ buffer. The Ethernet buffer is therefore no longer needed, and must be\r
+ freed for re-use. */\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+\r
+ xSemaphoreGive(xTXMutex);\r
+ \r
+ return pdTRUE;\r
+}\r
+\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+ uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+ uint32_t ul;\r
+\r
+ for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+ {\r
+ pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+ *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+ ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+ }\r
+}\r
+\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+ BaseType_t xReturn;\r
+\r
+ if( numaker_eth_link_ok() )\r
+ {\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer )\r
+{\r
+ IPStackEvent_t xRxEvent;\r
+ static BaseType_t lastLink = pdFAIL;\r
+ BaseType_t currLink = xGetPhyLinkStatus();\r
+ if( currLink != lastLink )\r
+ {\r
+ FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));\r
+ if( !currLink )\r
+ {\r
+ xRxEvent.eEventType = eNetworkDownEvent;\r
+ xSendEventStructToIPTask( &xRxEvent, 0 );\r
+ }\r
+ lastLink = currLink;\r
+ }\r
+\r
+} \r
+\r
+ \r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+ TimeOut_t xPhyTime;\r
+ TickType_t xPhyRemTime;\r
+ UBaseType_t uxLastMinBufferCount = 0;\r
+ UBaseType_t uxCurrentCount;\r
+ BaseType_t xResult = 0;\r
+ uint32_t ulStatus;\r
+ uint16_t dataLength = 0;\r
+ uint8_t *buffer = NULL;\r
+ NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;\r
+ IPStackEvent_t xRxEvent;\r
+ const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+ \r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+ /* A possibility to set some additional task properties. */\r
+ \r
+ for( ;; )\r
+ {\r
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+ if( uxLastMinBufferCount != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+ }\r
+ \r
+ /* No events to process now, wait for the next. */\r
+ ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); \r
+ while(1)\r
+ { \r
+ /* get received frame */\r
+ if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {\r
+ /* The event was lost because a network buffer was not available.\r
+ Call the standard trace macro to log the occurrence. */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ break;\r
+ } \r
+\r
+ /* Allocate a network buffer descriptor that points to a buffer\r
+ large enough to hold the received frame. As this is the simple\r
+ rather than efficient example the received data will just be copied\r
+ into this buffer. */\r
+\r
+ pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );\r
+\r
+ if( pxBufferDescriptor != NULL )\r
+ { \r
+ memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );\r
+// FreeRTOS_printf(("--> dataLength=%d\n",dataLength));\r
+ pxBufferDescriptor->xDataLength = dataLength; \r
+ } else {\r
+ numaker_eth_rx_next();\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ break;\r
+ }\r
+ /* The event about to be sent to the TCP/IP is an Rx event. */\r
+ xRxEvent.eEventType = eNetworkRxEvent;\r
+\r
+ /* pvData is used to point to the network buffer descriptor that\r
+ now references the received data. */\r
+ xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+ /* Send the data to the TCP/IP stack. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+ {\r
+ /* The buffer could not be sent to the IP task so the buffer\r
+ must be released. */\r
+ vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+\r
+ /* Make a call to the standard trace macro to log the\r
+ occurrence. */\r
+\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ } else\r
+ {\r
+ /* The message was successfully sent to the TCP/IP stack.\r
+ Call the standard trace macro to log the occurrence. */\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ } \r
+ numaker_eth_rx_next();\r
+ } \r
+ numaker_eth_trigger_rx();\r
+ }\r
+}\r
+\r
+void xNetworkCallback(char event)\r
+{\r
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+ switch (event)\r
+ {\r
+ case 'R': //For RX event\r
+ /* Wakeup the prvEMACHandlerTask. */\r
+ if( xRxHanderTask != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+ }\r
+ break;\r
+ case 'T': //For TX event\r
+ // ack of tx done, no-op in this stage\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+}\r
-/**************************************************************************//**
- * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
- *
- * 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. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
-*****************************************************************************/
-#include "FreeRTOS.h"
-#include "list.h"
-#include "FreeRTOS_IP.h"
-
-#include "m480_eth.h"
-
-#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
-#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
-#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
-#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
-#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
-#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
-
-
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-#ifdef __ICCARM__
-#pragma data_alignment=4
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
-uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
-uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
-#else
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
-uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
-#endif
-struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
-
-
-// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
-// Assume we want to set each tick to 100ns.
-// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
-// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
-// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
-
-
-
-static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)
-{
-
- EMAC->MIIMDAT = val;
- EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
-
- while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
-
-}
-
-
-static uint16_t mdio_read(uint8_t addr, uint8_t reg)
-{
- EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
- while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
-
- return(EMAC->MIIMDAT);
-}
-
-static int reset_phy(void)
-{
-
- uint16_t reg;
- uint32_t delayCnt;
-
-
- mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
-
- delayCnt = 2000;
- while(delayCnt-- > 0) {
- if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
- break;
-
- }
-
- if(delayCnt == 0) {
- NU_DEBUGF(("Reset phy failed\n"));
- return(-1);
- }
-
- mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
- ADVERTISE_10HALF |
- ADVERTISE_10FULL |
- ADVERTISE_100HALF |
- ADVERTISE_100FULL);
-
- reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
- mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
-
- delayCnt = 200000;
- while(delayCnt-- > 0) {
- if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
- == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
- break;
- }
-
- if(delayCnt == 0) {
- NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
- EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
- return(-1);
- } else {
- reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
-
- if(reg & ADVERTISE_100FULL) {
- NU_DEBUGF(("100 full\n"));
- EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
- } else if(reg & ADVERTISE_100HALF) {
- NU_DEBUGF(("100 half\n"));
- EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
- } else if(reg & ADVERTISE_10FULL) {
- NU_DEBUGF(("10 full\n"));
- EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
- } else {
- NU_DEBUGF(("10 half\n"));
- EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
- }
- }
- FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));
- FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));
-
- return(0);
-}
-
-
-static void init_tx_desc(void)
-{
- uint32_t i;
-
-
- cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
-
- for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
- tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
- tx_desc[i].buf = &tx_buf[i][0];
- tx_desc[i].status2 = 0;
- tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
-
- }
- EMAC->TXDSA = (unsigned int)&tx_desc[0];
- return;
-}
-
-static void init_rx_desc(void)
-{
- uint32_t i;
-
-
- cur_rx_desc_ptr = &rx_desc[0];
-
- for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
- rx_desc[i].status1 = OWNERSHIP_EMAC;
- rx_desc[i].buf = &rx_buf[i][0];
- rx_desc[i].status2 = 0;
- rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
- }
- EMAC->RXDSA = (unsigned int)&rx_desc[0];
- return;
-}
-
-void numaker_set_mac_addr(uint8_t *addr)
-{
-
- EMAC->CAM0M = (addr[0] << 24) |
- (addr[1] << 16) |
- (addr[2] << 8) |
- addr[3];
-
- EMAC->CAM0L = (addr[4] << 24) |
- (addr[5] << 16);
-
-
-}
-
-static void __eth_clk_pin_init()
-{
- /* Unlock protected registers */
- SYS_UnlockReg();
-
- /* Enable IP clock */
- CLK_EnableModuleClock(EMAC_MODULE);
-
- // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
- CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
-
- /* Update System Core Clock */
- SystemCoreClockUpdate();
-
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init I/O Multi-function */
- /*---------------------------------------------------------------------------------------------------------*/
- // Configure RMII pins
- SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
- SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
- SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
- SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
- SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
- SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
- SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
- SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
- SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
- SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
- SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
- SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
- SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
-
- // Enable high slew rate on all RMII TX output pins
- PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
- (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
- (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
-
-
- /* Lock protected registers */
- SYS_LockReg();
-
-
-}
-
-int numaker_eth_init(uint8_t *mac_addr)
-{
- int ret = 0;
- // init CLK & pins
- __eth_clk_pin_init();
-
- // Reset MAC
- EMAC->CTL = EMAC_CTL_RST_Msk;
- while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
-
- init_tx_desc();
- init_rx_desc();
-
- numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
-
-
- /* Configure the MAC interrupt enable register. */
- EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
- EMAC_INTEN_TXIEN_Msk |
- EMAC_INTEN_RXGDIEN_Msk |
- EMAC_INTEN_TXCPIEN_Msk |
- EMAC_INTEN_RXBEIEN_Msk |
- EMAC_INTEN_TXBEIEN_Msk |
- EMAC_INTEN_RDUIEN_Msk |
- EMAC_INTEN_TSALMIEN_Msk |
- EMAC_INTEN_WOLIEN_Msk;
-
- /* Configure the MAC control register. */
- EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
-
- /* Accept packets for us and all broadcast and multicast packets */
- EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
- EMAC_CAMCTL_AMP_Msk |
- EMAC_CAMCTL_ABP_Msk;
- EMAC->CAMEN = 1; // Enable CAM entry 0
-
- ret= reset_phy();
-
- EMAC_ENABLE_RX();
- EMAC_ENABLE_TX();
- return ret;
-}
-
-
-
-void ETH_halt(void)
-{
-
- EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
-}
-
-unsigned int m_status;
-
-void EMAC_RX_IRQHandler(void)
-{
-// NU_DEBUGF(("%s ... \r\n", __FUNCTION__));
- m_status = EMAC->INTSTS & 0xFFFF;
- EMAC->INTSTS = m_status;
- if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
- // Shouldn't goes here, unless descriptor corrupted
- NU_DEBUGF(("RX descriptor corrupted \r\n"));
- //return;
- }
- // FIX ME: for rx-event, to ack rx_isr into event queue
- xNetworkCallback('R');
-}
-
-
-void numaker_eth_trigger_rx(void)
-{
- ETH_TRIGGER_RX();
-}
-
-int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
-{
- unsigned int cur_entry, status;
-
- cur_entry = EMAC->CRXDSA;
- if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
- return -1;
- status = cur_rx_desc_ptr->status1;
-
- if(status & OWNERSHIP_EMAC)
- return -1;
-
- if (status & RXFD_RXGD) {
- *buf = cur_rx_desc_ptr->buf;
- *len = status & 0xFFFF;
- }
- return 0;
-}
-
-void numaker_eth_rx_next(void)
-{
- cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
- cur_rx_desc_ptr = cur_rx_desc_ptr->next;
-}
-
-void EMAC_TX_IRQHandler(void)
-{
- unsigned int cur_entry, status;
-
- status = EMAC->INTSTS & 0xFFFF0000;
- EMAC->INTSTS = status;
- if(status & EMAC_INTSTS_TXBEIF_Msk) {
- // Shouldn't goes here, unless descriptor corrupted
- return;
- }
-
- cur_entry = EMAC->CTXDSA;
-
- while (cur_entry != (uint32_t)fin_tx_desc_ptr) {
-
- fin_tx_desc_ptr = fin_tx_desc_ptr->next;
- }
- // FIX ME: for tx-event, no-op at this stage
- xNetworkCallback('T');
-}
-
-uint8_t *numaker_eth_get_tx_buf(void)
-{
- if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
- return(NULL);
- else
- return(cur_tx_desc_ptr->buf);
-}
-
-void numaker_eth_trigger_tx(uint16_t length, void *p)
-{
- struct eth_descriptor volatile *desc;
- cur_tx_desc_ptr->status2 = (unsigned int)length;
- desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
- cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
- cur_tx_desc_ptr = desc;
-
- ETH_TRIGGER_TX();
-
-}
-
-int numaker_eth_link_ok(void)
-{
- /* first, a dummy read to latch */
- mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
- if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
- return 1;
- return 0;
-}
-
-//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
-//{
-// nu_eth_txrx_cb = eth_cb;
-// nu_userData = userData;
-//}
-
-// Provide ethernet devices with a semi-unique MAC address
-void numaker_mac_address(uint8_t *mac)
-{
- uint32_t uID1;
- // Fetch word 0
- uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
- // Fetch word 1
- // we only want bottom 16 bits of word1 (MAC bits 32-47)
- // and bit 9 forced to 1, bit 8 forced to 0
- // Locally administered MAC, reduced conflicts
- // http://en.wikipedia.org/wiki/MAC_address
- uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
-
- if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
- {
- // with a semi-unique MAC address from the UUID
- /* Enable FMC ISP function */
- SYS_UnlockReg();
- FMC_Open();
- // = FMC_ReadUID(0);
- uID1 = FMC_ReadUID(1);
- word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
- word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
- /* Disable FMC ISP function */
- FMC_Close();
- /* Lock protected registers */
- SYS_LockReg();
- }
-
- word1 |= 0x00000200;
- word1 &= 0x0000FEFF;
-
- mac[0] = (word1 & 0x0000ff00) >> 8;
- mac[1] = (word1 & 0x000000ff);
- mac[2] = (word0 & 0xff000000) >> 24;
- mac[3] = (word0 & 0x00ff0000) >> 16;
- mac[4] = (word0 & 0x0000ff00) >> 8;
- mac[5] = (word0 & 0x000000ff);
-
- NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
-}
-
-void numaker_eth_enable_interrupts(void) {
- EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
- EMAC_INTEN_TXIEN_Msk ;
- NVIC_EnableIRQ(EMAC_RX_IRQn);
- NVIC_EnableIRQ(EMAC_TX_IRQn);
-}
-
-void numaker_eth_disable_interrupts(void) {
- NVIC_DisableIRQ(EMAC_RX_IRQn);
- NVIC_DisableIRQ(EMAC_TX_IRQn);
-}
+/**************************************************************************//**\r
+ * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without modification,\r
+ * are permitted provided that the following conditions are met:\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors\r
+ * may be used to endorse or promote products derived from this software\r
+ * without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*****************************************************************************/\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+#include "FreeRTOS_IP.h"\r
+\r
+#include "m480_eth.h"\r
+\r
+#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)\r
+#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)\r
+#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)\r
+#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)\r
+#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)\r
+#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)\r
+ \r
+\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+#ifdef __ICCARM__\r
+#pragma data_alignment=4\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];\r
+uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];\r
+uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];\r
+#else\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));\r
+uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));\r
+#endif\r
+struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;\r
+\r
+\r
+// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns\r
+// Assume we want to set each tick to 100ns.\r
+// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7\r
+// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz\r
+// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600\r
+\r
+\r
+\r
+static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)\r
+{\r
+\r
+ EMAC->MIIMDAT = val;\r
+ EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;\r
+\r
+ while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);\r
+\r
+}\r
+\r
+\r
+static uint16_t mdio_read(uint8_t addr, uint8_t reg)\r
+{\r
+ EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;\r
+ while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);\r
+\r
+ return(EMAC->MIIMDAT);\r
+}\r
+\r
+static int reset_phy(void)\r
+{\r
+\r
+ uint16_t reg;\r
+ uint32_t delayCnt;\r
+\r
+\r
+ mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);\r
+\r
+ delayCnt = 2000;\r
+ while(delayCnt-- > 0) {\r
+ if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)\r
+ break;\r
+\r
+ }\r
+\r
+ if(delayCnt == 0) {\r
+ NU_DEBUGF(("Reset phy failed\n"));\r
+ return(-1);\r
+ }\r
+\r
+ mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |\r
+ ADVERTISE_10HALF |\r
+ ADVERTISE_10FULL |\r
+ ADVERTISE_100HALF |\r
+ ADVERTISE_100FULL);\r
+\r
+ reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);\r
+ mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);\r
+\r
+ delayCnt = 200000;\r
+ while(delayCnt-- > 0) {\r
+ if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))\r
+ == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))\r
+ break;\r
+ }\r
+\r
+ if(delayCnt == 0) {\r
+ NU_DEBUGF(("AN failed. Set to 100 FULL\n"));\r
+ EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+ return(-1);\r
+ } else {\r
+ reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);\r
+\r
+ if(reg & ADVERTISE_100FULL) {\r
+ NU_DEBUGF(("100 full\n"));\r
+ EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+ } else if(reg & ADVERTISE_100HALF) {\r
+ NU_DEBUGF(("100 half\n"));\r
+ EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;\r
+ } else if(reg & ADVERTISE_10FULL) {\r
+ NU_DEBUGF(("10 full\n"));\r
+ EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;\r
+ } else {\r
+ NU_DEBUGF(("10 half\n"));\r
+ EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+ }\r
+ }\r
+ FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));\r
+ FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));\r
+\r
+ return(0);\r
+}\r
+\r
+\r
+static void init_tx_desc(void)\r
+{\r
+ uint32_t i;\r
+\r
+\r
+ cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];\r
+\r
+ for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {\r
+ tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;\r
+ tx_desc[i].buf = &tx_buf[i][0];\r
+ tx_desc[i].status2 = 0;\r
+ tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];\r
+\r
+ }\r
+ EMAC->TXDSA = (unsigned int)&tx_desc[0];\r
+ return;\r
+}\r
+\r
+static void init_rx_desc(void)\r
+{\r
+ uint32_t i;\r
+\r
+\r
+ cur_rx_desc_ptr = &rx_desc[0];\r
+\r
+ for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {\r
+ rx_desc[i].status1 = OWNERSHIP_EMAC;\r
+ rx_desc[i].buf = &rx_buf[i][0];\r
+ rx_desc[i].status2 = 0;\r
+ rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];\r
+ }\r
+ EMAC->RXDSA = (unsigned int)&rx_desc[0];\r
+ return;\r
+}\r
+\r
+void numaker_set_mac_addr(uint8_t *addr)\r
+{\r
+\r
+ EMAC->CAM0M = (addr[0] << 24) |\r
+ (addr[1] << 16) |\r
+ (addr[2] << 8) |\r
+ addr[3];\r
+\r
+ EMAC->CAM0L = (addr[4] << 24) |\r
+ (addr[5] << 16);\r
+\r
+\r
+}\r
+\r
+static void __eth_clk_pin_init()\r
+{\r
+ /* Unlock protected registers */\r
+ SYS_UnlockReg();\r
+\r
+ /* Enable IP clock */\r
+ CLK_EnableModuleClock(EMAC_MODULE);\r
+ \r
+ // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH\r
+ CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));\r
+ \r
+ /* Update System Core Clock */\r
+ SystemCoreClockUpdate();\r
+ \r
+ /*---------------------------------------------------------------------------------------------------------*/\r
+ /* Init I/O Multi-function */\r
+ /*---------------------------------------------------------------------------------------------------------*/\r
+ // Configure RMII pins\r
+ SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);\r
+ SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;\r
+ SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);\r
+ SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;\r
+ SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;\r
+ SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;\r
+ SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |\r
+ SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);\r
+ SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |\r
+ SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |\r
+ SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |\r
+ SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |\r
+ SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;\r
+\r
+ // Enable high slew rate on all RMII TX output pins\r
+ PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |\r
+ (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |\r
+ (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);\r
+\r
+\r
+ /* Lock protected registers */\r
+ SYS_LockReg();\r
+\r
+\r
+}\r
+\r
+int numaker_eth_init(uint8_t *mac_addr)\r
+{\r
+ int ret = 0;\r
+ // init CLK & pins\r
+ __eth_clk_pin_init();\r
+ \r
+ // Reset MAC\r
+ EMAC->CTL = EMAC_CTL_RST_Msk;\r
+ while(EMAC->CTL & EMAC_CTL_RST_Msk) {}\r
+\r
+ init_tx_desc();\r
+ init_rx_desc();\r
+\r
+ numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...\r
+\r
+\r
+ /* Configure the MAC interrupt enable register. */\r
+ EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |\r
+ EMAC_INTEN_TXIEN_Msk |\r
+ EMAC_INTEN_RXGDIEN_Msk |\r
+ EMAC_INTEN_TXCPIEN_Msk |\r
+ EMAC_INTEN_RXBEIEN_Msk |\r
+ EMAC_INTEN_TXBEIEN_Msk |\r
+ EMAC_INTEN_RDUIEN_Msk |\r
+ EMAC_INTEN_TSALMIEN_Msk |\r
+ EMAC_INTEN_WOLIEN_Msk;\r
+\r
+ /* Configure the MAC control register. */\r
+ EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;\r
+\r
+ /* Accept packets for us and all broadcast and multicast packets */\r
+ EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |\r
+ EMAC_CAMCTL_AMP_Msk |\r
+ EMAC_CAMCTL_ABP_Msk;\r
+ EMAC->CAMEN = 1; // Enable CAM entry 0 \r
+\r
+ ret= reset_phy(); \r
+ \r
+ EMAC_ENABLE_RX();\r
+ EMAC_ENABLE_TX();\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+void ETH_halt(void)\r
+{\r
+\r
+ EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);\r
+}\r
+\r
+unsigned int m_status;\r
+\r
+void EMAC_RX_IRQHandler(void)\r
+{\r
+// NU_DEBUGF(("%s ... \r\n", __FUNCTION__));\r
+ m_status = EMAC->INTSTS & 0xFFFF;\r
+ EMAC->INTSTS = m_status;\r
+ if (m_status & EMAC_INTSTS_RXBEIF_Msk) {\r
+ // Shouldn't goes here, unless descriptor corrupted\r
+ NU_DEBUGF(("RX descriptor corrupted \r\n"));\r
+ //return;\r
+ }\r
+ // FIX ME: for rx-event, to ack rx_isr into event queue\r
+ xNetworkCallback('R');\r
+}\r
+\r
+\r
+void numaker_eth_trigger_rx(void)\r
+{\r
+ ETH_TRIGGER_RX();\r
+}\r
+\r
+int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)\r
+{\r
+ unsigned int cur_entry, status;\r
+\r
+ cur_entry = EMAC->CRXDSA;\r
+ if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures\r
+ return -1;\r
+ status = cur_rx_desc_ptr->status1;\r
+\r
+ if(status & OWNERSHIP_EMAC)\r
+ return -1;\r
+\r
+ if (status & RXFD_RXGD) {\r
+ *buf = cur_rx_desc_ptr->buf;\r
+ *len = status & 0xFFFF;\r
+ }\r
+ return 0;\r
+} \r
+\r
+void numaker_eth_rx_next(void)\r
+{\r
+ cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;\r
+ cur_rx_desc_ptr = cur_rx_desc_ptr->next; \r
+} \r
+\r
+void EMAC_TX_IRQHandler(void)\r
+{\r
+ unsigned int cur_entry, status;\r
+\r
+ status = EMAC->INTSTS & 0xFFFF0000;\r
+ EMAC->INTSTS = status;\r
+ if(status & EMAC_INTSTS_TXBEIF_Msk) {\r
+ // Shouldn't goes here, unless descriptor corrupted\r
+ return;\r
+ }\r
+\r
+ cur_entry = EMAC->CTXDSA;\r
+\r
+ while (cur_entry != (uint32_t)fin_tx_desc_ptr) {\r
+\r
+ fin_tx_desc_ptr = fin_tx_desc_ptr->next;\r
+ }\r
+ // FIX ME: for tx-event, no-op at this stage\r
+ xNetworkCallback('T');\r
+}\r
+\r
+uint8_t *numaker_eth_get_tx_buf(void)\r
+{\r
+ if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)\r
+ return(NULL);\r
+ else\r
+ return(cur_tx_desc_ptr->buf);\r
+}\r
+\r
+void numaker_eth_trigger_tx(uint16_t length, void *p)\r
+{\r
+ struct eth_descriptor volatile *desc;\r
+ cur_tx_desc_ptr->status2 = (unsigned int)length;\r
+ desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr\r
+ cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;\r
+ cur_tx_desc_ptr = desc;\r
+\r
+ ETH_TRIGGER_TX();\r
+\r
+}\r
+\r
+int numaker_eth_link_ok(void)\r
+{\r
+ /* first, a dummy read to latch */\r
+ mdio_read(CONFIG_PHY_ADDR, MII_BMSR);\r
+ if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)\r
+ return 1;\r
+ return 0; \r
+}\r
+\r
+//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)\r
+//{\r
+// nu_eth_txrx_cb = eth_cb;\r
+// nu_userData = userData;\r
+//}\r
+\r
+// Provide ethernet devices with a semi-unique MAC address\r
+void numaker_mac_address(uint8_t *mac)\r
+{\r
+ uint32_t uID1;\r
+ // Fetch word 0\r
+ uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800\r
+ // Fetch word 1\r
+ // we only want bottom 16 bits of word1 (MAC bits 32-47)\r
+ // and bit 9 forced to 1, bit 8 forced to 0\r
+ // Locally administered MAC, reduced conflicts\r
+ // http://en.wikipedia.org/wiki/MAC_address\r
+ uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800\r
+\r
+ if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash\r
+ {\r
+ // with a semi-unique MAC address from the UUID\r
+ /* Enable FMC ISP function */\r
+ SYS_UnlockReg();\r
+ FMC_Open();\r
+ // = FMC_ReadUID(0);\r
+ uID1 = FMC_ReadUID(1);\r
+ word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;\r
+ word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);\r
+ /* Disable FMC ISP function */\r
+ FMC_Close();\r
+ /* Lock protected registers */\r
+ SYS_LockReg();\r
+ }\r
+\r
+ word1 |= 0x00000200;\r
+ word1 &= 0x0000FEFF;\r
+\r
+ mac[0] = (word1 & 0x0000ff00) >> 8; \r
+ mac[1] = (word1 & 0x000000ff);\r
+ mac[2] = (word0 & 0xff000000) >> 24;\r
+ mac[3] = (word0 & 0x00ff0000) >> 16;\r
+ mac[4] = (word0 & 0x0000ff00) >> 8;\r
+ mac[5] = (word0 & 0x000000ff);\r
+ \r
+ NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));\r
+}\r
+\r
+void numaker_eth_enable_interrupts(void) {\r
+ EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |\r
+ EMAC_INTEN_TXIEN_Msk ;\r
+ NVIC_EnableIRQ(EMAC_RX_IRQn);\r
+ NVIC_EnableIRQ(EMAC_TX_IRQn);\r
+}\r
+\r
+void numaker_eth_disable_interrupts(void) {\r
+ NVIC_DisableIRQ(EMAC_RX_IRQn);\r
+ NVIC_DisableIRQ(EMAC_TX_IRQn);\r
+}\r
-/**************************************************************************//**
- * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
- *
- * 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. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
-*****************************************************************************/
-#include "M480.h"
-#ifndef _M480_ETH_
-#define _M480_ETH_
-
-/* Generic MII registers. */
-
-#define MII_BMCR 0x00 /* Basic mode control register */
-#define MII_BMSR 0x01 /* Basic mode status register */
-#define MII_PHYSID1 0x02 /* PHYS ID 1 */
-#define MII_PHYSID2 0x03 /* PHYS ID 2 */
-#define MII_ADVERTISE 0x04 /* Advertisement control reg */
-#define MII_LPA 0x05 /* Link partner ability reg */
-#define MII_EXPANSION 0x06 /* Expansion register */
-#define MII_DCOUNTER 0x12 /* Disconnect counter */
-#define MII_FCSCOUNTER 0x13 /* False carrier counter */
-#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
-#define MII_RERRCOUNTER 0x15 /* Receive error counter */
-#define MII_SREVISION 0x16 /* Silicon revision */
-#define MII_RESV1 0x17 /* Reserved... */
-#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
-#define MII_PHYADDR 0x19 /* PHY address */
-#define MII_RESV2 0x1a /* Reserved... */
-#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
-#define MII_NCONFIG 0x1c /* Network interface config */
-
-/* Basic mode control register. */
-#define BMCR_RESV 0x007f /* Unused... */
-#define BMCR_CTST 0x0080 /* Collision test */
-#define BMCR_FULLDPLX 0x0100 /* Full duplex */
-#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
-#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
-#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
-#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
-#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
-#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
-#define BMCR_RESET 0x8000 /* Reset the DP83840 */
-
-/* Basic mode status register. */
-#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
-#define BMSR_JCD 0x0002 /* Jabber detected */
-#define BMSR_LSTATUS 0x0004 /* Link status */
-#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
-#define BMSR_RFAULT 0x0010 /* Remote fault detected */
-#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
-#define BMSR_RESV 0x07c0 /* Unused... */
-#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
-#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
-#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
-#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
-#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
-
-/* Advertisement control register. */
-#define ADVERTISE_SLCT 0x001f /* Selector bits */
-#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
-#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
-#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
-#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
-#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
-#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
-#define ADVERTISE_RESV 0x1c00 /* Unused... */
-#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
-#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
-#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
-
-#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors
-#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors
-
-#define PACKET_BUFFER_SIZE 1520
-
-#define CONFIG_PHY_ADDR 1
-
-
-// Frame Descriptor's Owner bit
-#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
-//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
-
-
-
-// Rx Frame Descriptor Status
-#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
-#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
-
-
-// Tx Frame Descriptor's Control bits
-#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
-#define TXFD_INTEN 0x04 // Interrupt Enable
-#define TXFD_CRCAPP 0x02 // Append CRC
-#define TXFD_PADEN 0x01 // Padding Enable
-
-// Tx Frame Descriptor Status
-#define TXFD_TXCP 0x00080000 // Transmission Completion
-#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
-
-// Tx/Rx buffer descriptor structure
-struct eth_descriptor;
-struct eth_descriptor {
- uint32_t status1;
- uint8_t *buf;
- uint32_t status2;
- struct eth_descriptor *next;
-#ifdef TIME_STAMPING
- uint32_t backup1;
- uint32_t backup2;
- uint32_t reserved1;
- uint32_t reserved2;
-#endif
-};
-
-#ifdef TIME_STAMPING
-
-#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
-#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
-s32_t ETH_settime(u32_t sec, u32_t nsec);
-s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
-s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
-s32_t ETH_adjtimex(int ppm);
-void ETH_setinc(void);
-
-#endif
-
-#ifdef NU_TRACE
-#define NU_DEBUGF(x) { printf x; }
-#else
-#define NU_DEBUGF(x)
-#endif
-
-void numaker_set_mac_addr(uint8_t *addr);
-int numaker_eth_init(uint8_t *mac_addr);
-uint8_t *numaker_eth_get_tx_buf(void);
-void numaker_eth_trigger_tx(uint16_t length, void *p);
-int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);
-void numaker_eth_rx_next(void);
-void numaker_eth_trigger_rx(void);
-int numaker_eth_link_ok(void);
-void numaker_mac_address(uint8_t *mac);
-void numaker_eth_enable_interrupts(void);
-void numaker_eth_disable_interrupts(void);
-
-#endif /* _M480_ETH_ */
+/**************************************************************************//**\r
+ * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without modification,\r
+ * are permitted provided that the following conditions are met:\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors\r
+ * may be used to endorse or promote products derived from this software\r
+ * without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*****************************************************************************/\r
+#include "M480.h"\r
+#ifndef _M480_ETH_\r
+#define _M480_ETH_\r
+\r
+/* Generic MII registers. */\r
+\r
+#define MII_BMCR 0x00 /* Basic mode control register */\r
+#define MII_BMSR 0x01 /* Basic mode status register */\r
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */\r
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */\r
+#define MII_ADVERTISE 0x04 /* Advertisement control reg */\r
+#define MII_LPA 0x05 /* Link partner ability reg */\r
+#define MII_EXPANSION 0x06 /* Expansion register */\r
+#define MII_DCOUNTER 0x12 /* Disconnect counter */\r
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */\r
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */\r
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */\r
+#define MII_SREVISION 0x16 /* Silicon revision */\r
+#define MII_RESV1 0x17 /* Reserved... */\r
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */\r
+#define MII_PHYADDR 0x19 /* PHY address */\r
+#define MII_RESV2 0x1a /* Reserved... */\r
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */\r
+#define MII_NCONFIG 0x1c /* Network interface config */\r
+\r
+/* Basic mode control register. */\r
+#define BMCR_RESV 0x007f /* Unused... */\r
+#define BMCR_CTST 0x0080 /* Collision test */\r
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */\r
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */\r
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */\r
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */\r
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */\r
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */\r
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */\r
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */\r
+\r
+/* Basic mode status register. */\r
+#define BMSR_ERCAP 0x0001 /* Ext-reg capability */\r
+#define BMSR_JCD 0x0002 /* Jabber detected */\r
+#define BMSR_LSTATUS 0x0004 /* Link status */\r
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */\r
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */\r
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */\r
+#define BMSR_RESV 0x07c0 /* Unused... */\r
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */\r
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */\r
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */\r
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */\r
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */\r
+\r
+/* Advertisement control register. */\r
+#define ADVERTISE_SLCT 0x001f /* Selector bits */\r
+#define ADVERTISE_CSMA 0x0001 /* Only selector supported */\r
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */\r
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */\r
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */\r
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */\r
+#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */\r
+#define ADVERTISE_RESV 0x1c00 /* Unused... */\r
+#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */\r
+#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */\r
+#define ADVERTISE_NPAGE 0x8000 /* Next page bit */\r
+\r
+#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors\r
+#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors\r
+\r
+#define PACKET_BUFFER_SIZE 1520\r
+\r
+#define CONFIG_PHY_ADDR 1\r
+\r
+\r
+// Frame Descriptor's Owner bit\r
+#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC\r
+//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU\r
+\r
+\r
+\r
+// Rx Frame Descriptor Status\r
+#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received\r
+#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available \r
+\r
+\r
+// Tx Frame Descriptor's Control bits\r
+#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable\r
+#define TXFD_INTEN 0x04 // Interrupt Enable\r
+#define TXFD_CRCAPP 0x02 // Append CRC\r
+#define TXFD_PADEN 0x01 // Padding Enable\r
+\r
+// Tx Frame Descriptor Status\r
+#define TXFD_TXCP 0x00080000 // Transmission Completion\r
+#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available\r
+\r
+// Tx/Rx buffer descriptor structure\r
+struct eth_descriptor;\r
+struct eth_descriptor {\r
+ uint32_t status1;\r
+ uint8_t *buf;\r
+ uint32_t status2;\r
+ struct eth_descriptor *next;\r
+#ifdef TIME_STAMPING\r
+ uint32_t backup1;\r
+ uint32_t backup2;\r
+ uint32_t reserved1;\r
+ uint32_t reserved2;\r
+#endif\r
+};\r
+\r
+#ifdef TIME_STAMPING\r
+\r
+#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)\r
+#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)\r
+s32_t ETH_settime(u32_t sec, u32_t nsec);\r
+s32_t ETH_gettime(u32_t *sec, u32_t *nsec);\r
+s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);\r
+s32_t ETH_adjtimex(int ppm);\r
+void ETH_setinc(void);\r
+\r
+#endif\r
+\r
+#ifdef NU_TRACE\r
+#define NU_DEBUGF(x) { printf x; }\r
+#else\r
+#define NU_DEBUGF(x)\r
+#endif\r
+\r
+void numaker_set_mac_addr(uint8_t *addr);\r
+int numaker_eth_init(uint8_t *mac_addr);\r
+uint8_t *numaker_eth_get_tx_buf(void);\r
+void numaker_eth_trigger_tx(uint16_t length, void *p);\r
+int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);\r
+void numaker_eth_rx_next(void);\r
+void numaker_eth_trigger_rx(void);\r
+int numaker_eth_link_ok(void);\r
+void numaker_mac_address(uint8_t *mac);\r
+void numaker_eth_enable_interrupts(void);\r
+void numaker_eth_disable_interrupts(void);\r
+\r
+#endif /* _M480_ETH_ */\r
-/***********************************************************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
-* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
-* applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
-* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
-* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
-* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
-* this software. By using this software, you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-*
-* Copyright (C) 2018 Renesas Electronics Corporation. All rights reserved.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-* File Name : NetworkInterface.c
-* Device(s) : RX
-* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-* History : DD.MM.YYYY Version Description
-* : 07.03.2018 0.1 Development
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-* Includes <System Includes> , "Project Includes"
-***********************************************************************************************************************/
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-/*#include "FreeRTOS_DNS.h" */
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-#include "r_ether_rx_if.h"
-#include "r_pinset.h"
-
-/***********************************************************************************************************************
- * Macro definitions
- **********************************************************************************************************************/
-#define ETHER_BUFSIZE_MIN 60
-
-#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M )
- #if ETHER_CFG_MODE_SEL == 0
- #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_MII()
- #elif ETHER_CFG_MODE_SEL == 1
- #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_RMII()
- #endif
-#elif defined( BSP_MCU_RX63N )
- #if ETHER_CFG_MODE_SEL == 0
- #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_MII()
- #elif ETHER_CFG_MODE_SEL == 1
- #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_RMII()
- #endif
-#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
-
-/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not
- * receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 2000
-#endif
-
-#ifndef PHY_LS_LOW_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still low every second. */
- #define PHY_LS_LOW_CHECK_TIME_MS 1000
-#endif
-
-/***********************************************************************************************************************
- * Private global variables and functions
- **********************************************************************************************************************/
-typedef enum
-{
- eMACInit, /* Must initialise MAC. */
- eMACPass, /* Initialisation was successful. */
- eMACFailed, /* Initialisation failed. */
-} eMAC_INIT_STATUS_TYPE;
-
-static TaskHandle_t ether_receive_check_task_handle = 0;
-static TaskHandle_t ether_link_check_task_handle = 0;
-static TaskHandle_t xTaskToNotify = NULL;
-static BaseType_t xPHYLinkStatus;
-static BaseType_t xReportedStatus;
-static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
-
-static int16_t SendData( uint8_t * pucBuffer,
- size_t length );
-static int InitializeNetwork( void );
-static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );
-static void clear_all_ether_rx_discriptors( uint32_t event );
-
-int32_t callback_ether_regist( void );
-void EINT_Trig_isr( void * );
-void get_random_number( uint8_t * data,
- uint32_t len );
-
-void prvLinkStatusChange( BaseType_t xStatus );
-#if ( ipconfigHAS_PRINTF != 0 )
- static void prvMonitorResources( void );
-#endif
-
-/***********************************************************************************************************************
- * Function Name: xNetworkInterfaceInitialise ()
- * Description : Initialization of Ethernet driver.
- * Arguments : none
- * Return Value : pdPASS, pdFAIL
- **********************************************************************************************************************/
-BaseType_t xNetworkInterfaceInitialise( void )
-{
- BaseType_t xReturn;
-
- if( xMacInitStatus == eMACInit )
- {
- /*
- * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
- * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
- *
- * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
- */
- if( InitializeNetwork() == pdFALSE )
- {
- xMacInitStatus = eMACFailed;
- }
- else
- {
- /* Indicate that the MAC initialisation succeeded. */
- xMacInitStatus = eMACPass;
- }
-
- FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
- }
-
- if( xMacInitStatus == eMACPass )
- {
- xReturn = xPHYLinkStatus;
- }
- else
- {
- xReturn = pdFAIL;
- }
-
- FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
-
- return xReturn;
-} /* End of function xNetworkInterfaceInitialise() */
-
-
-/***********************************************************************************************************************
- * Function Name: xNetworkInterfaceOutput ()
- * Description : Simple network output interface.
- * Arguments : pxDescriptor, xReleaseAfterSend
- * Return Value : pdTRUE, pdFALSE
- **********************************************************************************************************************/
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
- BaseType_t xReleaseAfterSend )
-{
- BaseType_t xReturn = pdFALSE;
-
- /* Simple network interfaces (as opposed to more efficient zero copy network
- * interfaces) just use Ethernet peripheral driver library functions to copy
- * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.
- * This example assumes SendData() is a peripheral driver library function that
- * takes a pointer to the start of the data to be sent and the length of the
- * data to be sent as two separate parameters. The start of the data is located
- * by pxDescriptor->pucEthernetBuffer. The length of the data is located
- * by pxDescriptor->xDataLength. */
- if( xPHYLinkStatus != 0 )
- {
- if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )
- {
- xReturn = pdTRUE;
- /* Call the standard trace macro to log the send event. */
- iptraceNETWORK_INTERFACE_TRANSMIT();
- }
- }
- else
- {
- /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */
- }
-
- if( xReleaseAfterSend != pdFALSE )
- {
- /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
- * buffer. The Ethernet buffer is therefore no longer needed, and must be
- * freed for re-use. */
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
-
- return xReturn;
-} /* End of function xNetworkInterfaceOutput() */
-
-
-#if ( ipconfigHAS_PRINTF != 0 )
- static void prvMonitorResources()
- {
- static UBaseType_t uxLastMinBufferCount = 0u;
- static UBaseType_t uxCurrentBufferCount = 0u;
- static size_t uxMinLastSize = 0uL;
- static size_t uxCurLastSize = 0uL;
- size_t uxMinSize;
- size_t uxCurSize;
-
- uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
-
- if( uxLastMinBufferCount != uxCurrentBufferCount )
- {
- /* The logging produced below may be helpful
- * while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentBufferCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );
- }
-
- uxMinSize = xPortGetMinimumEverFreeHeapSize();
- uxCurSize = xPortGetFreeHeapSize();
-
- if( uxMinLastSize != uxMinSize )
- {
- uxCurLastSize = uxCurSize;
- uxMinLastSize = uxMinSize;
- FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", uxCurSize, uxMinSize ) );
- }
-
- #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- {
- static UBaseType_t uxLastMinQueueSpace = 0;
- UBaseType_t uxCurrentCount = 0u;
-
- 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 */
- }
-#endif /* ( ipconfigHAS_PRINTF != 0 ) */
-
-/***********************************************************************************************************************
- * Function Name: prvEMACDeferredInterruptHandlerTask ()
- * Description : The deferred interrupt handler is a standard RTOS task.
- * Arguments : pvParameters
- * Return Value : none
- **********************************************************************************************************************/
-static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )
-{
- NetworkBufferDescriptor_t * pxBufferDescriptor;
- int32_t xBytesReceived = 0;
-
- /* Avoid compiler warning about unreferenced parameter. */
- ( void ) pvParameters;
-
- /* Used to indicate that xSendEventStructToIPTask() is being called because
- * of an Ethernet receive event. */
- IPStackEvent_t xRxEvent;
-
- uint8_t * buffer_pointer;
-
- /* Some variables related to monitoring the PHY. */
- TimeOut_t xPhyTime;
- TickType_t xPhyRemTime;
- const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
- FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );
- xTaskToNotify = ether_receive_check_task_handle;
-
- for( ; ; )
- {
- #if ( ipconfigHAS_PRINTF != 0 )
- {
- prvMonitorResources();
- }
- #endif /* ipconfigHAS_PRINTF != 0 ) */
-
- /* Wait for the Ethernet MAC interrupt to indicate that another packet
- * has been received. */
- if( xBytesReceived <= 0 )
- {
- ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
- }
-
- /* See how much data was received. */
- xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
-
- if( xBytesReceived < 0 )
- {
- /* This is an error. Logged. */
- FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );
- }
- else if( xBytesReceived > 0 )
- {
- /* Allocate a network buffer descriptor that points to a buffer
- * large enough to hold the received frame. As this is the simple
- * rather than efficient example the received data will just be copied
- * into this buffer. */
- pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );
-
- if( pxBufferDescriptor != NULL )
- {
- /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet
- * buffer large enough to hold the received data. Copy the
- * received data into pcNetworkBuffer->pucEthernetBuffer. Here it
- * is assumed ReceiveData() is a peripheral driver function that
- * copies the received data into a buffer passed in as the function's
- * parameter. Remember! While is is a simple robust technique -
- * it is not efficient. An example that uses a zero copy technique
- * is provided further down this page. */
- memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );
- /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */
-
- /* Set the actual packet length, in case a larger buffer was returned. */
- pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;
-
- R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
-
- /* See if the data contained in the received Ethernet frame needs
- * to be processed. NOTE! It is preferable to do this in
- * the interrupt service routine itself, which would remove the need
- * to unblock this task for packets that don't need processing. */
- if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer )
- {
- /* The event about to be sent to the TCP/IP is an Rx event. */
- xRxEvent.eEventType = eNetworkRxEvent;
-
- /* pvData is used to point to the network buffer descriptor that
- * now references the received data. */
- xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
- /* Send the data to the TCP/IP stack. */
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
- {
- /* The buffer could not be sent to the IP task so the buffer must be released. */
- vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-
- /* Make a call to the standard trace macro to log the occurrence. */
- iptraceETHERNET_RX_EVENT_LOST();
- clear_all_ether_rx_discriptors( 0 );
- }
- else
- {
- /* The message was successfully sent to the TCP/IP stack.
- * Call the standard trace macro to log the occurrence. */
- iptraceNETWORK_INTERFACE_RECEIVE();
- R_NOP();
- }
- }
- else
- {
- /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */
- vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
- }
- }
- else
- {
- /* The event was lost because a network buffer was not available.
- * Call the standard trace macro to log the occurrence. */
- iptraceETHERNET_RX_EVENT_LOST();
- clear_all_ether_rx_discriptors( 1 );
- FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );
- }
- }
-
- if( xBytesReceived > 0 )
- {
- /* A packet was received. No need to check for the PHY status now,
- * but set a timer to check it later on. */
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-
- /* Indicate that the Link Status is high, so that
- * xNetworkInterfaceOutput() can send packets. */
- if( xPHYLinkStatus == 0 )
- {
- xPHYLinkStatus = 1;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );
- }
- }
- else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )
- {
- R_ETHER_LinkProcess( 0 );
-
- if( xPHYLinkStatus != xReportedStatus )
- {
- xPHYLinkStatus = xReportedStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
-
- if( xPHYLinkStatus != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-} /* End of function prvEMACDeferredInterruptHandlerTask() */
-
-
-/***********************************************************************************************************************
- * Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
- * Description : .
- * Arguments : pxNetworkBuffers
- * Return Value : none
- **********************************************************************************************************************/
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
- uint32_t ul;
- uint8_t * buffer_address;
-
- R_EXTERN_SEC( B_ETHERNET_BUFFERS_1 )
-
- buffer_address = R_SECTOP( B_ETHERNET_BUFFERS_1 );
-
- for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
- {
- pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) );
- }
-} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
-
-
-/***********************************************************************************************************************
- * Function Name: prvLinkStatusChange ()
- * Description : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )
- * Arguments : xStatus : true when statyus has become high
- * Return Value : void
- **********************************************************************************************************************/
-void prvLinkStatusChange( BaseType_t xStatus )
-{
- if( xReportedStatus != xStatus )
- {
- FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );
- xReportedStatus = xStatus;
- }
-}
-
-/***********************************************************************************************************************
- * Function Name: InitializeNetwork ()
- * Description :
- * Arguments : none
- * Return Value : pdTRUE, pdFALSE
- **********************************************************************************************************************/
-static int InitializeNetwork( void )
-{
- ether_return_t eth_ret;
- BaseType_t return_code = pdFALSE;
- ether_param_t param;
- uint8_t myethaddr[ 6 ] =
- {
- configMAC_ADDR0,
- configMAC_ADDR1,
- configMAC_ADDR2,
- configMAC_ADDR3,
- configMAC_ADDR4,
- configMAC_ADDR5
- }; /*XXX Fix me */
-
- R_ETHER_PinSet_CHANNEL_0();
- R_ETHER_Initial();
- callback_ether_regist();
-
- param.channel = ETHER_CHANNEL_0;
- eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */
-
- if( ETHER_SUCCESS != eth_ret )
- {
- return pdFALSE;
- }
-
- eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );
-
- if( ETHER_SUCCESS != eth_ret )
- {
- return pdFALSE;
- }
-
- return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,
- "ETHER_RECEIVE_CHECK_TASK",
- 512u,
- 0,
- configMAX_PRIORITIES - 1,
- ðer_receive_check_task_handle );
-
- if( pdFALSE == return_code )
- {
- return pdFALSE;
- }
-
- return pdTRUE;
-} /* End of function InitializeNetwork() */
-
-
-/***********************************************************************************************************************
- * Function Name: SendData ()
- * Description :
- * Arguments : pucBuffer, length
- * Return Value : 0 success, negative fail
- **********************************************************************************************************************/
-static int16_t SendData( uint8_t * pucBuffer,
- size_t length ) /*TODO complete stub function */
-{
- ether_return_t ret;
- uint8_t * pwrite_buffer;
- uint16_t write_buf_size;
-
- /* (1) Retrieve the transmit buffer location controlled by the descriptor. */
- ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );
-
- if( ETHER_SUCCESS == ret )
- {
- if( write_buf_size >= length )
- {
- memcpy( pwrite_buffer, pucBuffer, length );
- }
-
- if( length < ETHER_BUFSIZE_MIN ) /*under minimum*/
- {
- memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/
- length = ETHER_BUFSIZE_MIN; /*resize*/
- }
-
- ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );
- ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );
- }
-
- if( ETHER_SUCCESS != ret )
- {
- return -5; /* XXX return meaningful value */
- }
- else
- {
- return 0;
- }
-} /* End of function SendData() */
-
-
-/***********************************************************************************************************************
-* Function Name: EINT_Trig_isr
-* Description : Standard frame received interrupt handler
-* Arguments : ectrl - EDMAC and ETHERC control structure
-* Return Value : None
-* Note : This callback function is executed when EINT0 interrupt occurred.
-***********************************************************************************************************************/
-void EINT_Trig_isr( void * ectrl )
-{
- ether_cb_arg_t * pdecode;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- pdecode = ( ether_cb_arg_t * ) ectrl;
-
- if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */
- {
- if( xTaskToNotify != NULL )
- {
- vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );
- }
-
- /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
- * should be performed to ensure the interrupt returns directly to the highest
- * priority task. The macro used for this purpose is dependent on the port in
- * use and may be called portEND_SWITCHING_ISR(). */
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
- /*TODO complete interrupt handler for other events. */
- }
-} /* End of function EINT_Trig_isr() */
-
-
-static void clear_all_ether_rx_discriptors( uint32_t event )
-{
- int32_t xBytesReceived;
- uint8_t * buffer_pointer;
-
- /* Avoid compiler warning about unreferenced parameter. */
- ( void ) event;
-
- while( 1 )
- {
- /* See how much data was received. */
- xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
-
- if( 0 > xBytesReceived )
- {
- /* This is an error. Ignored. */
- }
- else if( 0 < xBytesReceived )
- {
- R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
- iptraceETHERNET_RX_EVENT_LOST();
- }
- else
- {
- break;
- }
- }
-}
-
-/***********************************************************************************************************************
- * End of file "NetworkInterface.c"
- **********************************************************************************************************************/
+/***********************************************************************************************************************\r
+* DISCLAIMER\r
+* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No\r
+* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all\r
+* applicable laws, including copyright laws.\r
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING\r
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM\r
+* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES\r
+* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS\r
+* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r
+* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of\r
+* this software. By using this software, you agree to the additional terms and conditions found by accessing the\r
+* following link:\r
+* http://www.renesas.com/disclaimer\r
+*\r
+* Copyright (C) 2018 Renesas Electronics Corporation. All rights reserved.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+* File Name : NetworkInterface.c\r
+* Device(s) : RX\r
+* Description : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+* History : DD.MM.YYYY Version Description\r
+* : 07.03.2018 0.1 Development\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+* Includes <System Includes> , "Project Includes"\r
+***********************************************************************************************************************/\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+/*#include "FreeRTOS_DNS.h" */\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "r_ether_rx_if.h"\r
+#include "r_pinset.h"\r
+\r
+/***********************************************************************************************************************\r
+ * Macro definitions\r
+ **********************************************************************************************************************/\r
+#define ETHER_BUFSIZE_MIN 60\r
+\r
+#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M )\r
+ #if ETHER_CFG_MODE_SEL == 0\r
+ #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_MII()\r
+ #elif ETHER_CFG_MODE_SEL == 1\r
+ #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC0_RMII()\r
+ #endif\r
+#elif defined( BSP_MCU_RX63N )\r
+ #if ETHER_CFG_MODE_SEL == 0\r
+ #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_MII()\r
+ #elif ETHER_CFG_MODE_SEL == 1\r
+ #define R_ETHER_PinSet_CHANNEL_0() R_ETHER_PinSet_ETHERC_RMII()\r
+ #endif\r
+#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+\r
+/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not\r
+ * receiving packets. */\r
+ #define PHY_LS_HIGH_CHECK_TIME_MS 2000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still low every second. */\r
+ #define PHY_LS_LOW_CHECK_TIME_MS 1000\r
+#endif\r
+\r
+/***********************************************************************************************************************\r
+ * Private global variables and functions\r
+ **********************************************************************************************************************/\r
+typedef enum\r
+{\r
+ eMACInit, /* Must initialise MAC. */\r
+ eMACPass, /* Initialisation was successful. */\r
+ eMACFailed, /* Initialisation failed. */\r
+} eMAC_INIT_STATUS_TYPE;\r
+\r
+static TaskHandle_t ether_receive_check_task_handle = 0;\r
+static TaskHandle_t ether_link_check_task_handle = 0;\r
+static TaskHandle_t xTaskToNotify = NULL;\r
+static BaseType_t xPHYLinkStatus;\r
+static BaseType_t xReportedStatus;\r
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
+\r
+static int16_t SendData( uint8_t * pucBuffer,\r
+ size_t length );\r
+static int InitializeNetwork( void );\r
+static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );\r
+static void clear_all_ether_rx_discriptors( uint32_t event );\r
+\r
+int32_t callback_ether_regist( void );\r
+void EINT_Trig_isr( void * );\r
+void get_random_number( uint8_t * data,\r
+ uint32_t len );\r
+\r
+void prvLinkStatusChange( BaseType_t xStatus );\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ static void prvMonitorResources( void );\r
+#endif\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: xNetworkInterfaceInitialise ()\r
+ * Description : Initialization of Ethernet driver.\r
+ * Arguments : none\r
+ * Return Value : pdPASS, pdFAIL\r
+ **********************************************************************************************************************/\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+ BaseType_t xReturn;\r
+\r
+ if( xMacInitStatus == eMACInit )\r
+ {\r
+ /*\r
+ * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the\r
+ * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.\r
+ *\r
+ * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.\r
+ */\r
+ if( InitializeNetwork() == pdFALSE )\r
+ {\r
+ xMacInitStatus = eMACFailed;\r
+ }\r
+ else\r
+ {\r
+ /* Indicate that the MAC initialisation succeeded. */\r
+ xMacInitStatus = eMACPass;\r
+ }\r
+\r
+ FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );\r
+ }\r
+\r
+ if( xMacInitStatus == eMACPass )\r
+ {\r
+ xReturn = xPHYLinkStatus;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );\r
+\r
+ return xReturn;\r
+} /* End of function xNetworkInterfaceInitialise() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: xNetworkInterfaceOutput ()\r
+ * Description : Simple network output interface.\r
+ * Arguments : pxDescriptor, xReleaseAfterSend\r
+ * Return Value : pdTRUE, pdFALSE\r
+ **********************************************************************************************************************/\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+ BaseType_t xReleaseAfterSend )\r
+{\r
+ BaseType_t xReturn = pdFALSE;\r
+\r
+ /* Simple network interfaces (as opposed to more efficient zero copy network\r
+ * interfaces) just use Ethernet peripheral driver library functions to copy\r
+ * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.\r
+ * This example assumes SendData() is a peripheral driver library function that\r
+ * takes a pointer to the start of the data to be sent and the length of the\r
+ * data to be sent as two separate parameters. The start of the data is located\r
+ * by pxDescriptor->pucEthernetBuffer. The length of the data is located\r
+ * by pxDescriptor->xDataLength. */\r
+ if( xPHYLinkStatus != 0 )\r
+ {\r
+ if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )\r
+ {\r
+ xReturn = pdTRUE;\r
+ /* Call the standard trace macro to log the send event. */\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */\r
+ }\r
+\r
+ if( xReleaseAfterSend != pdFALSE )\r
+ {\r
+ /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet\r
+ * buffer. The Ethernet buffer is therefore no longer needed, and must be\r
+ * freed for re-use. */\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+\r
+ return xReturn;\r
+} /* End of function xNetworkInterfaceOutput() */\r
+\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ static void prvMonitorResources()\r
+ {\r
+ static UBaseType_t uxLastMinBufferCount = 0u;\r
+ static UBaseType_t uxCurrentBufferCount = 0u;\r
+ static size_t uxMinLastSize = 0uL;\r
+ static size_t uxCurLastSize = 0uL;\r
+ size_t uxMinSize;\r
+ size_t uxCurSize;\r
+\r
+ uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();\r
+\r
+ if( uxLastMinBufferCount != uxCurrentBufferCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ * while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentBufferCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );\r
+ }\r
+\r
+ uxMinSize = xPortGetMinimumEverFreeHeapSize();\r
+ uxCurSize = xPortGetFreeHeapSize();\r
+\r
+ if( uxMinLastSize != uxMinSize )\r
+ {\r
+ uxCurLastSize = uxCurSize;\r
+ uxMinLastSize = uxMinSize;\r
+ FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", uxCurSize, uxMinSize ) );\r
+ }\r
+\r
+ #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ static UBaseType_t uxLastMinQueueSpace = 0;\r
+ UBaseType_t uxCurrentCount = 0u;\r
+\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+\r
+ if( uxLastMinQueueSpace != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ * while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinQueueSpace = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+ }\r
+ }\r
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+ }\r
+#endif /* ( ipconfigHAS_PRINTF != 0 ) */\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: prvEMACDeferredInterruptHandlerTask ()\r
+ * Description : The deferred interrupt handler is a standard RTOS task.\r
+ * Arguments : pvParameters\r
+ * Return Value : none\r
+ **********************************************************************************************************************/\r
+static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )\r
+{\r
+ NetworkBufferDescriptor_t * pxBufferDescriptor;\r
+ int32_t xBytesReceived = 0;\r
+\r
+ /* Avoid compiler warning about unreferenced parameter. */\r
+ ( void ) pvParameters;\r
+\r
+ /* Used to indicate that xSendEventStructToIPTask() is being called because\r
+ * of an Ethernet receive event. */\r
+ IPStackEvent_t xRxEvent;\r
+\r
+ uint8_t * buffer_pointer;\r
+\r
+ /* Some variables related to monitoring the PHY. */\r
+ TimeOut_t xPhyTime;\r
+ TickType_t xPhyRemTime;\r
+ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+ FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );\r
+ xTaskToNotify = ether_receive_check_task_handle;\r
+\r
+ for( ; ; )\r
+ {\r
+ #if ( ipconfigHAS_PRINTF != 0 )\r
+ {\r
+ prvMonitorResources();\r
+ }\r
+ #endif /* ipconfigHAS_PRINTF != 0 ) */\r
+\r
+ /* Wait for the Ethernet MAC interrupt to indicate that another packet\r
+ * has been received. */\r
+ if( xBytesReceived <= 0 )\r
+ {\r
+ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+ }\r
+\r
+ /* See how much data was received. */\r
+ xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );\r
+\r
+ if( xBytesReceived < 0 )\r
+ {\r
+ /* This is an error. Logged. */\r
+ FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );\r
+ }\r
+ else if( xBytesReceived > 0 )\r
+ {\r
+ /* Allocate a network buffer descriptor that points to a buffer\r
+ * large enough to hold the received frame. As this is the simple\r
+ * rather than efficient example the received data will just be copied\r
+ * into this buffer. */\r
+ pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );\r
+\r
+ if( pxBufferDescriptor != NULL )\r
+ {\r
+ /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet\r
+ * buffer large enough to hold the received data. Copy the\r
+ * received data into pcNetworkBuffer->pucEthernetBuffer. Here it\r
+ * is assumed ReceiveData() is a peripheral driver function that\r
+ * copies the received data into a buffer passed in as the function's\r
+ * parameter. Remember! While is is a simple robust technique -\r
+ * it is not efficient. An example that uses a zero copy technique\r
+ * is provided further down this page. */\r
+ memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );\r
+ /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */\r
+\r
+ /* Set the actual packet length, in case a larger buffer was returned. */\r
+ pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;\r
+\r
+ R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );\r
+\r
+ /* See if the data contained in the received Ethernet frame needs\r
+ * to be processed. NOTE! It is preferable to do this in\r
+ * the interrupt service routine itself, which would remove the need\r
+ * to unblock this task for packets that don't need processing. */\r
+ if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer )\r
+ {\r
+ /* The event about to be sent to the TCP/IP is an Rx event. */\r
+ xRxEvent.eEventType = eNetworkRxEvent;\r
+\r
+ /* pvData is used to point to the network buffer descriptor that\r
+ * now references the received data. */\r
+ xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+ /* Send the data to the TCP/IP stack. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+ {\r
+ /* The buffer could not be sent to the IP task so the buffer must be released. */\r
+ vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+\r
+ /* Make a call to the standard trace macro to log the occurrence. */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ clear_all_ether_rx_discriptors( 0 );\r
+ }\r
+ else\r
+ {\r
+ /* The message was successfully sent to the TCP/IP stack.\r
+ * Call the standard trace macro to log the occurrence. */\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ R_NOP();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */\r
+ vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The event was lost because a network buffer was not available.\r
+ * Call the standard trace macro to log the occurrence. */\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ clear_all_ether_rx_discriptors( 1 );\r
+ FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );\r
+ }\r
+ }\r
+\r
+ if( xBytesReceived > 0 )\r
+ {\r
+ /* A packet was received. No need to check for the PHY status now,\r
+ * but set a timer to check it later on. */\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+\r
+ /* Indicate that the Link Status is high, so that\r
+ * xNetworkInterfaceOutput() can send packets. */\r
+ if( xPHYLinkStatus == 0 )\r
+ {\r
+ xPHYLinkStatus = 1;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );\r
+ }\r
+ }\r
+ else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )\r
+ {\r
+ R_ETHER_LinkProcess( 0 );\r
+\r
+ if( xPHYLinkStatus != xReportedStatus )\r
+ {\r
+ xPHYLinkStatus = xReportedStatus;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );\r
+ }\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+\r
+ if( xPHYLinkStatus != 0 )\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ }\r
+ else\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ }\r
+ }\r
+ }\r
+} /* End of function prvEMACDeferredInterruptHandlerTask() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: vNetworkInterfaceAllocateRAMToBuffers ()\r
+ * Description : .\r
+ * Arguments : pxNetworkBuffers\r
+ * Return Value : none\r
+ **********************************************************************************************************************/\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+ uint32_t ul;\r
+ uint8_t * buffer_address;\r
+\r
+ R_EXTERN_SEC( B_ETHERNET_BUFFERS_1 )\r
+\r
+ buffer_address = R_SECTOP( B_ETHERNET_BUFFERS_1 );\r
+\r
+ for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+ {\r
+ pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) );\r
+ }\r
+} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: prvLinkStatusChange ()\r
+ * Description : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )\r
+ * Arguments : xStatus : true when statyus has become high\r
+ * Return Value : void\r
+ **********************************************************************************************************************/\r
+void prvLinkStatusChange( BaseType_t xStatus )\r
+{\r
+ if( xReportedStatus != xStatus )\r
+ {\r
+ FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );\r
+ xReportedStatus = xStatus;\r
+ }\r
+}\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: InitializeNetwork ()\r
+ * Description :\r
+ * Arguments : none\r
+ * Return Value : pdTRUE, pdFALSE\r
+ **********************************************************************************************************************/\r
+static int InitializeNetwork( void )\r
+{\r
+ ether_return_t eth_ret;\r
+ BaseType_t return_code = pdFALSE;\r
+ ether_param_t param;\r
+ uint8_t myethaddr[ 6 ] =\r
+ {\r
+ configMAC_ADDR0,\r
+ configMAC_ADDR1,\r
+ configMAC_ADDR2,\r
+ configMAC_ADDR3,\r
+ configMAC_ADDR4,\r
+ configMAC_ADDR5\r
+ }; /*XXX Fix me */\r
+\r
+ R_ETHER_PinSet_CHANNEL_0();\r
+ R_ETHER_Initial();\r
+ callback_ether_regist();\r
+\r
+ param.channel = ETHER_CHANNEL_0;\r
+ eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */\r
+\r
+ if( ETHER_SUCCESS != eth_ret )\r
+ {\r
+ return pdFALSE;\r
+ }\r
+\r
+ eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );\r
+\r
+ if( ETHER_SUCCESS != eth_ret )\r
+ {\r
+ return pdFALSE;\r
+ }\r
+\r
+ return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,\r
+ "ETHER_RECEIVE_CHECK_TASK",\r
+ 512u,\r
+ 0,\r
+ configMAX_PRIORITIES - 1,\r
+ ðer_receive_check_task_handle );\r
+\r
+ if( pdFALSE == return_code )\r
+ {\r
+ return pdFALSE;\r
+ }\r
+\r
+ return pdTRUE;\r
+} /* End of function InitializeNetwork() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: SendData ()\r
+ * Description :\r
+ * Arguments : pucBuffer, length\r
+ * Return Value : 0 success, negative fail\r
+ **********************************************************************************************************************/\r
+static int16_t SendData( uint8_t * pucBuffer,\r
+ size_t length ) /*TODO complete stub function */\r
+{\r
+ ether_return_t ret;\r
+ uint8_t * pwrite_buffer;\r
+ uint16_t write_buf_size;\r
+\r
+ /* (1) Retrieve the transmit buffer location controlled by the descriptor. */\r
+ ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );\r
+\r
+ if( ETHER_SUCCESS == ret )\r
+ {\r
+ if( write_buf_size >= length )\r
+ {\r
+ memcpy( pwrite_buffer, pucBuffer, length );\r
+ }\r
+\r
+ if( length < ETHER_BUFSIZE_MIN ) /*under minimum*/\r
+ {\r
+ memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/\r
+ length = ETHER_BUFSIZE_MIN; /*resize*/\r
+ }\r
+\r
+ ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );\r
+ ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );\r
+ }\r
+\r
+ if( ETHER_SUCCESS != ret )\r
+ {\r
+ return -5; /* XXX return meaningful value */\r
+ }\r
+ else\r
+ {\r
+ return 0;\r
+ }\r
+} /* End of function SendData() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: EINT_Trig_isr\r
+* Description : Standard frame received interrupt handler\r
+* Arguments : ectrl - EDMAC and ETHERC control structure\r
+* Return Value : None\r
+* Note : This callback function is executed when EINT0 interrupt occurred.\r
+***********************************************************************************************************************/\r
+void EINT_Trig_isr( void * ectrl )\r
+{\r
+ ether_cb_arg_t * pdecode;\r
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+ pdecode = ( ether_cb_arg_t * ) ectrl;\r
+\r
+ if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */\r
+ {\r
+ if( xTaskToNotify != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );\r
+ }\r
+\r
+ /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch\r
+ * should be performed to ensure the interrupt returns directly to the highest\r
+ * priority task. The macro used for this purpose is dependent on the port in\r
+ * use and may be called portEND_SWITCHING_ISR(). */\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+ /*TODO complete interrupt handler for other events. */\r
+ }\r
+} /* End of function EINT_Trig_isr() */\r
+\r
+\r
+static void clear_all_ether_rx_discriptors( uint32_t event )\r
+{\r
+ int32_t xBytesReceived;\r
+ uint8_t * buffer_pointer;\r
+\r
+ /* Avoid compiler warning about unreferenced parameter. */\r
+ ( void ) event;\r
+\r
+ while( 1 )\r
+ {\r
+ /* See how much data was received. */\r
+ xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );\r
+\r
+ if( 0 > xBytesReceived )\r
+ {\r
+ /* This is an error. Ignored. */\r
+ }\r
+ else if( 0 < xBytesReceived )\r
+ {\r
+ R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/***********************************************************************************************************************\r
+ * End of file "NetworkInterface.c"\r
+ **********************************************************************************************************************/\r
-/***********************************************************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
-* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
-* applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
-* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
-* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
-* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
-* this software. By using this software, you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-*
-* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
-***********************************************************************************************************************/
-/***********************************************************************************************************************
-* File Name : ether_callback.c
-* Version : ----
-* Description : This module solves all the world's problems
-***********************************************************************************************************************/
-/**********************************************************************************************************************
-* History : DD.MM.YYYY Version Description
-* : 05.01.2015 ---- Clean up source code.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-Includes <System Includes> , "Project Includes"
-***********************************************************************************************************************/
-#include "r_ether_rx_if.h"
-
-/***********************************************************************************************************************
-Private global variables and functions
-***********************************************************************************************************************/
-int32_t callback_ether_regist(void);
-void callback_ether(void * pparam);
-static void callback_wakeon_lan(uint32_t channel);
-static void callback_link_on(uint32_t channel);
-static void callback_link_off(uint32_t channel);
-
-volatile uint8_t pause_enable = ETHER_FLAG_OFF;
-volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX];
-volatile uint8_t link_detect[ETHER_CHANNEL_MAX];
-
-void EINT_Trig_isr(void *);
-
-/*
- * When that Link Status changes, the following function will be called:
- */
-void prvLinkStatusChange( BaseType_t xStatus );
-
-/***********************************************************************************************************************
-* Function Name: callback_ether
-* Description : Regist of callback function
-* Arguments : -
-* Return Value : 0: success, -1:failed
-***********************************************************************************************************************/
-int32_t callback_ether_regist(void)
-{
- ether_param_t param;
- ether_cb_t cb_func;
-
- int32_t ret;
-
- /* Set the callback function (LAN cable connect/disconnect event) */
- cb_func.pcb_func = &callback_ether;
- param.ether_callback = cb_func;
- ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);
- if (ETHER_SUCCESS != ret)
- {
- return -1;
- }
-
- /* Set the callback function (Ether interrupt event) */
- cb_func.pcb_int_hnd = &EINT_Trig_isr;
- param.ether_callback = cb_func;
- ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);
- if (ETHER_SUCCESS != ret)
- {
- return -1;
- }
- return 0;
-} /* End of function callback_ether_regist() */
-
-/***********************************************************************************************************************
-* Function Name: callback_ether
-* Description : Sample of the callback function
-* Arguments : pparam -
-*
-* Return Value : none
-***********************************************************************************************************************/
-void callback_ether(void * pparam)
-{
- ether_cb_arg_t * pdecode;
- uint32_t channel;
-
- pdecode = (ether_cb_arg_t *)pparam;
- channel = pdecode->channel; /* Get Ethernet channel number */
-
- switch (pdecode->event_id)
- {
- /* Callback function that notifies user to have detected magic packet. */
- case ETHER_CB_EVENT_ID_WAKEON_LAN:
- callback_wakeon_lan(channel);
- break;
-
- /* Callback function that notifies user to have become Link up. */
- case ETHER_CB_EVENT_ID_LINK_ON:
- callback_link_on(channel);
- break;
-
- /* Callback function that notifies user to have become Link down. */
- case ETHER_CB_EVENT_ID_LINK_OFF:
- callback_link_off(channel);
- break;
-
- default:
- break;
- }
-} /* End of function callback_ether() */
-
-/***********************************************************************************************************************
-* Function Name: callback_wakeon_lan
-* Description :
-* Arguments : channel -
-* Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_wakeon_lan(uint32_t channel)
-{
- if (ETHER_CHANNEL_MAX > channel)
- {
- magic_packet_detect[channel] = 1;
-
- /* Please add necessary processing when magic packet is detected. */
- }
-} /* End of function callback_wakeon_lan() */
-
-/***********************************************************************************************************************
-* Function Name: callback_link_on
-* Description :
-* Arguments : channel -
-* Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_link_on(uint32_t channel)
-{
- if (ETHER_CHANNEL_MAX > channel)
- {
- link_detect[channel] = ETHER_FLAG_ON_LINK_ON;
-
- /* Please add necessary processing when becoming Link up. */
- prvLinkStatusChange( 1 );
- }
-} /* End of function callback_link_on() */
-
-/***********************************************************************************************************************
-* Function Name: callback_link_off
-* Description :
-* Arguments : channel -
-* Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_link_off(uint32_t channel)
-{
- if (ETHER_CHANNEL_MAX > channel)
- {
- link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;
-
- /* Please add necessary processing when becoming Link down. */
- prvLinkStatusChange( 0 );
- }
-} /* End of function ether_cb_link_off() */
-
-/* End of File */
+/***********************************************************************************************************************\r
+* DISCLAIMER\r
+* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No\r
+* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all\r
+* applicable laws, including copyright laws.\r
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING\r
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM\r
+* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES\r
+* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS\r
+* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r
+* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of\r
+* this software. By using this software, you agree to the additional terms and conditions found by accessing the\r
+* following link:\r
+* http://www.renesas.com/disclaimer\r
+*\r
+* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.\r
+***********************************************************************************************************************/\r
+/***********************************************************************************************************************\r
+* File Name : ether_callback.c\r
+* Version : ----\r
+* Description : This module solves all the world's problems\r
+***********************************************************************************************************************/\r
+/**********************************************************************************************************************\r
+* History : DD.MM.YYYY Version Description\r
+* : 05.01.2015 ---- Clean up source code.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+Includes <System Includes> , "Project Includes"\r
+***********************************************************************************************************************/\r
+#include "r_ether_rx_if.h"\r
+\r
+/***********************************************************************************************************************\r
+Private global variables and functions\r
+***********************************************************************************************************************/\r
+int32_t callback_ether_regist(void);\r
+void callback_ether(void * pparam);\r
+static void callback_wakeon_lan(uint32_t channel);\r
+static void callback_link_on(uint32_t channel);\r
+static void callback_link_off(uint32_t channel);\r
+\r
+volatile uint8_t pause_enable = ETHER_FLAG_OFF;\r
+volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX];\r
+volatile uint8_t link_detect[ETHER_CHANNEL_MAX];\r
+\r
+void EINT_Trig_isr(void *);\r
+\r
+/*\r
+ * When that Link Status changes, the following function will be called:\r
+ */\r
+void prvLinkStatusChange( BaseType_t xStatus );\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_ether\r
+* Description : Regist of callback function\r
+* Arguments : -\r
+* Return Value : 0: success, -1:failed\r
+***********************************************************************************************************************/\r
+int32_t callback_ether_regist(void)\r
+{\r
+ ether_param_t param;\r
+ ether_cb_t cb_func;\r
+\r
+ int32_t ret;\r
+\r
+ /* Set the callback function (LAN cable connect/disconnect event) */\r
+ cb_func.pcb_func = &callback_ether;\r
+ param.ether_callback = cb_func;\r
+ ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);\r
+ if (ETHER_SUCCESS != ret)\r
+ {\r
+ return -1;\r
+ }\r
+\r
+ /* Set the callback function (Ether interrupt event) */\r
+ cb_func.pcb_int_hnd = &EINT_Trig_isr;\r
+ param.ether_callback = cb_func;\r
+ ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);\r
+ if (ETHER_SUCCESS != ret)\r
+ {\r
+ return -1;\r
+ }\r
+ return 0;\r
+} /* End of function callback_ether_regist() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_ether\r
+* Description : Sample of the callback function\r
+* Arguments : pparam -\r
+*\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+void callback_ether(void * pparam)\r
+{\r
+ ether_cb_arg_t * pdecode;\r
+ uint32_t channel;\r
+\r
+ pdecode = (ether_cb_arg_t *)pparam;\r
+ channel = pdecode->channel; /* Get Ethernet channel number */\r
+\r
+ switch (pdecode->event_id)\r
+ {\r
+ /* Callback function that notifies user to have detected magic packet. */\r
+ case ETHER_CB_EVENT_ID_WAKEON_LAN:\r
+ callback_wakeon_lan(channel);\r
+ break;\r
+\r
+ /* Callback function that notifies user to have become Link up. */\r
+ case ETHER_CB_EVENT_ID_LINK_ON:\r
+ callback_link_on(channel);\r
+ break;\r
+\r
+ /* Callback function that notifies user to have become Link down. */\r
+ case ETHER_CB_EVENT_ID_LINK_OFF:\r
+ callback_link_off(channel);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+} /* End of function callback_ether() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_wakeon_lan\r
+* Description :\r
+* Arguments : channel -\r
+* Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_wakeon_lan(uint32_t channel)\r
+{\r
+ if (ETHER_CHANNEL_MAX > channel)\r
+ {\r
+ magic_packet_detect[channel] = 1;\r
+\r
+ /* Please add necessary processing when magic packet is detected. */\r
+ }\r
+} /* End of function callback_wakeon_lan() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_link_on\r
+* Description :\r
+* Arguments : channel -\r
+* Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_link_on(uint32_t channel)\r
+{\r
+ if (ETHER_CHANNEL_MAX > channel)\r
+ {\r
+ link_detect[channel] = ETHER_FLAG_ON_LINK_ON;\r
+\r
+ /* Please add necessary processing when becoming Link up. */\r
+ prvLinkStatusChange( 1 );\r
+ }\r
+} /* End of function callback_link_on() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_link_off\r
+* Description :\r
+* Arguments : channel -\r
+* Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_link_off(uint32_t channel)\r
+{\r
+ if (ETHER_CHANNEL_MAX > channel)\r
+ {\r
+ link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;\r
+\r
+ /* Please add necessary processing when becoming Link down. */\r
+ prvLinkStatusChange( 0 );\r
+ }\r
+} /* End of function ether_cb_link_off() */\r
+\r
+/* End of File */\r
-/*
-FreeRTOS+TCP V2.0.11
-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>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "NetworkBufferManagement.h"
-
-/* Hardware includes. */
-#include "hwEthernet.h"
-
-/* Demo includes. */
-#include "NetworkInterface.h"
-
-#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* When a packet is ready to be sent, if it cannot be sent immediately then the
-task performing the transmit will block for niTX_BUFFER_FREE_WAIT
-milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
-up. */
-#define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )
-#define niMAX_TX_ATTEMPTS ( 5 )
-
-/* The length of the queue used to send interrupt status words from the
-interrupt handler to the deferred handler task. */
-#define niINTERRUPT_QUEUE_LENGTH ( 10 )
-
-/*-----------------------------------------------------------*/
-
-/*
- * A deferred interrupt handler task that processes
- */
-extern void vEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* The queue used to communicate Ethernet events with the IP task. */
-extern QueueHandle_t xNetworkEventQueue;
-
-/* The semaphore used to wake the deferred interrupt handler task when an Rx
-interrupt is received. */
-SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xStatus, xReturn;
-extern uint8_t ucMACAddress[ 6 ];
-
- /* Initialise the MAC. */
- vInitEmac();
-
- while( lEMACWaitForLink() != pdPASS )
- {
- vTaskDelay( 20 );
- }
-
- vSemaphoreCreateBinary( xEMACRxEventSemaphore );
- configASSERT( xEMACRxEventSemaphore );
-
- /* The handler task is created at the highest possible priority to
- ensure the interrupt handler can return directly to it. */
- xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
- xReturn = pdPASS;
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
-extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
-
- vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
-
- /* Finished with the network buffer. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
- return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Hardware includes. */\r
+#include "hwEthernet.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )\r
+#define niMAX_TX_ATTEMPTS ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+extern void vEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+ /* Initialise the MAC. */\r
+ vInitEmac();\r
+\r
+ while( lEMACWaitForLink() != pdPASS )\r
+ {\r
+ vTaskDelay( 20 );\r
+ }\r
+\r
+ vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+ configASSERT( xEMACRxEventSemaphore );\r
+\r
+ /* The handler task is created at the highest possible priority to\r
+ ensure the interrupt handler can return directly to it. */\r
+ xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+ xReturn = pdPASS;\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );\r
+\r
+ vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );\r
+\r
+ /* Finished with the network buffer. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+ return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
-#define xBUFFER_CACHE_SIZE 10
-#define xMAX_FAULT_INJECTION_RATE 15
-#define xMIN_FAULT_INJECTION_RATE 3
-#define xNUM_FAULT_TYPES 1
-
-static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
-
-#define xFAULT_LOG_SIZE 2048
-uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
-uint32_t ulFaultLogIndex = 0;
-
-static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
-{
-BaseType_t x, xReturn = pdFALSE;
-
- for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
- {
- if( xNetworkBufferCache[ x ] == NULL )
- {
- xNetworkBufferCache[ x ] = pxNetworkBufferIn;
- xReturn = pdTRUE;
- break;
- }
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
-{
-BaseType_t x;
-NetworkBufferDescriptor_t *pxReturn = NULL;
-
- for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
- {
- if( xNetworkBufferCache[ x ] != NULL )
- {
- pxReturn = xNetworkBufferCache[ x ];
- xNetworkBufferCache[ x ] = NULL;
- break;
- }
- }
-
- return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
-{
-NetworkBufferDescriptor_t *pxReturn;
-
- /* Obtain a new descriptor. */
- pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
-
- if( pxReturn != NULL )
- {
- /* Copy in the packet data. */
- pxReturn->xDataLength = pxOriginalPacket->xDataLength;
- memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
- }
-
- return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
-{
-static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
-NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-uint32_t ulFault;
-
-return pxNetworkBufferIn;
-
- ulCallCount++;
-
- if( ulCallCount > ulNextFaultCallCount )
- {
- xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );
- ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;
- if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
- {
- ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
- }
-
- ulCallCount = 0;
-
- xApplicationGetRandomNumber( &( ulFault ) );
- ulFault = ulFault % xNUM_FAULT_TYPES;
-
- if( ulFaultLogIndex < xFAULT_LOG_SIZE )
- {
- ulInjectedFault[ ulFaultLogIndex ] = ulFault;
- ulFaultLogIndex++;
- }
-
- switch( ulFault )
- {
- case 0:
- /* Just drop the packet. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
- pxReturn = NULL;
- break;
-
- case 1:
- /* Store the packet in the cache for later. */
- if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
- {
- /* The packet may get sent later, it is not being sent
- now. */
- pxReturn = NULL;
- }
- break;
-
- case 2:
- /* Send a cached packet. */
- pxReturn = prvGetCachedPacket();
- if( pxReturn != NULL )
- {
- /* A cached packet was obtained so drop the original
- packet. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
- }
- else
- {
- /* Could not obtain a packet from the cache so just return
- the packet that was passed in. */
- pxReturn = pxNetworkBufferIn;
- }
- break;
-
- case 4:
-
- /* Send a duplicate of the packet right away. */
- pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
-
- /* Send the original packet to the stack. */
- xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
- if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
- }
- break;
-
- case 5:
-
- /* Send both a cached packet and the current packet. */
- xRxEvent.pvData = ( void * ) prvGetCachedPacket();
- if( xRxEvent.pvData != NULL )
- {
- if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
- }
- }
- break;
-
- case 6:
- case 7:
- case 8:
- /* Store the packet in the cache for later. */
- if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
- {
- /* The packet may get sent later, it is not being sent
- now. */
- pxReturn = NULL;
- }
- break;
- }
- }
-
- return pxReturn;
-}
-/*-----------------------------------------------------------*/
+#define xBUFFER_CACHE_SIZE 10\r
+#define xMAX_FAULT_INJECTION_RATE 15\r
+#define xMIN_FAULT_INJECTION_RATE 3\r
+#define xNUM_FAULT_TYPES 1\r
+\r
+static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };\r
+\r
+#define xFAULT_LOG_SIZE 2048\r
+uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];\r
+uint32_t ulFaultLogIndex = 0;\r
+\r
+static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )\r
+{\r
+BaseType_t x, xReturn = pdFALSE;\r
+\r
+ for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )\r
+ {\r
+ if( xNetworkBufferCache[ x ] == NULL )\r
+ {\r
+ xNetworkBufferCache[ x ] = pxNetworkBufferIn;\r
+ xReturn = pdTRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvGetCachedPacket( void )\r
+{\r
+BaseType_t x;\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+\r
+ for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )\r
+ {\r
+ if( xNetworkBufferCache[ x ] != NULL )\r
+ {\r
+ pxReturn = xNetworkBufferCache[ x ];\r
+ xNetworkBufferCache[ x ] = NULL;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn;\r
+\r
+ /* Obtain a new descriptor. */\r
+ pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );\r
+\r
+ if( pxReturn != NULL )\r
+ {\r
+ /* Copy in the packet data. */\r
+ pxReturn->xDataLength = pxOriginalPacket->xDataLength;\r
+ memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );\r
+ }\r
+\r
+ return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )\r
+{\r
+static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;\r
+NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulFault;\r
+\r
+return pxNetworkBufferIn;\r
+\r
+ ulCallCount++;\r
+\r
+ if( ulCallCount > ulNextFaultCallCount )\r
+ {\r
+ xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );\r
+ ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;\r
+ if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )\r
+ {\r
+ ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;\r
+ }\r
+\r
+ ulCallCount = 0;\r
+\r
+ xApplicationGetRandomNumber( &( ulFault ) );\r
+ ulFault = ulFault % xNUM_FAULT_TYPES;\r
+\r
+ if( ulFaultLogIndex < xFAULT_LOG_SIZE )\r
+ {\r
+ ulInjectedFault[ ulFaultLogIndex ] = ulFault;\r
+ ulFaultLogIndex++;\r
+ }\r
+\r
+ switch( ulFault )\r
+ {\r
+ case 0:\r
+ /* Just drop the packet. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+ pxReturn = NULL;\r
+ break;\r
+\r
+ case 1:\r
+ /* Store the packet in the cache for later. */\r
+ if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+ {\r
+ /* The packet may get sent later, it is not being sent\r
+ now. */\r
+ pxReturn = NULL;\r
+ }\r
+ break;\r
+\r
+ case 2:\r
+ /* Send a cached packet. */\r
+ pxReturn = prvGetCachedPacket();\r
+ if( pxReturn != NULL )\r
+ {\r
+ /* A cached packet was obtained so drop the original\r
+ packet. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+ }\r
+ else\r
+ {\r
+ /* Could not obtain a packet from the cache so just return\r
+ the packet that was passed in. */\r
+ pxReturn = pxNetworkBufferIn;\r
+ }\r
+ break;\r
+\r
+ case 4:\r
+\r
+ /* Send a duplicate of the packet right away. */\r
+ pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );\r
+\r
+ /* Send the original packet to the stack. */\r
+ xRxEvent.pvData = ( void * ) pxNetworkBufferIn;\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+ }\r
+ break;\r
+\r
+ case 5:\r
+\r
+ /* Send both a cached packet and the current packet. */\r
+ xRxEvent.pvData = ( void * ) prvGetCachedPacket();\r
+ if( xRxEvent.pvData != NULL )\r
+ {\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+ }\r
+ }\r
+ break;\r
+\r
+ case 6:\r
+ case 7:\r
+ case 8:\r
+ /* Store the packet in the cache for later. */\r
+ if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+ {\r
+ /* The packet may get sent later, it is not being sent\r
+ now. */\r
+ pxReturn = NULL;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
-/*
-FreeRTOS+TCP V2.0.11
-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
-*/
-
-/* WinPCap includes. */
-#define HAVE_REMOTE
-#include "pcap.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-/* Thread-safe circular buffers are being used to pass data to and from the PCAP
-access functions. */
-#include "Win32-Extensions.h"
-#include "FreeRTOS_Stream_Buffer.h"
-
-/* Sizes of the thread safe circular buffers used to pass data to and from the
-WinPCAP Windows threads. */
-#define xSEND_BUFFER_SIZE 32768
-#define xRECV_BUFFER_SIZE 32768
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
- #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* Used to insert test code only. */
-#define niDISRUPT_PACKETS 0
-
-/*-----------------------------------------------------------*/
-
-/*
- * Windows threads that are outside of the control of the FreeRTOS simulator are
- * used to interface with the WinPCAP libraries.
- */
-DWORD WINAPI prvWinPcapRecvThread( void *pvParam );
-DWORD WINAPI prvWinPcapSendThread( void *pvParam );
-
-/*
- * Print out a numbered list of network interfaces that are available on the
- * host computer.
- */
-static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
-
-/*
- * Open the network interface. The number of the interface to be opened is set
- * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
- */
-static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
-static int prvOpenInterface( const char *pucName );
-
-/*
- * Configure the capture filter to allow blocking reads, and to filter out
- * packets that are not of interest to this demo.
- */
-static void prvConfigureCaptureBehaviour( void );
-
-/*
- * A function that simulates Ethernet interrupts by periodically polling the
- * WinPCap interface for new data.
- */
-static void prvInterruptSimulatorTask( void *pvParameters );
-
-/*
- * Create the buffers that are used to pass data between the FreeRTOS simulator
- * and the Win32 threads that manage WinPCAP.
- */
-static void prvCreateThreadSafeBuffers( void );
-
-/*
- * Utility function used to format print messages only.
- */
-static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );
-
-/*-----------------------------------------------------------*/
-
-/* Required by the WinPCap library. */
-static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];
-
-/* An event used to wake up the Win32 thread that sends data through the WinPCAP
-library. */
-static void *pvSendEvent = NULL;
-
-/* _HT_ made the PCAP interface number configurable through the program's
-parameters in order to test in different machines. */
-static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;
-
-/* Handles to the Windows threads that handle the PCAP IO. */
-static HANDLE vWinPcapRecvThreadHandle = NULL;
-static HANDLE vWinPcapSendThreadHandle = NULL;;
-
-/* The interface being used by WinPCap. */
-static pcap_t *pxOpenedInterfaceHandle = NULL;
-
-/* Circular buffers used by the PCAP Win32 threads. */
-static StreamBuffer_t *xSendBuffer = NULL;
-static StreamBuffer_t *xRecvBuffer = NULL;
-
-/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */
-extern uint8_t ucMACAddress[ 6 ];
-
-/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */
-static volatile uint32_t ulWinPCAPSendFailures = 0;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xReturn = pdFALSE;
-pcap_if_t *pxAllNetworkInterfaces;
-
- /* Query the computer the simulation is being executed on to find the
- network interfaces it has installed. */
- pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
-
- /* 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. */
- if( pxAllNetworkInterfaces != NULL )
- {
- prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
- }
-
- if( pxOpenedInterfaceHandle != NULL )
- {
- xReturn = pdPASS;
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvCreateThreadSafeBuffers( void )
-{
- /* The buffer used to pass data to be transmitted from a FreeRTOS task to
- the Win32 thread that sends via the WinPCAP library. */
- if( xSendBuffer == NULL)
- {
- xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );
- 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 Win32 thread that receives
- via the WinPCAP library to the FreeRTOS task. */
- if( xRecvBuffer == NULL)
- {
- xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );
- configASSERT( xRecvBuffer );
- memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );
- xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
- }
-}
-/*-----------------------------------------------------------*/
-
-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 Win32 thread that sends data via the WinPCAP 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_debug_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. */
- SetEvent( pvSendEvent );
-
- /* The buffer has been sent so can be released. */
- if( bReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- }
-
- return pdPASS;
-}
-/*-----------------------------------------------------------*/
-
-static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
-{
-pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
-int32_t lInterfaceNumber = 1;
-char cBuffer[ 512 ];
-static BaseType_t xInvalidInterfaceDetected = pdFALSE;
-
- if( xInvalidInterfaceDetected == pdFALSE )
- {
- if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
- {
- printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer );
- pxAllNetworkInterfaces = NULL;
- }
- else
- {
- printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );
- }
-
- 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 %d, 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 %d.\n", xConfigNetworkInterfaceToUse );
- }
- }
-
- return pxAllNetworkInterfaces;
-}
-/*-----------------------------------------------------------*/
-
-static int prvOpenInterface( const char *pucName )
-{
-static char pucInterfaceName[ 256 ];
-
- if( pucName != NULL )
- {
- strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );
- }
-
- pxOpenedInterfaceHandle = pcap_open( pucInterfaceName, /* The name of the selected interface. */
- ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */
- PCAP_OPENFLAG_PROMISCUOUS, /* 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 Windows TCP/IP stack. */
- 100,
- NULL, /* No authentication is required as this is
- not a remote capture session. */
- cErrorBuffer
- );
-
- if ( pxOpenedInterfaceHandle == NULL )
- {
- printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );
- return 1;
- }
- else
- {
- /* Configure the capture filter to allow blocking reads, and to filter
- out packets that are not of interest to this demo. */
- prvConfigureCaptureBehaviour();
- }
- return 0;
-}
-/*-----------------------------------------------------------*/
-
-static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
-{
-pcap_if_t *pxInterface;
-int32_t x;
-
- /* 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 ) == 0 )
- {
- printf( "Successfully opened interface number %d.\n", x + 1 );
- }
- else
- {
- printf( "Failed to open interface number %d.\n", x + 1 );
- }
-
- /* The device list is no longer required. */
- pcap_freealldevs( pxAllNetworkInterfaces );
-}
-/*-----------------------------------------------------------*/
-
-static void prvConfigureCaptureBehaviour( void )
-{
-struct bpf_program xFilterCode;
-uint32_t ulNetMask;
-
- /* Set up a filter so only the packets of interest are passed to the IP
- stack. cErrorBuffer is used for convenience to create the string. Don't
- confuse this with an error message. */
- sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",
- ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );
-
- ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
-
- if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
- {
- printf( "\nThe packet filter string is invalid\n" );
- }
- else
- {
- if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
- {
- printf( "\nAn error occurred setting the packet filter.\n" );
- }
- /* 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 );
- }
-
- /* Create the buffers used to pass packets between the FreeRTOS simulator
- and the Win32 threads that are handling WinPCAP. */
- prvCreateThreadSafeBuffers();
-
- if( pvSendEvent == NULL )
- {
- /* Create event used to signal the Win32 WinPCAP Tx thread. */
- pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );
-
- /* Create the Win32 thread that handles WinPCAP Rx. */
- vWinPcapRecvThreadHandle = CreateThread(
- NULL, /* Pointer to thread security attributes. */
- 0, /* Initial thread stack size, in bytes. */
- prvWinPcapRecvThread, /* Pointer to thread function. */
- NULL, /* Argument for new thread. */
- 0, /* Creation flags. */
- NULL );
-
- /* Use the cores that are not used by the FreeRTOS tasks. */
- SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );
-
- /* Create the Win32 thread that handlers WinPCAP Tx. */
- vWinPcapSendThreadHandle = CreateThread(
- NULL, /* Pointer to thread security attributes. */
- 0, /* initial thread stack size, in bytes. */
- prvWinPcapSendThread, /* Pointer to thread function. */
- NULL, /* Argument for new thread. */
- 0, /* Creation flags. */
- NULL );
-
- /* Use the cores that are not used by the FreeRTOS tasks. */
- SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );
-
- /* 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. */
- xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );
- }
-}
-/*-----------------------------------------------------------*/
-
-/* WinPCAP function. */
-void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )
-{
- (void)user;
-
- /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS
- OR TO PRINT OUT MESSAGES HERE. */
-
- /* 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 );
- }
-}
-/*-----------------------------------------------------------*/
-
-DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )
-{
- ( void ) pvParam;
-
- /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
- OUT MESSAGES HERE. */
-
- for( ;; )
- {
- pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );
- }
-}
-/*-----------------------------------------------------------*/
-
-DWORD WINAPI prvWinPcapSendThread( void *pvParam )
-{
-size_t xLength;
-uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
-static char cErrorMessage[ 1024 ];
-const DWORD xMaxMSToWait = 1000;
-
- /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
- OUT MESSAGES HERE. */
-
- /* Remove compiler warnings about unused parameters. */
- ( void ) pvParam;
-
- for( ;; )
- {
- /* Wait until notified of something to send. */
- WaitForSingleObject( pvSendEvent, xMaxMSToWait );
-
- /* Is there more than the length value stored in the circular buffer
- used to pass data from the FreeRTOS simulator into this Win32 thread? */
- while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )
- {
- uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
- uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
- if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
- {
- ulWinPCAPSendFailures++;
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
-
-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 Win32 thread that
- handles WinPCAP 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 );
- }
- }
-}
-/*-----------------------------------------------------------*/
-
-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;
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* WinPCap includes. */\r
+#define HAVE_REMOTE\r
+#include "pcap.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Thread-safe circular buffers are being used to pass data to and from the PCAP\r
+access functions. */\r
+#include "Win32-Extensions.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* Sizes of the thread safe circular buffers used to pass data to and from the\r
+WinPCAP Windows threads. */\r
+#define xSEND_BUFFER_SIZE 32768\r
+#define xRECV_BUFFER_SIZE 32768\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* Used to insert test code only. */\r
+#define niDISRUPT_PACKETS 0\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Windows threads that are outside of the control of the FreeRTOS simulator are\r
+ * used to interface with the WinPCAP libraries.\r
+ */\r
+DWORD WINAPI prvWinPcapRecvThread( void *pvParam );\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam );\r
+\r
+/*\r
+ * Print out a numbered list of network interfaces that are available on the\r
+ * host computer.\r
+ */\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
+\r
+/*\r
+ * Open the network interface. The number of the interface to be opened is set\r
+ * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ */\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
+static int prvOpenInterface( const char *pucName );\r
+\r
+/*\r
+ * Configure the capture filter to allow blocking reads, and to filter out\r
+ * packets that are not of interest to this demo.\r
+ */\r
+static void prvConfigureCaptureBehaviour( void );\r
+\r
+/*\r
+ * A function that simulates Ethernet interrupts by periodically polling the\r
+ * WinPCap interface for new data.\r
+ */\r
+static void prvInterruptSimulatorTask( void *pvParameters );\r
+\r
+/*\r
+ * Create the buffers that are used to pass data between the FreeRTOS simulator\r
+ * and the Win32 threads that manage WinPCAP.\r
+ */\r
+static void prvCreateThreadSafeBuffers( void );\r
+\r
+/*\r
+ * Utility function used to format print messages only.\r
+ */\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Required by the WinPCap library. */\r
+static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];\r
+\r
+/* An event used to wake up the Win32 thread that sends data through the WinPCAP\r
+library. */\r
+static void *pvSendEvent = NULL;\r
+\r
+/* _HT_ made the PCAP interface number configurable through the program's\r
+parameters in order to test in different machines. */\r
+static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;\r
+\r
+/* Handles to the Windows threads that handle the PCAP IO. */\r
+static HANDLE vWinPcapRecvThreadHandle = NULL;\r
+static HANDLE vWinPcapSendThreadHandle = NULL;;\r
+\r
+/* The interface being used by WinPCap. */\r
+static pcap_t *pxOpenedInterfaceHandle = NULL;\r
+\r
+/* Circular buffers used by the PCAP Win32 threads. */\r
+static StreamBuffer_t *xSendBuffer = NULL;\r
+static StreamBuffer_t *xRecvBuffer = NULL;\r
+\r
+/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */\r
+static volatile uint32_t ulWinPCAPSendFailures = 0;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdFALSE;\r
+pcap_if_t *pxAllNetworkInterfaces;\r
+\r
+ /* Query the computer the simulation is being executed on to find the\r
+ network interfaces it has installed. */\r
+ pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
+\r
+ /* Open the network interface. The number of the interface to be opened is\r
+ set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ Calling this function will set the pxOpenedInterfaceHandle variable. If,\r
+ after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
+ the interface could not be opened. */\r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
+ }\r
+\r
+ if( pxOpenedInterfaceHandle != NULL )\r
+ {\r
+ xReturn = pdPASS;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateThreadSafeBuffers( void )\r
+{\r
+ /* The buffer used to pass data to be transmitted from a FreeRTOS task to\r
+ the Win32 thread that sends via the WinPCAP library. */\r
+ if( xSendBuffer == NULL)\r
+ {\r
+ xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );\r
+ configASSERT( xSendBuffer );\r
+ memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );\r
+ xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;\r
+ }\r
+\r
+ /* The buffer used to pass received data from the Win32 thread that receives\r
+ via the WinPCAP library to the FreeRTOS task. */\r
+ if( xRecvBuffer == NULL)\r
+ {\r
+ xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );\r
+ configASSERT( xRecvBuffer );\r
+ memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );\r
+ xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+size_t xSpace;\r
+\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+ configASSERT( xIsCallingFromIPTask() == pdTRUE );\r
+\r
+ /* Both the length of the data being sent and the actual data being sent\r
+ are placed in the thread safe buffer used to pass data between the FreeRTOS\r
+ tasks and the Win32 thread that sends data via the WinPCAP library. Drop\r
+ the packet if there is insufficient space in the buffer to hold both. */\r
+ xSpace = uxStreamBufferGetSpace( xSendBuffer );\r
+\r
+ if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+ ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )\r
+ {\r
+ /* First write in the length of the data, then write in the data\r
+ itself. */\r
+ uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );\r
+ uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
+ }\r
+ else\r
+ {\r
+ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );\r
+ }\r
+\r
+ /* Kick the Tx task in either case in case it doesn't know the buffer is\r
+ full. */\r
+ SetEvent( pvSendEvent );\r
+\r
+ /* The buffer has been sent so can be released. */\r
+ if( bReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ }\r
+\r
+ return pdPASS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
+{\r
+pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
+int32_t lInterfaceNumber = 1;\r
+char cBuffer[ 512 ];\r
+static BaseType_t xInvalidInterfaceDetected = pdFALSE;\r
+\r
+ if( xInvalidInterfaceDetected == pdFALSE )\r
+ {\r
+ if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
+ {\r
+ printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+ else\r
+ {\r
+ printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );\r
+ }\r
+\r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ /* Print out the list of network interfaces. The first in the list\r
+ is interface '1', not interface '0'. */\r
+ for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
+ {\r
+ /* The descriptions of the devices can be full of spaces, clean them\r
+ a little. printf() can only be used here because the network is not\r
+ up yet - so no other network tasks will be running. */\r
+ printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );\r
+ printf( " (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );\r
+ printf( "\n" );\r
+ lInterfaceNumber++;\r
+ }\r
+ }\r
+\r
+ if( lInterfaceNumber == 1 )\r
+ {\r
+ /* The interface number was never incremented, so the above for() loop\r
+ did not execute meaning no interfaces were found. */\r
+ printf( " \nNo network interfaces were found.\n" );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+\r
+ printf( "\r\nThe interface that will be opened is set by " );\r
+ printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );\r
+\r
+ if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) )\r
+ {\r
+ printf( "\r\nERROR: configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse );\r
+ printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );\r
+ printf( "then re-compile and re-start the application. Only Ethernet (as opposed to WiFi)\r\n" );\r
+ printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );\r
+ xInvalidInterfaceDetected = pdTRUE;\r
+\r
+ if( pxAllNetworkInterfaces != NULL )\r
+ {\r
+ /* Free the device list, as no devices are going to be opened. */\r
+ pcap_freealldevs( pxAllNetworkInterfaces );\r
+ pxAllNetworkInterfaces = NULL;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ printf( "Attempting to open interface number %d.\n", xConfigNetworkInterfaceToUse );\r
+ }\r
+ }\r
+\r
+ return pxAllNetworkInterfaces;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static int prvOpenInterface( const char *pucName )\r
+{\r
+static char pucInterfaceName[ 256 ];\r
+\r
+ if( pucName != NULL )\r
+ {\r
+ strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );\r
+ }\r
+\r
+ pxOpenedInterfaceHandle = pcap_open( pucInterfaceName, /* The name of the selected interface. */\r
+ ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */\r
+ PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscuous mode as the MAC and\r
+ IP address is going to be "simulated", and\r
+ not be the real MAC and IP address. This allows\r
+ traffic to the simulated IP address to be routed\r
+ to uIP, and traffic to the real IP address to be\r
+ routed to the Windows TCP/IP stack. */\r
+ 100,\r
+ NULL, /* No authentication is required as this is\r
+ not a remote capture session. */\r
+ cErrorBuffer\r
+ );\r
+\r
+ if ( pxOpenedInterfaceHandle == NULL )\r
+ {\r
+ printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );\r
+ return 1;\r
+ }\r
+ else\r
+ {\r
+ /* Configure the capture filter to allow blocking reads, and to filter\r
+ out packets that are not of interest to this demo. */\r
+ prvConfigureCaptureBehaviour();\r
+ }\r
+ return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
+{\r
+pcap_if_t *pxInterface;\r
+int32_t x;\r
+\r
+ /* Walk the list of devices until the selected device is located. */\r
+ pxInterface = pxAllNetworkInterfaces;\r
+ for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )\r
+ {\r
+ pxInterface = pxInterface->next;\r
+ }\r
+\r
+ /* Open the selected interface. */\r
+ if( prvOpenInterface( pxInterface->name ) == 0 )\r
+ {\r
+ printf( "Successfully opened interface number %d.\n", x + 1 );\r
+ }\r
+ else\r
+ {\r
+ printf( "Failed to open interface number %d.\n", x + 1 );\r
+ }\r
+\r
+ /* The device list is no longer required. */\r
+ pcap_freealldevs( pxAllNetworkInterfaces );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvConfigureCaptureBehaviour( void )\r
+{\r
+struct bpf_program xFilterCode;\r
+uint32_t ulNetMask;\r
+\r
+ /* Set up a filter so only the packets of interest are passed to the IP\r
+ stack. cErrorBuffer is used for convenience to create the string. Don't\r
+ confuse this with an error message. */\r
+ sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",\r
+ ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );\r
+\r
+ ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
+\r
+ if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
+ {\r
+ printf( "\nThe packet filter string is invalid\n" );\r
+ }\r
+ else\r
+ {\r
+ if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
+ {\r
+ printf( "\nAn error occurred setting the packet filter.\n" );\r
+ }\r
+ /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct \r
+ parameter.pcap_freecode() will free that memory. */\r
+ pcap_freecode( &xFilterCode );\r
+ }\r
+\r
+ /* Create the buffers used to pass packets between the FreeRTOS simulator\r
+ and the Win32 threads that are handling WinPCAP. */\r
+ prvCreateThreadSafeBuffers();\r
+\r
+ if( pvSendEvent == NULL )\r
+ {\r
+ /* Create event used to signal the Win32 WinPCAP Tx thread. */\r
+ pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );\r
+\r
+ /* Create the Win32 thread that handles WinPCAP Rx. */\r
+ vWinPcapRecvThreadHandle = CreateThread(\r
+ NULL, /* Pointer to thread security attributes. */\r
+ 0, /* Initial thread stack size, in bytes. */\r
+ prvWinPcapRecvThread, /* Pointer to thread function. */\r
+ NULL, /* Argument for new thread. */\r
+ 0, /* Creation flags. */\r
+ NULL );\r
+\r
+ /* Use the cores that are not used by the FreeRTOS tasks. */\r
+ SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );\r
+\r
+ /* Create the Win32 thread that handlers WinPCAP Tx. */\r
+ vWinPcapSendThreadHandle = CreateThread(\r
+ NULL, /* Pointer to thread security attributes. */\r
+ 0, /* initial thread stack size, in bytes. */\r
+ prvWinPcapSendThread, /* Pointer to thread function. */\r
+ NULL, /* Argument for new thread. */\r
+ 0, /* Creation flags. */\r
+ NULL );\r
+\r
+ /* Use the cores that are not used by the FreeRTOS tasks. */\r
+ SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );\r
+\r
+ /* Create a task that simulates an interrupt in a real system. This will\r
+ block waiting for packets, then send a message to the IP task when data\r
+ is available. */\r
+ xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* WinPCAP function. */\r
+void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )\r
+{\r
+ (void)user;\r
+\r
+ /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS\r
+ OR TO PRINT OUT MESSAGES HERE. */\r
+\r
+ /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */\r
+ if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+ ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )\r
+ {\r
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );\r
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )\r
+{\r
+ ( void ) pvParam;\r
+\r
+ /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+ OUT MESSAGES HERE. */\r
+\r
+ for( ;; )\r
+ {\r
+ pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam )\r
+{\r
+size_t xLength;\r
+uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+static char cErrorMessage[ 1024 ];\r
+const DWORD xMaxMSToWait = 1000;\r
+\r
+ /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+ OUT MESSAGES HERE. */\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParam;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Wait until notified of something to send. */\r
+ WaitForSingleObject( pvSendEvent, xMaxMSToWait );\r
+\r
+ /* Is there more than the length value stored in the circular buffer\r
+ used to pass data from the FreeRTOS simulator into this Win32 thread? */\r
+ while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )\r
+ {\r
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );\r
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );\r
+ if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )\r
+ {\r
+ ulWinPCAPSendFailures++;\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInterruptSimulatorTask( void *pvParameters )\r
+{\r
+struct pcap_pkthdr xHeader;\r
+static struct pcap_pkthdr *pxHeader;\r
+const uint8_t *pucPacketData;\r
+uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+eFrameProcessingResult_t eResult;\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Does the circular buffer used to pass data from the Win32 thread that\r
+ handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */\r
+ if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )\r
+ {\r
+ /* Get the next packet. */\r
+ uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );\r
+ uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );\r
+ pucPacketData = ucRecvBuffer;\r
+ pxHeader = &xHeader;\r
+\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+\r
+ /* Check for minimal size. */\r
+ if( pxHeader->len >= sizeof( EthernetHeader_t ) )\r
+ {\r
+ eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );\r
+ }\r
+ else\r
+ {\r
+ eResult = eReleaseBuffer;\r
+ }\r
+\r
+ if( eResult == eProcessBuffer )\r
+ {\r
+ /* Will the data fit into the frame buffer? */\r
+ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )\r
+ {\r
+ /* Obtain a buffer into which the data can be placed. This\r
+ is only an interrupt simulator, not a real interrupt, so it\r
+ is ok to call the task level function here, but note that\r
+ some buffer implementations cannot be called from a real\r
+ interrupt. */\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );\r
+\r
+ if( pxNetworkBuffer != NULL )\r
+ {\r
+ memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );\r
+ pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;\r
+\r
+ #if( niDISRUPT_PACKETS == 1 )\r
+ {\r
+ pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );\r
+ }\r
+ #endif /* niDISRUPT_PACKETS */\r
+\r
+ if( pxNetworkBuffer != NULL )\r
+ {\r
+ xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+ /* Data was received and stored. Send a message to\r
+ the IP task to let it know. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+ {\r
+ /* The buffer could not be sent to the stack so\r
+ must be released again. This is only an\r
+ interrupt simulator, not a real interrupt, so it\r
+ is ok to use the task level function here, but\r
+ note no all buffer implementations will allow\r
+ this function to be executed from a real\r
+ interrupt. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* The packet was already released or stored inside\r
+ vRxFaultInjection(). Don't release it here. */\r
+ }\r
+ }\r
+ else\r
+ {\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Log that a packet was dropped because it would have\r
+ overflowed the buffer, but there may be more buffers to\r
+ process. */\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* There is no real way of simulating an interrupt. Make sure\r
+ other tasks can run. */\r
+ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )\r
+{\r
+ char *pcTarget = pcBuffer;\r
+\r
+ /* Utility function used to formap messages being printed only. */\r
+ while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )\r
+ {\r
+ *( pcTarget++ ) = *pcMessage;\r
+\r
+ if( isspace( *pcMessage ) != pdFALSE )\r
+ {\r
+ while( isspace( *pcMessage ) != pdFALSE )\r
+ {\r
+ pcMessage++;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ pcMessage++;\r
+ }\r
+ }\r
+\r
+ *pcTarget = '\0';\r
+\r
+ return pcBuffer;\r
+}\r
-/*
-FreeRTOS+TCP V2.0.11
-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 "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Xilinx library files. */
-#include <xemacps.h>
-#include "Zynq/x_topology.h"
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_emacpsif_hw.h"
-
-/* Provided memory configured as uncached. */
-#include "uncached_memory.h"
-
-#ifndef BMSR_LINK_STATUS
- #define BMSR_LINK_STATUS 0x0004UL
-#endif
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
- receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 15000
-#endif
-
-#ifndef PHY_LS_LOW_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still low every second. */
- #define PHY_LS_LOW_CHECK_TIME_MS 1000
-#endif
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-#define niBUFFER_1_PACKET_SIZE 1536
-
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
-
-#ifndef iptraceEMAC_TASK_STARTING
- #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
- #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Look for the link to be up every few milliseconds until either xMaxTime time
- * has passed or a link is found.
- */
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler for all MAC/DMA interrupt sources.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* EMAC data/descriptions. */
-static xemacpsif_s xEMACpsif;
-struct xtopology_t xXTopology =
-{
- .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
- .emac_type = xemac_type_emacps,
- .intc_baseaddr = 0x0,
- .intc_emac_intr = 0x0,
- .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
- .scugic_emac_intr = 0x36,
-};
-
-XEmacPs_Config mac_config =
-{
- .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
- .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
-};
-
-extern int phy_detected;
-
-/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
-static uint32_t ulPHYLinkStatus = 0;
-
-#if( ipconfigUSE_LLMNR == 1 )
- static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
-#endif
-
-/* ucMACAddress as it appears in main.c */
-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;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-uint32_t ulLinkSpeed, ulDMAReg;
-BaseType_t xStatus, xLinkStatus;
-XEmacPs *pxEMAC_PS;
-const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
-
- /* Guard against the init function being called more than once. */
- if( xEMACTaskHandle == NULL )
- {
- pxEMAC_PS = &( xEMACpsif.emacps );
- memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
-
- xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
- if( xStatus != XST_SUCCESS )
- {
- FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
- }
-
- /* Initialize the mac and set the MAC address. */
- XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
-
- #if( ipconfigUSE_LLMNR == 1 )
- {
- /* Also add LLMNR multicast MAC address. */
- XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
- }
- #endif /* ipconfigUSE_LLMNR == 1 */
-
- XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
- ulLinkSpeed = Phy_Setup( pxEMAC_PS );
- XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
-
- /* Setting the operating speed of the MAC needs a delay. */
- vTaskDelay( pdMS_TO_TICKS( 25UL ) );
-
- ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
-
- /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
- packets from the receiver packet buffer memory when no AHB resource is available. */
- XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
- ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
-
- setup_isr( &xEMACpsif );
- init_dma( &xEMACpsif );
- start_emacps( &xEMACpsif );
-
- prvGMACWaitLS( xWaitLinkDelay );
-
- /* The deferred interrupt handler task is created at the highest
- possible priority to ensure the interrupt handler can return directly
- to it. The task's handle is stored in xEMACTaskHandle so interrupts can
- notify the task when there is something to process. */
- xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- }
- else
- {
- /* Initialisation was already performed, just wait for the link. */
- prvGMACWaitLS( xWaitRelinkDelay );
- }
-
- /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
- DHCP process and all other communication will fail. */
- xLinkStatus = xGetPhyLinkStatus();
-
- return ( xLinkStatus != pdFALSE );
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
-{
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- iptraceNETWORK_INTERFACE_TRANSMIT();
- emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
- }
- else if( bReleaseAfterSend != pdFALSE )
- {
- /* No link. */
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- }
-
- return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned ulRegister )
-{
-uint16_t usValue;
-
- XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
- return usValue;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime, xEndTime;
-const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
-BaseType_t xReturn;
-
- xStartTime = xTaskGetTickCount();
-
- for( ;; )
- {
- xEndTime = xTaskGetTickCount();
-
- if( xEndTime - xStartTime > xMaxTime )
- {
- xReturn = pdFALSE;
- break;
- }
- ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xReturn = pdTRUE;
- break;
- }
-
- vTaskDelay( xShortDelay );
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-uint8_t *ucRAMBuffer = ucNetworkPackets;
-uint32_t ul;
-
- for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
- {
- pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
- *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
- ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
- }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xReturn;
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
- {
- xReturn = pdFALSE;
- }
- else
- {
- xReturn = pdTRUE;
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
-
- /* Remove compiler warnings about unused parameters. */
- ( void ) pvParameters;
-
- /* A possibility to set some additional task properties like calling
- portTASK_USES_FLOATING_POINT() */
- iptraceEMAC_TASK_STARTING();
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
- for( ;; )
- {
- uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
- if( uxLastMinBufferCount != uxCurrentCount )
- {
- /* The logging produced below may be helpful
- while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
- }
-
- #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- {
- static UBaseType_t uxLastMinQueueSpace = 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 */
-
- if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
- {
- /* No events to process now, wait for the next. */
- ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
- xResult = emacps_check_rx( &xEMACpsif );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
- emacps_check_tx( &xEMACpsif );
- }
-
- if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
- {
- xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
- emacps_check_errors( &xEMACpsif );
- }
-
- if( xResult > 0 )
- {
- /* A packet was received. No need to check for the PHY status now,
- but set a timer to check it later on. */
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- xResult = 0;
- }
- else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
- {
- xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
- {
- ulPHYLinkStatus = xStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Xilinx library files. */\r
+#include <xemacps.h>\r
+#include "Zynq/x_topology.h"\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_emacpsif_hw.h"\r
+\r
+/* Provided memory configured as uncached. */\r
+#include "uncached_memory.h"\r
+\r
+#ifndef BMSR_LINK_STATUS\r
+ #define BMSR_LINK_STATUS 0x0004UL\r
+#endif\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+ receiving packets. */\r
+ #define PHY_LS_HIGH_CHECK_TIME_MS 15000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still low every second. */\r
+ #define PHY_LS_LOW_CHECK_TIME_MS 1000\r
+#endif\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+#define niBUFFER_1_PACKET_SIZE 1536\r
+\r
+/* Naming and numbering of PHY registers. */\r
+#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+ #define iptraceEMAC_TASK_STARTING() do { } while( 0 )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+ #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Look for the link to be up every few milliseconds until either xMaxTime time\r
+ * has passed or a link is found.\r
+ */\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler for all MAC/DMA interrupt sources.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* EMAC data/descriptions. */\r
+static xemacpsif_s xEMACpsif;\r
+struct xtopology_t xXTopology =\r
+{\r
+ .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,\r
+ .emac_type = xemac_type_emacps,\r
+ .intc_baseaddr = 0x0,\r
+ .intc_emac_intr = 0x0,\r
+ .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,\r
+ .scugic_emac_intr = 0x36,\r
+};\r
+\r
+XEmacPs_Config mac_config =\r
+{\r
+ .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */\r
+ .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */\r
+};\r
+\r
+extern int phy_detected;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+ static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor. The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+uint32_t ulLinkSpeed, ulDMAReg;\r
+BaseType_t xStatus, xLinkStatus;\r
+XEmacPs *pxEMAC_PS;\r
+const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );\r
+\r
+ /* Guard against the init function being called more than once. */\r
+ if( xEMACTaskHandle == NULL )\r
+ {\r
+ pxEMAC_PS = &( xEMACpsif.emacps );\r
+ memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );\r
+\r
+ xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);\r
+ if( xStatus != XST_SUCCESS )\r
+ {\r
+ FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );\r
+ }\r
+\r
+ /* Initialize the mac and set the MAC address. */\r
+ XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );\r
+\r
+ #if( ipconfigUSE_LLMNR == 1 )\r
+ {\r
+ /* Also add LLMNR multicast MAC address. */\r
+ XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );\r
+ }\r
+ #endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+ XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );\r
+ ulLinkSpeed = Phy_Setup( pxEMAC_PS );\r
+ XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);\r
+\r
+ /* Setting the operating speed of the MAC needs a delay. */\r
+ vTaskDelay( pdMS_TO_TICKS( 25UL ) );\r
+\r
+ ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);\r
+\r
+ /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive\r
+ packets from the receiver packet buffer memory when no AHB resource is available. */\r
+ XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,\r
+ ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);\r
+\r
+ setup_isr( &xEMACpsif );\r
+ init_dma( &xEMACpsif );\r
+ start_emacps( &xEMACpsif );\r
+\r
+ prvGMACWaitLS( xWaitLinkDelay );\r
+\r
+ /* The deferred interrupt handler task is created at the highest\r
+ possible priority to ensure the interrupt handler can return directly\r
+ to it. The task's handle is stored in xEMACTaskHandle so interrupts can\r
+ notify the task when there is something to process. */\r
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+ }\r
+ else\r
+ {\r
+ /* Initialisation was already performed, just wait for the link. */\r
+ prvGMACWaitLS( xWaitRelinkDelay );\r
+ }\r
+\r
+ /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the\r
+ DHCP process and all other communication will fail. */\r
+ xLinkStatus = xGetPhyLinkStatus();\r
+\r
+ return ( xLinkStatus != pdFALSE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+ emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );\r
+ }\r
+ else if( bReleaseAfterSend != pdFALSE )\r
+ {\r
+ /* No link. */\r
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+ }\r
+\r
+ return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned ulRegister )\r
+{\r
+uint16_t usValue;\r
+\r
+ XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );\r
+ return usValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime, xEndTime;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );\r
+BaseType_t xReturn;\r
+\r
+ xStartTime = xTaskGetTickCount();\r
+\r
+ for( ;; )\r
+ {\r
+ xEndTime = xTaskGetTickCount();\r
+\r
+ if( xEndTime - xStartTime > xMaxTime )\r
+ {\r
+ xReturn = pdFALSE;\r
+ break;\r
+ }\r
+ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xReturn = pdTRUE;\r
+ break;\r
+ }\r
+\r
+ vTaskDelay( xShortDelay );\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+ for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+ {\r
+ pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+ *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+ ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+\r
+ /* A possibility to set some additional task properties like calling\r
+ portTASK_USES_FLOATING_POINT() */\r
+ iptraceEMAC_TASK_STARTING();\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+ for( ;; )\r
+ {\r
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+ if( uxLastMinBufferCount != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+ }\r
+\r
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+ if( uxLastMinQueueSpace != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinQueueSpace = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+ }\r
+ }\r
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+ if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )\r
+ {\r
+ /* No events to process now, wait for the next. */\r
+ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+ }\r
+\r
+ if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )\r
+ {\r
+ xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;\r
+ xResult = emacps_check_rx( &xEMACpsif );\r
+ }\r
+\r
+ if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )\r
+ {\r
+ xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;\r
+ emacps_check_tx( &xEMACpsif );\r
+ }\r
+\r
+ if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )\r
+ {\r
+ xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;\r
+ emacps_check_errors( &xEMACpsif );\r
+ }\r
+\r
+ if( xResult > 0 )\r
+ {\r
+ /* A packet was received. No need to check for the PHY status now,\r
+ but set a timer to check it later on. */\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ xResult = 0;\r
+ }\r
+ else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+ {\r
+ xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+ {\r
+ ulPHYLinkStatus = xStatus;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+ }\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ }\r
+ else\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __NETIF_XEMACPSIF_H__
-#define __NETIF_XEMACPSIF_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "xstatus.h"
-#include "sleep.h"
-#include "xparameters.h"
-#include "xparameters_ps.h" /* defines XPAR values */
-#include "xil_types.h"
-#include "xil_assert.h"
-#include "xil_io.h"
-#include "xil_exception.h"
-#include "xpseudo_asm.h"
-#include "xil_cache.h"
-#include "xil_printf.h"
-#include "xuartps.h"
-#include "xscugic.h"
-#include "xemacps.h" /* defines XEmacPs API */
-
-//#include "netif/xpqueue.h"
-//#include "xlwipconfig.h"
-
-void xemacpsif_setmac(uint32_t index, uint8_t *addr);
-uint8_t* xemacpsif_getmac(uint32_t index);
-//int xemacpsif_init(struct netif *netif);
-//int xemacpsif_input(struct netif *netif);
-#ifdef NOTNOW_BHILL
-unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
-#endif
-
-/* xaxiemacif_hw.c */
-void xemacps_error_handler(XEmacPs * Temac);
-
-struct xBD_TYPE {
- uint32_t address;
- uint32_t flags;
-};
-
-/*
- * Missing declaration in 'src/xemacps_hw.h' :
- * When set, the GEM DMA will automatically
- * discard receive packets from the receiver packet
- * buffer memory when no AHB resource is
- * available.
- * When low, then received packets will remain to be
- * stored in the SRAM based packet buffer until
- * AHB buffer resource next becomes available.
- */
-#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
-
-#define EMAC_IF_RX_EVENT 1
-#define EMAC_IF_TX_EVENT 2
-#define EMAC_IF_ERR_EVENT 4
-#define EMAC_IF_ALL_EVENT 7
-
-/* structure within each netif, encapsulating all information required for
- * using a particular temac instance
- */
-typedef struct {
- XEmacPs emacps;
-
- /* pointers to memory holding buffer descriptors (used only with SDMA) */
- struct xBD_TYPE *rxSegments;
- struct xBD_TYPE *txSegments;
-
- unsigned char *tx_space;
- unsigned uTxUnitSize;
-
- char *remain_mem;
- unsigned remain_siz;
-
- volatile int rxHead, rxTail;
- volatile int txHead, txTail;
-
- volatile int txBusy;
-
- volatile uint32_t isr_events;
-
- unsigned int last_rx_frms_cntr;
-
-} xemacpsif_s;
-
-//extern xemacpsif_s xemacpsif;
-
-int is_tx_space_available(xemacpsif_s *emac);
-
-/* xaxiemacif_dma.c */
-
-struct xNETWORK_BUFFER;
-
-int emacps_check_rx( xemacpsif_s *xemacpsif );
-void emacps_check_tx( xemacpsif_s *xemacpsif );
-int emacps_check_errors( xemacpsif_s *xemacps );
-void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
-
-extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
-extern unsigned Phy_Setup( XEmacPs *xemacpsp );
-extern void setup_isr( xemacpsif_s *xemacpsif );
-extern XStatus init_dma( xemacpsif_s *xemacpsif );
-extern void start_emacps( xemacpsif_s *xemacpsif );
-
-void EmacEnableIntr(void);
-void EmacDisableIntr(void);
-
-XStatus init_axi_dma(xemacpsif_s *xemacpsif);
-void process_sent_bds( xemacpsif_s *xemacpsif );
-
-void emacps_send_handler(void *arg);
-void emacps_recv_handler(void *arg);
-void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
-void HandleTxErrors(xemacpsif_s *xemacpsif);
-XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif);
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __NETIF_XAXIEMACIF_H__ */
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __NETIF_XEMACPSIF_H__\r
+#define __NETIF_XEMACPSIF_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <stdint.h>\r
+\r
+#include "xstatus.h"\r
+#include "sleep.h"\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h" /* defines XPAR values */\r
+#include "xil_types.h"\r
+#include "xil_assert.h"\r
+#include "xil_io.h"\r
+#include "xil_exception.h"\r
+#include "xpseudo_asm.h"\r
+#include "xil_cache.h"\r
+#include "xil_printf.h"\r
+#include "xuartps.h"\r
+#include "xscugic.h"\r
+#include "xemacps.h" /* defines XEmacPs API */\r
+\r
+//#include "netif/xpqueue.h"\r
+//#include "xlwipconfig.h"\r
+\r
+void xemacpsif_setmac(uint32_t index, uint8_t *addr);\r
+uint8_t* xemacpsif_getmac(uint32_t index);\r
+//int xemacpsif_init(struct netif *netif);\r
+//int xemacpsif_input(struct netif *netif);\r
+#ifdef NOTNOW_BHILL\r
+unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);\r
+#endif\r
+\r
+/* xaxiemacif_hw.c */\r
+void xemacps_error_handler(XEmacPs * Temac);\r
+\r
+struct xBD_TYPE {\r
+ uint32_t address;\r
+ uint32_t flags;\r
+};\r
+\r
+/*\r
+ * Missing declaration in 'src/xemacps_hw.h' :\r
+ * When set, the GEM DMA will automatically\r
+ * discard receive packets from the receiver packet\r
+ * buffer memory when no AHB resource is\r
+ * available.\r
+ * When low, then received packets will remain to be\r
+ * stored in the SRAM based packet buffer until\r
+ * AHB buffer resource next becomes available.\r
+ */\r
+#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000\r
+\r
+#define EMAC_IF_RX_EVENT 1\r
+#define EMAC_IF_TX_EVENT 2\r
+#define EMAC_IF_ERR_EVENT 4\r
+#define EMAC_IF_ALL_EVENT 7\r
+\r
+/* structure within each netif, encapsulating all information required for\r
+ * using a particular temac instance\r
+ */\r
+typedef struct {\r
+ XEmacPs emacps;\r
+\r
+ /* pointers to memory holding buffer descriptors (used only with SDMA) */\r
+ struct xBD_TYPE *rxSegments;\r
+ struct xBD_TYPE *txSegments;\r
+\r
+ unsigned char *tx_space;\r
+ unsigned uTxUnitSize;\r
+\r
+ char *remain_mem;\r
+ unsigned remain_siz;\r
+\r
+ volatile int rxHead, rxTail;\r
+ volatile int txHead, txTail;\r
+\r
+ volatile int txBusy;\r
+\r
+ volatile uint32_t isr_events;\r
+\r
+ unsigned int last_rx_frms_cntr;\r
+\r
+} xemacpsif_s;\r
+\r
+//extern xemacpsif_s xemacpsif;\r
+\r
+int is_tx_space_available(xemacpsif_s *emac);\r
+\r
+/* xaxiemacif_dma.c */\r
+\r
+struct xNETWORK_BUFFER;\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif );\r
+void emacps_check_tx( xemacpsif_s *xemacpsif );\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );\r
+\r
+extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );\r
+extern unsigned Phy_Setup( XEmacPs *xemacpsp );\r
+extern void setup_isr( xemacpsif_s *xemacpsif );\r
+extern XStatus init_dma( xemacpsif_s *xemacpsif );\r
+extern void start_emacps( xemacpsif_s *xemacpsif );\r
+\r
+void EmacEnableIntr(void);\r
+void EmacDisableIntr(void);\r
+\r
+XStatus init_axi_dma(xemacpsif_s *xemacpsif);\r
+void process_sent_bds( xemacpsif_s *xemacpsif );\r
+\r
+void emacps_send_handler(void *arg);\r
+void emacps_recv_handler(void *arg);\r
+void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);\r
+void HandleTxErrors(xemacpsif_s *xemacpsif);\r
+XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif);\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __NETIF_XAXIEMACIF_H__ */\r
-/*
-FreeRTOS+TCP V2.0.11
-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
-*/
-
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_topology.h"
-#include "xstatus.h"
-
-#include "xparameters.h"
-#include "xparameters_ps.h"
-#include "xil_exception.h"
-#include "xil_mmu.h"
-
-#include "FreeRTOS.h"
-#include "task.h"
-#include "timers.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-#include "uncached_memory.h"
-
-/* Two defines used to set or clear the EMAC interrupt */
-#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR
-#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR
-
-
-
-#if( ipconfigPACKET_FILLER_SIZE != 2 )
- #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'
-#endif
-#define TX_OFFSET ipconfigPACKET_FILLER_SIZE
-
-#define RX_BUFFER_ALIGNMENT 14
-
-/* Defined in NetworkInterface.c */
-extern TaskHandle_t xEMACTaskHandle;
-
-/*
- pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.
- The actual TX buffers are located in uncached RAM.
-*/
-static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };
-
-/*
- pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.
- Once a message has been received by the EMAC, the descriptor can be passed
- immediately to the IP-task.
-*/
-static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };
-
-/*
- The FreeRTOS+TCP port is using a fixed 'topology', which is declared in
- ./portable/NetworkInterface/Zynq/NetworkInterface.c
-*/
-extern struct xtopology_t xXTopology;
-
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-
-/*
- The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".
- In stead 'struct xemacpsif_s' has a "head" and a "tail" index.
- "head" is the next index to be written, used.
- "tail" is the next index to be read, freed.
-*/
-
-int is_tx_space_available( xemacpsif_s *xemacpsif )
-{
-size_t uxCount;
-
- if( xTXDescriptorSemaphore != NULL )
- {
- uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
- }
- else
- {
- uxCount = ( UBaseType_t ) 0u;
- }
-
- return uxCount;
-}
-
-void emacps_check_tx( xemacpsif_s *xemacpsif )
-{
-int tail = xemacpsif->txTail;
-int head = xemacpsif->txHead;
-size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-
- /* uxCount is the number of TX descriptors that are in use by the DMA. */
- /* When done, "TXBUF_USED" will be set. */
-
- while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )
- {
- if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )
- {
- break;
- }
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-#warning ipconfigZERO_COPY_TX_DRIVER is defined
- {
- void *pvBuffer = pxDMA_tx_buffers[ tail ];
- NetworkBufferDescriptor_t *pxBuffer;
-
- if( pvBuffer != NULL )
- {
- pxDMA_tx_buffers[ tail ] = NULL;
- pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );
- if( pxBuffer != NULL )
- {
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- }
- else
- {
- FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );
- }
- }
- }
-#endif
- /* Clear all but the "used" and "wrap" bits. */
- if( tail < ipconfigNIC_N_TX_DESC - 1 )
- {
- xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;
- }
- else
- {
- xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
- }
- uxCount--;
- /* Tell the counting semaphore that one more TX descriptor is available. */
- xSemaphoreGive( xTXDescriptorSemaphore );
- if( ++tail == ipconfigNIC_N_TX_DESC )
- {
- tail = 0;
- }
- xemacpsif->txTail = tail;
- }
-
- return;
-}
-
-void emacps_send_handler(void *arg)
-{
-xemacpsif_s *xemacpsif;
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in
- "isr_events". The task in NetworkInterface will wake-up and do the necessary work.
- */
- xemacpsif->isr_events |= EMAC_IF_TX_EVENT;
- xemacpsif->txBusy = pdFALSE;
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static BaseType_t xValidLength( BaseType_t xLength )
-{
-BaseType_t xReturn;
-
- if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )
- {
- xReturn = pdTRUE;
- }
- else
- {
- xReturn = pdFALSE;
- }
-
- return xReturn;
-}
-
-XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )
-{
-int head = xemacpsif->txHead;
-int iHasSent = 0;
-uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;
-TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
-
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- /* This driver wants to own all network buffers which are to be transmitted. */
- configASSERT( iReleaseAfterSend != pdFALSE );
- }
- #endif
-
- /* Open a do {} while ( 0 ) loop to be able to call break. */
- do
- {
- uint32_t ulFlags = 0;
-
- if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )
- {
- break;
- }
-
- if( xTXDescriptorSemaphore == NULL )
- {
- break;
- }
-
- if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
- {
- FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );
- break;
- }
-
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- /* Pass the pointer (and its ownership) directly to DMA. */
- pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;
- if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
- }
- /* Buffer has been transferred, do not release it. */
- iReleaseAfterSend = pdFALSE;
-#else
- if( pxDMA_tx_buffers[ head ] == NULL )
- {
- FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );
- break;
- }
- /* Copy the message to unbuffered space in RAM. */
- memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
-#endif
- /* Packets will be sent one-by-one, so for each packet
- the TXBUF_LAST bit will be set. */
- ulFlags |= XEMACPS_TXBUF_LAST_MASK;
- ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );
- if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )
- {
- ulFlags |= XEMACPS_TXBUF_WRAP_MASK;
- }
-
- /* Copy the address of the buffer and set the flags. */
- xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];
- xemacpsif->txSegments[ head ].flags = ulFlags;
-
- iHasSent = pdTRUE;
- if( ++head == ipconfigNIC_N_TX_DESC )
- {
- head = 0;
- }
- /* Update the TX-head index. These variable are declared volatile so they will be
- accessed as little as possible. */
- xemacpsif->txHead = head;
- } while( pdFALSE );
-
- if( iReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxBuffer );
- pxBuffer = NULL;
- }
-
- /* Data Synchronization Barrier */
- dsb();
-
- if( iHasSent != pdFALSE )
- {
- /* Make STARTTX high */
- uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);
- /* Start transmit */
- xemacpsif->txBusy = pdTRUE;
- XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
- }
- dsb();
-
- return 0;
-}
-
-void emacps_recv_handler(void *arg)
-{
- xemacpsif_s *xemacpsif;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- xemacpsif = (xemacpsif_s *)(arg);
- xemacpsif->isr_events |= EMAC_IF_RX_EVENT;
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static NetworkBufferDescriptor_t *ethMsg = NULL;
-static NetworkBufferDescriptor_t *ethLast = NULL;
-
-static void passEthMessages( void )
-{
-IPStackEvent_t xRxEvent;
-
- xRxEvent.eEventType = eNetworkRxEvent;
- xRxEvent.pvData = ( void * ) ethMsg;
-
- if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
- {
- /* The buffer could not be sent to the stack so must be released again.
- This is a deferred handler taskr, not a real interrupt, so it is ok to
- use the task level function here. */
- do
- {
- NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;
- vReleaseNetworkBufferAndDescriptor( ethMsg );
- ethMsg = xNext;
- } while( ethMsg != NULL );
-
- iptraceETHERNET_RX_EVENT_LOST();
- FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );
- }
-
- ethMsg = ethLast = NULL;
-}
-
-int emacps_check_rx( xemacpsif_s *xemacpsif )
-{
-NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
-int rx_bytes;
-volatile int msgCount = 0;
-int head = xemacpsif->rxHead;
-
- /* There seems to be an issue (SI# 692601), see comments below. */
- resetrx_on_no_rxdata(xemacpsif);
-
- /* This FreeRTOS+TCP driver shall be compiled with the option
- "ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a
- chain of RX messages within one message to the IP-task. */
- for( ;; )
- {
- if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||
- ( pxDMA_rx_buffers[ head ] == NULL ) )
- {
- break;
- }
-
- pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
- if( pxNewBuffer == NULL )
- {
- /* A packet has been received, but there is no replacement for this Network Buffer.
- The packet will be dropped, and it Network Buffer will stay in place. */
- FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );
- pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
- }
- else
- {
- pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
-
- /* Just avoiding to use or refer to the same buffer again */
- pxDMA_rx_buffers[ head ] = pxNewBuffer;
-
- /*
- * Adjust the buffer size to the actual number of bytes received.
- */
- rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;
-
- pxBuffer->xDataLength = rx_bytes;
-
- if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );
- }
-
- /* store it in the receive queue, where it'll be processed by a
- different handler. */
- iptraceNETWORK_INTERFACE_RECEIVE();
- pxBuffer->pxNextBuffer = NULL;
-
- if( ethMsg == NULL )
- {
- // Becomes the first message
- ethMsg = pxBuffer;
- }
- else if( ethLast != NULL )
- {
- // Add to the tail
- ethLast->pxNextBuffer = pxBuffer;
- }
-
- ethLast = pxBuffer;
- msgCount++;
- }
- {
- if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
- }
- {
- uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
- if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )
- {
- addr |= XEMACPS_RXBUF_WRAP_MASK;
- }
- /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */
- xemacpsif->rxSegments[ head ].address = addr;
- xemacpsif->rxSegments[ head ].flags = 0;
- }
- }
-
- if( ++head == ipconfigNIC_N_RX_DESC )
- {
- head = 0;
- }
- xemacpsif->rxHead = head;
- }
-
- if( ethMsg != NULL )
- {
- passEthMessages( );
- }
-
- return msgCount;
-}
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif)
-{
-int index;
-unsigned char *ucTxBuffer;
-
- /* Clear all TX descriptors and assign uncached memory to each descriptor.
- "tx_space" points to the first available TX buffer. */
- ucTxBuffer = xemacpsif->tx_space;
-
- for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )
- {
- xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;
- xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- pxDMA_tx_buffers[ index ] = ( void* )NULL;
-#else
- pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );
-#endif
- ucTxBuffer += xemacpsif->uTxUnitSize;
- }
- xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =
- XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
-}
-
-XStatus init_dma(xemacpsif_s *xemacpsif)
-{
- NetworkBufferDescriptor_t *pxBuffer;
-
- int iIndex;
- UBaseType_t xRxSize;
- UBaseType_t xTxSize;
- struct xtopology_t *xtopologyp = &xXTopology;
-
- xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );
-
- xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );
-
- /* Also round-up to 4KB */
- xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
- /*
- * We allocate 65536 bytes for RX BDs which can accommodate a
- * maximum of 8192 BDs which is much more than any application
- * will ever need.
- */
- xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) );
- xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );
- xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );
-
- /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */
- xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;
- xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;
-
- if( xTXDescriptorSemaphore == NULL )
- {
- xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );
- configASSERT( xTXDescriptorSemaphore );
- }
- /*
- * Allocate RX descriptors, 1 RxBD at a time.
- */
- for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )
- {
- pxBuffer = pxDMA_rx_buffers[ iIndex ];
- if( pxBuffer == NULL )
- {
- pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
- if( pxBuffer == NULL )
- {
- FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );
- return -1;
- }
- }
-
- xemacpsif->rxSegments[ iIndex ].flags = 0;
- xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
-
- pxDMA_rx_buffers[ iIndex ] = pxBuffer;
- /* Make sure this memory is not in cache for now. */
- if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
- {
- Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
- (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
- }
- }
-
- xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;
-
- memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );
-
- clean_dma_txdescs( xemacpsif );
-
- {
- uint32_t value;
- value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );
-
- // 1xxxx: Attempt to use INCR16 AHB bursts
- value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;
-#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
- value |= XEMACPS_DMACR_TCPCKSUM_MASK;
-#else
-#warning Are you sure the EMAC should not calculate outgoing checksums?
- value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;
-#endif
- XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );
- }
- {
- uint32_t value;
- value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );
-
- /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).
- Now tell the EMAC that received messages should be stored at "address + 2". */
- value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;
-
-#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )
- value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#else
-#warning Are you sure the EMAC should not calculate incoming checksums?
- value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#endif
- XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );
- }
-
- /*
- * Connect the device driver handler that will be called when an
- * interrupt for the device occurs, the handler defined above performs
- * the specific interrupt processing for the device.
- */
- XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
- (Xil_ExceptionHandler)XEmacPs_IntrHandler,
- (void *)&xemacpsif->emacps);
- /*
- * Enable the interrupt for emacps.
- */
- EmacEnableIntr( );
-
- return 0;
-}
-
-/*
- * resetrx_on_no_rxdata():
- *
- * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
- * called by the user.
- * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
- * Under heavy Rx traffic because of the HW bug there are times when the Rx path
- * becomes unresponsive. The workaround for it is to check for the Rx path for
- * traffic (by reading the stats registers regularly). If the stats register
- * does not increment for sometime (proving no Rx traffic), the function resets
- * the Rx data path.
- *
- */
-
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
-{
- unsigned long regctrl;
- unsigned long tempcntr;
-
- tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );
- if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )
- {
- regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, regctrl);
- regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
- regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
- }
- xemacpsif->last_rx_frms_cntr = tempcntr;
-}
-
-void EmacDisableIntr(void)
-{
- XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
-void EmacEnableIntr(void)
-{
- XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_topology.h"\r
+#include "xstatus.h"\r
+\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h"\r
+#include "xil_exception.h"\r
+#include "xil_mmu.h"\r
+\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "timers.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#include "uncached_memory.h"\r
+\r
+/* Two defines used to set or clear the EMAC interrupt */\r
+#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR\r
+#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR\r
+\r
+\r
+\r
+#if( ipconfigPACKET_FILLER_SIZE != 2 )\r
+ #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'\r
+#endif\r
+#define TX_OFFSET ipconfigPACKET_FILLER_SIZE\r
+\r
+#define RX_BUFFER_ALIGNMENT 14\r
+\r
+/* Defined in NetworkInterface.c */\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*\r
+ pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.\r
+ The actual TX buffers are located in uncached RAM.\r
+*/\r
+static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };\r
+\r
+/*\r
+ pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.\r
+ Once a message has been received by the EMAC, the descriptor can be passed\r
+ immediately to the IP-task.\r
+*/\r
+static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };\r
+\r
+/*\r
+ The FreeRTOS+TCP port is using a fixed 'topology', which is declared in\r
+ ./portable/NetworkInterface/Zynq/NetworkInterface.c\r
+*/\r
+extern struct xtopology_t xXTopology;\r
+\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*\r
+ The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".\r
+ In stead 'struct xemacpsif_s' has a "head" and a "tail" index.\r
+ "head" is the next index to be written, used.\r
+ "tail" is the next index to be read, freed.\r
+*/\r
+\r
+int is_tx_space_available( xemacpsif_s *xemacpsif )\r
+{\r
+size_t uxCount;\r
+\r
+ if( xTXDescriptorSemaphore != NULL )\r
+ {\r
+ uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+ }\r
+ else\r
+ {\r
+ uxCount = ( UBaseType_t ) 0u;\r
+ }\r
+\r
+ return uxCount;\r
+}\r
+\r
+void emacps_check_tx( xemacpsif_s *xemacpsif )\r
+{\r
+int tail = xemacpsif->txTail;\r
+int head = xemacpsif->txHead;\r
+size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+\r
+ /* uxCount is the number of TX descriptors that are in use by the DMA. */\r
+ /* When done, "TXBUF_USED" will be set. */\r
+\r
+ while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )\r
+ {\r
+ if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )\r
+ {\r
+ break;\r
+ }\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+#warning ipconfigZERO_COPY_TX_DRIVER is defined\r
+ {\r
+ void *pvBuffer = pxDMA_tx_buffers[ tail ];\r
+ NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+ if( pvBuffer != NULL )\r
+ {\r
+ pxDMA_tx_buffers[ tail ] = NULL;\r
+ pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );\r
+ if( pxBuffer != NULL )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+ }\r
+ else\r
+ {\r
+ FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );\r
+ }\r
+ }\r
+ }\r
+#endif\r
+ /* Clear all but the "used" and "wrap" bits. */\r
+ if( tail < ipconfigNIC_N_TX_DESC - 1 )\r
+ {\r
+ xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;\r
+ }\r
+ else\r
+ {\r
+ xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+ }\r
+ uxCount--;\r
+ /* Tell the counting semaphore that one more TX descriptor is available. */\r
+ xSemaphoreGive( xTXDescriptorSemaphore );\r
+ if( ++tail == ipconfigNIC_N_TX_DESC )\r
+ {\r
+ tail = 0;\r
+ }\r
+ xemacpsif->txTail = tail;\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+void emacps_send_handler(void *arg)\r
+{\r
+xemacpsif_s *xemacpsif;\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+ xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+ /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in\r
+ "isr_events". The task in NetworkInterface will wake-up and do the necessary work.\r
+ */\r
+ xemacpsif->isr_events |= EMAC_IF_TX_EVENT;\r
+ xemacpsif->txBusy = pdFALSE;\r
+\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+ }\r
+\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static BaseType_t xValidLength( BaseType_t xLength )\r
+{\r
+BaseType_t xReturn;\r
+\r
+ if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )\r
+ {\r
+ xReturn = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdFALSE;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+\r
+XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )\r
+{\r
+int head = xemacpsif->txHead;\r
+int iHasSent = 0;\r
+uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;\r
+TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );\r
+\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ {\r
+ /* This driver wants to own all network buffers which are to be transmitted. */\r
+ configASSERT( iReleaseAfterSend != pdFALSE );\r
+ }\r
+ #endif\r
+\r
+ /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+ do\r
+ {\r
+ uint32_t ulFlags = 0;\r
+\r
+ if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )\r
+ {\r
+ break;\r
+ }\r
+\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ break;\r
+ }\r
+\r
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+ {\r
+ FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );\r
+ break;\r
+ }\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ /* Pass the pointer (and its ownership) directly to DMA. */\r
+ pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;\r
+ if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+ {\r
+ Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+ }\r
+ /* Buffer has been transferred, do not release it. */\r
+ iReleaseAfterSend = pdFALSE;\r
+#else\r
+ if( pxDMA_tx_buffers[ head ] == NULL )\r
+ {\r
+ FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );\r
+ break;\r
+ }\r
+ /* Copy the message to unbuffered space in RAM. */\r
+ memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+#endif\r
+ /* Packets will be sent one-by-one, so for each packet\r
+ the TXBUF_LAST bit will be set. */\r
+ ulFlags |= XEMACPS_TXBUF_LAST_MASK;\r
+ ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );\r
+ if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )\r
+ {\r
+ ulFlags |= XEMACPS_TXBUF_WRAP_MASK;\r
+ }\r
+\r
+ /* Copy the address of the buffer and set the flags. */\r
+ xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];\r
+ xemacpsif->txSegments[ head ].flags = ulFlags;\r
+\r
+ iHasSent = pdTRUE;\r
+ if( ++head == ipconfigNIC_N_TX_DESC )\r
+ {\r
+ head = 0;\r
+ }\r
+ /* Update the TX-head index. These variable are declared volatile so they will be\r
+ accessed as little as possible. */\r
+ xemacpsif->txHead = head;\r
+ } while( pdFALSE );\r
+\r
+ if( iReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+ pxBuffer = NULL;\r
+ }\r
+\r
+ /* Data Synchronization Barrier */\r
+ dsb();\r
+\r
+ if( iHasSent != pdFALSE )\r
+ {\r
+ /* Make STARTTX high */\r
+ uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+ /* Start transmit */\r
+ xemacpsif->txBusy = pdTRUE;\r
+ XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );\r
+ }\r
+ dsb();\r
+\r
+ return 0;\r
+}\r
+\r
+void emacps_recv_handler(void *arg)\r
+{\r
+ xemacpsif_s *xemacpsif;\r
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+ xemacpsif = (xemacpsif_s *)(arg);\r
+ xemacpsif->isr_events |= EMAC_IF_RX_EVENT;\r
+\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+ }\r
+\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static NetworkBufferDescriptor_t *ethMsg = NULL;\r
+static NetworkBufferDescriptor_t *ethLast = NULL;\r
+\r
+static void passEthMessages( void )\r
+{\r
+IPStackEvent_t xRxEvent;\r
+\r
+ xRxEvent.eEventType = eNetworkRxEvent;\r
+ xRxEvent.pvData = ( void * ) ethMsg;\r
+\r
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )\r
+ {\r
+ /* The buffer could not be sent to the stack so must be released again.\r
+ This is a deferred handler taskr, not a real interrupt, so it is ok to\r
+ use the task level function here. */\r
+ do\r
+ {\r
+ NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;\r
+ vReleaseNetworkBufferAndDescriptor( ethMsg );\r
+ ethMsg = xNext;\r
+ } while( ethMsg != NULL );\r
+\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );\r
+ }\r
+\r
+ ethMsg = ethLast = NULL;\r
+}\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif )\r
+{\r
+NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;\r
+int rx_bytes;\r
+volatile int msgCount = 0;\r
+int head = xemacpsif->rxHead;\r
+\r
+ /* There seems to be an issue (SI# 692601), see comments below. */\r
+ resetrx_on_no_rxdata(xemacpsif);\r
+\r
+ /* This FreeRTOS+TCP driver shall be compiled with the option\r
+ "ipconfigUSE_LINKED_RX_MESSAGES" enabled. It allows the driver to send a\r
+ chain of RX messages within one message to the IP-task. */\r
+ for( ;; )\r
+ {\r
+ if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||\r
+ ( pxDMA_rx_buffers[ head ] == NULL ) )\r
+ {\r
+ break;\r
+ }\r
+\r
+ pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );\r
+ if( pxNewBuffer == NULL )\r
+ {\r
+ /* A packet has been received, but there is no replacement for this Network Buffer.\r
+ The packet will be dropped, and it Network Buffer will stay in place. */\r
+ FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );\r
+ pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+ }\r
+ else\r
+ {\r
+ pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+\r
+ /* Just avoiding to use or refer to the same buffer again */\r
+ pxDMA_rx_buffers[ head ] = pxNewBuffer;\r
+\r
+ /*\r
+ * Adjust the buffer size to the actual number of bytes received.\r
+ */\r
+ rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;\r
+\r
+ pxBuffer->xDataLength = rx_bytes;\r
+\r
+ if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+ {\r
+ Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );\r
+ }\r
+\r
+ /* store it in the receive queue, where it'll be processed by a\r
+ different handler. */\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ pxBuffer->pxNextBuffer = NULL;\r
+\r
+ if( ethMsg == NULL )\r
+ {\r
+ // Becomes the first message\r
+ ethMsg = pxBuffer;\r
+ }\r
+ else if( ethLast != NULL )\r
+ {\r
+ // Add to the tail\r
+ ethLast->pxNextBuffer = pxBuffer;\r
+ }\r
+\r
+ ethLast = pxBuffer;\r
+ msgCount++;\r
+ }\r
+ {\r
+ if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )\r
+ {\r
+ Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);\r
+ }\r
+ {\r
+ uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+ if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )\r
+ {\r
+ addr |= XEMACPS_RXBUF_WRAP_MASK;\r
+ }\r
+ /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */\r
+ xemacpsif->rxSegments[ head ].address = addr;\r
+ xemacpsif->rxSegments[ head ].flags = 0;\r
+ }\r
+ }\r
+\r
+ if( ++head == ipconfigNIC_N_RX_DESC )\r
+ {\r
+ head = 0;\r
+ }\r
+ xemacpsif->rxHead = head;\r
+ }\r
+\r
+ if( ethMsg != NULL )\r
+ {\r
+ passEthMessages( );\r
+ }\r
+\r
+ return msgCount;\r
+}\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif)\r
+{\r
+int index;\r
+unsigned char *ucTxBuffer;\r
+\r
+ /* Clear all TX descriptors and assign uncached memory to each descriptor.\r
+ "tx_space" points to the first available TX buffer. */\r
+ ucTxBuffer = xemacpsif->tx_space;\r
+\r
+ for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )\r
+ {\r
+ xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;\r
+ xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+ pxDMA_tx_buffers[ index ] = ( void* )NULL;\r
+#else\r
+ pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );\r
+#endif\r
+ ucTxBuffer += xemacpsif->uTxUnitSize;\r
+ }\r
+ xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =\r
+ XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+}\r
+\r
+XStatus init_dma(xemacpsif_s *xemacpsif)\r
+{\r
+ NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+ int iIndex;\r
+ UBaseType_t xRxSize;\r
+ UBaseType_t xTxSize;\r
+ struct xtopology_t *xtopologyp = &xXTopology;\r
+\r
+ xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );\r
+\r
+ xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );\r
+\r
+ /* Also round-up to 4KB */\r
+ xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;\r
+ /*\r
+ * We allocate 65536 bytes for RX BDs which can accommodate a\r
+ * maximum of 8192 BDs which is much more than any application\r
+ * will ever need.\r
+ */\r
+ xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) );\r
+ xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );\r
+ xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );\r
+\r
+ /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */\r
+ xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;\r
+ xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;\r
+\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );\r
+ configASSERT( xTXDescriptorSemaphore );\r
+ }\r
+ /*\r
+ * Allocate RX descriptors, 1 RxBD at a time.\r
+ */\r
+ for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )\r
+ {\r
+ pxBuffer = pxDMA_rx_buffers[ iIndex ];\r
+ if( pxBuffer == NULL )\r
+ {\r
+ pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );\r
+ if( pxBuffer == NULL )\r
+ {\r
+ FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );\r
+ return -1;\r
+ }\r
+ }\r
+\r
+ xemacpsif->rxSegments[ iIndex ].flags = 0;\r
+ xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+\r
+ pxDMA_rx_buffers[ iIndex ] = pxBuffer;\r
+ /* Make sure this memory is not in cache for now. */\r
+ if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+ {\r
+ Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,\r
+ (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);\r
+ }\r
+ }\r
+\r
+ xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;\r
+\r
+ memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );\r
+\r
+ clean_dma_txdescs( xemacpsif );\r
+\r
+ {\r
+ uint32_t value;\r
+ value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );\r
+\r
+ // 1xxxx: Attempt to use INCR16 AHB bursts\r
+ value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ value |= XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate outgoing checksums?\r
+ value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#endif\r
+ XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );\r
+ }\r
+ {\r
+ uint32_t value;\r
+ value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );\r
+\r
+ /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).\r
+ Now tell the EMAC that received messages should be stored at "address + 2". */\r
+ value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;\r
+\r
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )\r
+ value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate incoming checksums?\r
+ value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#endif\r
+ XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );\r
+ }\r
+\r
+ /*\r
+ * Connect the device driver handler that will be called when an\r
+ * interrupt for the device occurs, the handler defined above performs\r
+ * the specific interrupt processing for the device.\r
+ */\r
+ XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,\r
+ (Xil_ExceptionHandler)XEmacPs_IntrHandler,\r
+ (void *)&xemacpsif->emacps);\r
+ /*\r
+ * Enable the interrupt for emacps.\r
+ */\r
+ EmacEnableIntr( );\r
+\r
+ return 0;\r
+}\r
+\r
+/*\r
+ * resetrx_on_no_rxdata():\r
+ *\r
+ * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata\r
+ * called by the user.\r
+ * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.\r
+ * Under heavy Rx traffic because of the HW bug there are times when the Rx path\r
+ * becomes unresponsive. The workaround for it is to check for the Rx path for\r
+ * traffic (by reading the stats registers regularly). If the stats register\r
+ * does not increment for sometime (proving no Rx traffic), the function resets\r
+ * the Rx data path.\r
+ *\r
+ */\r
+\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)\r
+{\r
+ unsigned long regctrl;\r
+ unsigned long tempcntr;\r
+\r
+ tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );\r
+ if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )\r
+ {\r
+ regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET);\r
+ regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);\r
+ XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET, regctrl);\r
+ regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+ regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);\r
+ XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);\r
+ }\r
+ xemacpsif->last_rx_frms_cntr = tempcntr;\r
+}\r
+\r
+void EmacDisableIntr(void)\r
+{\r
+ XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
+void EmacEnableIntr(void)\r
+{\r
+ XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Zynq/x_emacpsif.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-
-///* FreeRTOS+TCP includes. */
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-extern TaskHandle_t xEMACTaskHandle;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-unsigned int link_speed = 100;
-
-void setup_isr( xemacpsif_s *xemacpsif )
-{
- /*
- * Setup callbacks
- */
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
- (void *) emacps_send_handler,
- (void *) xemacpsif);
-
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
- (void *) emacps_recv_handler,
- (void *) xemacpsif);
-
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
- (void *) emacps_error_handler,
- (void *) xemacpsif);
-}
-
-void start_emacps (xemacpsif_s *xemacps)
-{
- /* start the temac */
- XEmacPs_Start(&xemacps->emacps);
-}
-
-extern struct xtopology_t xXTopology;
-
-volatile int error_msg_count = 0;
-volatile const char *last_err_msg = "";
-
-struct xERROR_MSG {
- void *arg;
- u8 Direction;
- u32 ErrorWord;
-};
-
-static struct xERROR_MSG xErrorList[ 8 ];
-static BaseType_t xErrorHead, xErrorTail;
-
-void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
-{
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xemacpsif_s *xemacpsif;
- BaseType_t xNextHead = xErrorHead;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
- {
- if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
- xNextHead = 0;
- if( xNextHead != xErrorTail )
- {
-
- xErrorList[ xErrorHead ].arg = arg;
- xErrorList[ xErrorHead ].Direction = Direction;
- xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
-
- xErrorHead = xNextHead;
-
- xemacpsif = (xemacpsif_s *)(arg);
- xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
- }
-
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- }
-
- }
-
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
-
-int emacps_check_errors( xemacpsif_s *xemacps )
-{
-int xResult;
-
- ( void ) xemacps;
-
- if( xErrorHead == xErrorTail )
- {
- xResult = 0;
- }
- else
- {
- xResult = 1;
- emacps_handle_error(
- xErrorList[ xErrorTail ].arg,
- xErrorList[ xErrorTail ].Direction,
- xErrorList[ xErrorTail ].ErrorWord );
- }
-
- return xResult;
-}
-
-BaseType_t xNetworkInterfaceInitialise( void );
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
-{
- xemacpsif_s *xemacpsif;
- struct xtopology_t *xtopologyp;
- XEmacPs *xemacps;
-
- xemacpsif = (xemacpsif_s *)(arg);
-
- xtopologyp = &xXTopology;
-
- xemacps = &xemacpsif->emacps;
-
- /* Do not appear to be used. */
- ( void ) xemacps;
- ( void ) xtopologyp;
-
- last_err_msg = NULL;
-
- if( ErrorWord != 0 )
- {
- switch (Direction) {
- case XEMACPS_RECV:
- if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
- {
- last_err_msg = "Receive DMA error";
- xNetworkInterfaceInitialise( );
- }
- if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
- {
- last_err_msg = "Receive over run";
- emacps_recv_handler(arg);
- }
- if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
- {
- last_err_msg = "Receive buffer not available";
- emacps_recv_handler(arg);
- }
- break;
- case XEMACPS_SEND:
- if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
- {
- last_err_msg = "Transmit DMA error";
- xNetworkInterfaceInitialise( );
- }
- if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
- {
- last_err_msg = "Transmit under run";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
- {
- last_err_msg = "Transmit buffer exhausted";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
- {
- last_err_msg = "Transmit retry excessed limits";
- HandleTxErrors( xemacpsif );
- }
- if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
- {
- last_err_msg = "Transmit collision";
- emacps_check_tx( xemacpsif );
- }
- break;
- }
- }
- // Break on this statement and inspect error_msg if you like
- if( last_err_msg != NULL )
- {
- error_msg_count++;
- FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
- }
-}
-
-extern XEmacPs_Config mac_config;
-
-void HandleTxErrors(xemacpsif_s *xemacpsif)
-{
- u32 netctrlreg;
-
- //taskENTER_CRITICAL()
- {
- netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, netctrlreg);
-
- clean_dma_txdescs( xemacpsif );
- netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, netctrlreg);
- }
- //taskEXIT_CRITICAL( );
-}
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+///* FreeRTOS+TCP includes. */\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+unsigned int link_speed = 100;\r
+\r
+void setup_isr( xemacpsif_s *xemacpsif )\r
+{\r
+ /*\r
+ * Setup callbacks\r
+ */\r
+ XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,\r
+ (void *) emacps_send_handler,\r
+ (void *) xemacpsif);\r
+\r
+ XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,\r
+ (void *) emacps_recv_handler,\r
+ (void *) xemacpsif);\r
+\r
+ XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,\r
+ (void *) emacps_error_handler,\r
+ (void *) xemacpsif);\r
+}\r
+\r
+void start_emacps (xemacpsif_s *xemacps)\r
+{\r
+ /* start the temac */\r
+ XEmacPs_Start(&xemacps->emacps);\r
+}\r
+\r
+extern struct xtopology_t xXTopology;\r
+\r
+volatile int error_msg_count = 0;\r
+volatile const char *last_err_msg = "";\r
+\r
+struct xERROR_MSG {\r
+ void *arg;\r
+ u8 Direction;\r
+ u32 ErrorWord;\r
+};\r
+\r
+static struct xERROR_MSG xErrorList[ 8 ];\r
+static BaseType_t xErrorHead, xErrorTail;\r
+\r
+void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+ xemacpsif_s *xemacpsif;\r
+ BaseType_t xNextHead = xErrorHead;\r
+\r
+ xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+ if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )\r
+ {\r
+ if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )\r
+ xNextHead = 0;\r
+ if( xNextHead != xErrorTail )\r
+ {\r
+\r
+ xErrorList[ xErrorHead ].arg = arg;\r
+ xErrorList[ xErrorHead ].Direction = Direction;\r
+ xErrorList[ xErrorHead ].ErrorWord = ErrorWord;\r
+\r
+ xErrorHead = xNextHead;\r
+\r
+ xemacpsif = (xemacpsif_s *)(arg);\r
+ xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;\r
+ }\r
+\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+ }\r
+\r
+ }\r
+\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps )\r
+{\r
+int xResult;\r
+\r
+ ( void ) xemacps;\r
+\r
+ if( xErrorHead == xErrorTail )\r
+ {\r
+ xResult = 0;\r
+ }\r
+ else\r
+ {\r
+ xResult = 1;\r
+ emacps_handle_error(\r
+ xErrorList[ xErrorTail ].arg,\r
+ xErrorList[ xErrorTail ].Direction,\r
+ xErrorList[ xErrorTail ].ErrorWord );\r
+ }\r
+\r
+ return xResult;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void );\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+ xemacpsif_s *xemacpsif;\r
+ struct xtopology_t *xtopologyp;\r
+ XEmacPs *xemacps;\r
+\r
+ xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+ xtopologyp = &xXTopology;\r
+\r
+ xemacps = &xemacpsif->emacps;\r
+\r
+ /* Do not appear to be used. */\r
+ ( void ) xemacps;\r
+ ( void ) xtopologyp;\r
+\r
+ last_err_msg = NULL;\r
+\r
+ if( ErrorWord != 0 )\r
+ {\r
+ switch (Direction) {\r
+ case XEMACPS_RECV:\r
+ if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Receive DMA error";\r
+ xNetworkInterfaceInitialise( );\r
+ }\r
+ if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Receive over run";\r
+ emacps_recv_handler(arg);\r
+ }\r
+ if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Receive buffer not available";\r
+ emacps_recv_handler(arg);\r
+ }\r
+ break;\r
+ case XEMACPS_SEND:\r
+ if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Transmit DMA error";\r
+ xNetworkInterfaceInitialise( );\r
+ }\r
+ if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Transmit under run";\r
+ HandleTxErrors( xemacpsif );\r
+ }\r
+ if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Transmit buffer exhausted";\r
+ HandleTxErrors( xemacpsif );\r
+ }\r
+ if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Transmit retry excessed limits";\r
+ HandleTxErrors( xemacpsif );\r
+ }\r
+ if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )\r
+ {\r
+ last_err_msg = "Transmit collision";\r
+ emacps_check_tx( xemacpsif );\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ // Break on this statement and inspect error_msg if you like\r
+ if( last_err_msg != NULL )\r
+ {\r
+ error_msg_count++;\r
+ FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );\r
+ }\r
+}\r
+\r
+extern XEmacPs_Config mac_config;\r
+\r
+void HandleTxErrors(xemacpsif_s *xemacpsif)\r
+{\r
+ u32 netctrlreg;\r
+\r
+ //taskENTER_CRITICAL()\r
+ {\r
+ netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET);\r
+ netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);\r
+ XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+\r
+ clean_dma_txdescs( xemacpsif );\r
+ netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET);\r
+ netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);\r
+ XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+ XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+ }\r
+ //taskEXIT_CRITICAL( );\r
+}\r
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XEMACPSIF_HW_H_
-#define __XEMACPSIF_HW_H_
-
-#include "Zynq/x_emacpsif.h"
-//#include "lwip/netif.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-XEmacPs_Config * lookup_config(unsigned mac_base);
-
-//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
-
-int emacps_check_errors( xemacpsif_s *xemacps );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XEMACPSIF_HW_H_\r
+#define __XEMACPSIF_HW_H_\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwip/netif.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+XEmacPs_Config * lookup_config(unsigned mac_base);\r
+\r
+//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
-/*
- * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Advanced Micro Devices, Inc. nor the names
- * of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS 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.
- */
-
-/*
- * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Zynq/x_emacpsif.h"
-//#include "lwipopts.h"
-#include "xparameters_ps.h"
-#include "xparameters.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-///* FreeRTOS+TCP includes. */
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-int phy_detected = 0;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-/* Advertisement control register. */
-#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
-#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
-#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
-#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
-
-#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \
- ADVERTISE_10HALF | ADVERTISE_100HALF)
-#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)
-#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)
-
-#define ADVERTISE_1000 0x0300
-
-
-//#define PHY_REG_00_BMCR 0x00 // Basic mode control register
-//#define PHY_REG_01_BMSR 0x01 // Basic mode status register
-//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
-//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
-//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
-
-#define IEEE_CONTROL_REG_OFFSET 0
-#define IEEE_STATUS_REG_OFFSET 1
-#define IEEE_AUTONEGO_ADVERTISE_REG 4
-#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
-#define IEEE_1000_ADVERTISE_REG_OFFSET 9
-#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
-#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
-#define IEEE_SPECIFIC_STATUS_REG 17
-#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
-#define IEEE_CONTROL_REG_MAC 21
-#define IEEE_PAGE_ADDRESS_REGISTER 22
-
-
-#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
-#define IEEE_CTRL_LINKSPEED_MASK 0x0040
-#define IEEE_CTRL_LINKSPEED_1000M 0x0040
-#define IEEE_CTRL_LINKSPEED_100M 0x2000
-#define IEEE_CTRL_LINKSPEED_10M 0x0000
-#define IEEE_CTRL_RESET_MASK 0x8000
-#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#define IEEE_CTRL_RESET 0x9140
-#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
-#endif
-#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
-#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
-#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
-#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
-#define IEEE_AN1_ABILITY_MASK 0x1FE0
-#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
-#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
-#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
-#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
-
-#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
-#define IEEE_PAUSE_MASK 0x0400
-#define IEEE_AUTONEG_ERROR_MASK 0x8000
-
-#define PHY_DETECT_REG 1
-#define PHY_DETECT_MASK 0x1808
-
-#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
-#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
-#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
-#define XEMACPS_GMII2RGMII_REG_NUM 0x10
-
-/* Frequency setting */
-#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)
-#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)
-#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
-#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
-#ifdef PEEP
-#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
-#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
-#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
-#endif
-#define SLCR_LOCK_KEY_VALUE 0x767B
-#define SLCR_UNLOCK_KEY_VALUE 0xDF0D
-#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)
-#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
-
-#define EMAC0_BASE_ADDRESS 0xE000B000
-#define EMAC1_BASE_ADDRESS 0xE000C000
-
-static int detect_phy(XEmacPs *xemacpsp)
-{
- u16 phy_reg;
- u32 phy_addr;
-
- for (phy_addr = 31; phy_addr > 0; phy_addr--) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
- &phy_reg);
-
- if ((phy_reg != 0xFFFF) &&
- ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
- /* Found a valid PHY address */
- FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
- phy_addr));
- FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );
- phy_detected = phy_addr;
- return phy_addr;
- }
- }
-
- FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
-
- /* default to zero */
- return 0;
-}
-
-#ifdef PEEP
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
-
- u16 control;
- u16 status;
- u16 partner_capabilities;
- u16 partner_capabilities_1000;
- u16 phylinkspeed;
- u32 phy_addr = detect_phy(xemacpsp);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- ADVERTISE_1000);
- /* Advertise PHY speed of 100 and 10 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_100_AND_10);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
- &control);
- control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
- IEEE_STAT_AUTONEGOTIATE_RESTART);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
- /* Read PHY control and status registers is successful. */
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-
- if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
- IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
-
- while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
- &status);
- }
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
- &partner_capabilities);
-
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
- &partner_capabilities_1000);
- if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
- return 1000;
- }
-
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
- return 100;
- if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
- return 10;
-
- xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
- __FUNCTION__);
- return 10;
-
- } else {
-
- /* Update TEMAC speed accordingly */
- if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
- /* Get commanded link speed */
- phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
-
- switch (phylinkspeed) {
- case (IEEE_CTRL_LINKSPEED_1000M):
- return 1000;
- case (IEEE_CTRL_LINKSPEED_100M):
- return 100;
- case (IEEE_CTRL_LINKSPEED_10M):
- return 10;
- default:
- xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
- __FUNCTION__, phylinkspeed);
- return 10;
- }
-
- } else {
-
- return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
-
- }
- }
-}
-
-#else /* Zynq */
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
- u16 temp;
- u16 control;
- u16 status;
- u16 partner_capabilities;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
-#else
- u32 phy_addr = detect_phy(xemacpsp);
-#endif
- xil_printf("Start PHY autonegotiation \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;
- control |= IEEE_PAUSE_MASK;
- control |= ADVERTISE_100;
- control |= ADVERTISE_10;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- &control);
- control |= ADVERTISE_1000;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
- &control);
- control |= (7 << 12); /* max number of gigabit attempts */
- control |= (1 << 11); /* enable downshift */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
- control);
-#endif
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
- control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- control &= IEEE_CTRL_ISOLATE_DISABLE;
-#endif
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control |= IEEE_CTRL_RESET_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
- while (1) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- if (control & IEEE_CTRL_RESET_MASK)
- continue;
- else
- break;
- }
-#endif
- xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
- while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
- sleep(1);
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
- &temp);
- if (temp & IEEE_AUTONEG_ERROR_MASK) {
- xil_printf("Auto negotiation error \r\n");
- }
-#endif
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
- &status);
- }
-
- xil_printf("autonegotiation complete \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
-#endif
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
- xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
- XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
- while(!(temp & 0x8000)) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
- }
- if((temp & 0x0C00) == 0x0800) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 1000;
- }
- else if((temp & 0x0C00) == 0x0400) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 100;
- }
- else if((temp & 0x0C00) == 0x0000) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- return 10;
- } else {
- xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
- XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
- XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
- return 10;
- }
-#else
- if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
- return 1000;
- else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
- return 100;
- else /* 10Mbps */
- return 10;
-#endif
-}
-#endif
-
-unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
-{
- u16 control;
- u32 phy_addr = detect_phy(xemacpsp);
-
- XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
- control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
- control |= IEEE_ASYMMETRIC_PAUSE_MASK;
- control |= IEEE_PAUSE_MASK;
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
- control &= ~IEEE_CTRL_LINKSPEED_1000M;
- control &= ~IEEE_CTRL_LINKSPEED_100M;
- control &= ~IEEE_CTRL_LINKSPEED_10M;
-
- if (speed == 1000) {
- control |= IEEE_CTRL_LINKSPEED_1000M;
- }
-
- else if (speed == 100) {
- control |= IEEE_CTRL_LINKSPEED_100M;
- /* Dont advertise PHY speed of 1000 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
- /* Dont advertise PHY speed of 10 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_100);
- }
-
- else if (speed == 10) {
- control |= IEEE_CTRL_LINKSPEED_10M;
- /* Dont advertise PHY speed of 1000 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
- 0);
- /* Dont advertise PHY speed of 100 Mbps */
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
- ADVERTISE_10);
- }
-
- XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
- control | IEEE_CTRL_RESET_MASK);
- {
- volatile int wait;
- for (wait=0; wait < 100000; wait++);
- }
- return 0;
-}
-
-static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
-{
- volatile u32 slcrBaseAddress;
-#ifndef PEEP
- u32 SlcrDiv0;
- u32 SlcrDiv1=0;
- u32 SlcrTxClkCntrl;
-#endif
-
- *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
-
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
- slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
- } else {
- slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
- }
-#ifdef PEEP
- if (speed == 1000) {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_1G_CLK_CTRL_VALUE;
- } else if (speed == 100) {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_100M_CLK_CTRL_VALUE;
- } else {
- *(volatile unsigned int *)(slcrBaseAddress) =
- SLCR_GEM_10M_CLK_CTRL_VALUE;
- }
-#else
- if (speed == 1000) {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
-#endif
- }
- } else if (speed == 100) {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
-#endif
- }
- } else {
- if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
-#endif
- } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
- SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
- SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
-#endif
- }
- }
- SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
- SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
- SlcrTxClkCntrl |= (SlcrDiv1 << 20);
- SlcrTxClkCntrl |= (SlcrDiv0 << 8);
- *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
-#endif
- *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
- return;
-}
-
-
-unsigned link_speed;
-unsigned Phy_Setup (XEmacPs *xemacpsp)
-{
- unsigned long conv_present = 0;
- unsigned long convspeeddupsetting = 0;
- unsigned long convphyaddr = 0;
-
-#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
- conv_present = 1;
-#else
-#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
- convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
- conv_present = 1;
-#endif
-#endif
-
-#ifdef ipconfigNIC_LINKSPEED_AUTODETECT
- link_speed = get_IEEE_phy_speed(xemacpsp);
- if (link_speed == 1000) {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
- } else if (link_speed == 100) {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
- } else {
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
- }
-#elif defined(ipconfigNIC_LINKSPEED1000)
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
- link_speed = 1000;
- configure_IEEE_phy_speed(xemacpsp, link_speed);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
- sleep(1);
-#elif defined(ipconfigNIC_LINKSPEED100)
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
- link_speed = 100;
- configure_IEEE_phy_speed(xemacpsp, link_speed);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
- sleep(1);
-#elif defined(ipconfigNIC_LINKSPEED10)
- SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
- link_speed = 10;
- configure_IEEE_phy_speed(xemacpsp, link_speed);
- convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
- sleep(1);
-#endif
- if (conv_present) {
- XEmacPs_PhyWrite(xemacpsp, convphyaddr,
- XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
- }
-
- xil_printf("link speed: %d\r\n", link_speed);
- return link_speed;
-}
-
+/*\r
+ * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in\r
+ * the documentation and/or other materials provided with the\r
+ * distribution.\r
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names\r
+ * of its contributors may be used to endorse or promote products\r
+ * derived from this software without specific prior written\r
+ * permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/*\r
+ * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwipopts.h"\r
+#include "xparameters_ps.h"\r
+#include "xparameters.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+///* FreeRTOS+TCP includes. */\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+int phy_detected = 0;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+/* Advertisement control register. */\r
+#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */\r
+#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */\r
+#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */\r
+#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */\r
+\r
+#define ADVERTISE_100_AND_10 (ADVERTISE_10FULL | ADVERTISE_100FULL | \\r
+ ADVERTISE_10HALF | ADVERTISE_100HALF)\r
+#define ADVERTISE_100 (ADVERTISE_100FULL | ADVERTISE_100HALF)\r
+#define ADVERTISE_10 (ADVERTISE_10FULL | ADVERTISE_10HALF)\r
+\r
+#define ADVERTISE_1000 0x0300\r
+\r
+\r
+//#define PHY_REG_00_BMCR 0x00 // Basic mode control register\r
+//#define PHY_REG_01_BMSR 0x01 // Basic mode status register\r
+//#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1\r
+//#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2\r
+//#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg\r
+\r
+#define IEEE_CONTROL_REG_OFFSET 0\r
+#define IEEE_STATUS_REG_OFFSET 1\r
+#define IEEE_AUTONEGO_ADVERTISE_REG 4\r
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5\r
+#define IEEE_1000_ADVERTISE_REG_OFFSET 9\r
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10\r
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG 16\r
+#define IEEE_SPECIFIC_STATUS_REG 17\r
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19\r
+#define IEEE_CONTROL_REG_MAC 21\r
+#define IEEE_PAGE_ADDRESS_REGISTER 22\r
+\r
+\r
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040\r
+#define IEEE_CTRL_LINKSPEED_MASK 0x0040\r
+#define IEEE_CTRL_LINKSPEED_1000M 0x0040\r
+#define IEEE_CTRL_LINKSPEED_100M 0x2000\r
+#define IEEE_CTRL_LINKSPEED_10M 0x0000\r
+#define IEEE_CTRL_RESET_MASK 0x8000\r
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#define IEEE_CTRL_RESET 0x9140\r
+#define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF\r
+#endif\r
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008\r
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020\r
+#define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200\r
+#define IEEE_STAT_1GBPS_EXTENSIONS 0x0100\r
+#define IEEE_AN1_ABILITY_MASK 0x1FE0\r
+#define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00\r
+#define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380\r
+#define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060\r
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030\r
+\r
+#define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800\r
+#define IEEE_PAUSE_MASK 0x0400\r
+#define IEEE_AUTONEG_ERROR_MASK 0x8000\r
+\r
+#define PHY_DETECT_REG 1\r
+#define PHY_DETECT_MASK 0x1808\r
+\r
+#define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140\r
+#define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100\r
+#define XEMACPS_GMII2RGMII_SPEED10_FD 0x100\r
+#define XEMACPS_GMII2RGMII_REG_NUM 0x10\r
+\r
+/* Frequency setting */\r
+#define SLCR_LOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x4)\r
+#define SLCR_UNLOCK_ADDR (XPS_SYS_CTRL_BASEADDR + 0x8)\r
+#define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)\r
+#define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)\r
+#ifdef PEEP\r
+#define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031\r
+#define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001\r
+#define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011\r
+#endif\r
+#define SLCR_LOCK_KEY_VALUE 0x767B\r
+#define SLCR_UNLOCK_KEY_VALUE 0xDF0D\r
+#define SLCR_ADDR_GEM_RST_CTRL (XPS_SYS_CTRL_BASEADDR + 0x214)\r
+#define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF\r
+\r
+#define EMAC0_BASE_ADDRESS 0xE000B000\r
+#define EMAC1_BASE_ADDRESS 0xE000C000\r
+\r
+static int detect_phy(XEmacPs *xemacpsp)\r
+{\r
+ u16 phy_reg;\r
+ u32 phy_addr;\r
+\r
+ for (phy_addr = 31; phy_addr > 0; phy_addr--) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,\r
+ &phy_reg);\r
+\r
+ if ((phy_reg != 0xFFFF) &&\r
+ ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {\r
+ /* Found a valid PHY address */\r
+ FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",\r
+ phy_addr));\r
+ FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );\r
+ phy_detected = phy_addr;\r
+ return phy_addr;\r
+ }\r
+ }\r
+\r
+ FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );\r
+\r
+ /* default to zero */\r
+ return 0;\r
+}\r
+\r
+#ifdef PEEP\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+\r
+ u16 control;\r
+ u16 status;\r
+ u16 partner_capabilities;\r
+ u16 partner_capabilities_1000;\r
+ u16 phylinkspeed;\r
+ u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+ ADVERTISE_1000);\r
+ /* Advertise PHY speed of 100 and 10 Mbps */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+ ADVERTISE_100_AND_10);\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+ &control);\r
+ control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
+ IEEE_STAT_AUTONEGOTIATE_RESTART);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+ /* Read PHY control and status registers is successful. */\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+\r
+ if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
+ IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
+\r
+ while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+ &status);\r
+ }\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
+ &partner_capabilities);\r
+\r
+ if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
+ &partner_capabilities_1000);\r
+ if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
+ return 1000;\r
+ }\r
+\r
+ if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
+ return 100;\r
+ if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
+ return 10;\r
+\r
+ xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",\r
+ __FUNCTION__);\r
+ return 10;\r
+\r
+ } else {\r
+\r
+ /* Update TEMAC speed accordingly */\r
+ if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+ /* Get commanded link speed */\r
+ phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
+\r
+ switch (phylinkspeed) {\r
+ case (IEEE_CTRL_LINKSPEED_1000M):\r
+ return 1000;\r
+ case (IEEE_CTRL_LINKSPEED_100M):\r
+ return 100;\r
+ case (IEEE_CTRL_LINKSPEED_10M):\r
+ return 10;\r
+ default:\r
+ xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",\r
+ __FUNCTION__, phylinkspeed);\r
+ return 10;\r
+ }\r
+\r
+ } else {\r
+\r
+ return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
+\r
+ }\r
+ }\r
+}\r
+\r
+#else /* Zynq */\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+ u16 temp;\r
+ u16 control;\r
+ u16 status;\r
+ u16 partner_capabilities;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+ u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
+#else\r
+ u32 phy_addr = detect_phy(xemacpsp);\r
+#endif\r
+ xil_printf("Start PHY autonegotiation \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+ XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+ control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+ control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+ control |= IEEE_PAUSE_MASK;\r
+ control |= ADVERTISE_100;\r
+ control |= ADVERTISE_10;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+ &control);\r
+ control |= ADVERTISE_1000;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+ control);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+ &control);\r
+ control |= (7 << 12); /* max number of gigabit attempts */\r
+ control |= (1 << 11); /* enable downshift */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+ control);\r
+#endif\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+ control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
+ control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+ control &= IEEE_CTRL_ISOLATE_DISABLE;\r
+#endif\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+ control |= IEEE_CTRL_RESET_MASK;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+ while (1) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+ if (control & IEEE_CTRL_RESET_MASK)\r
+ continue;\r
+ else\r
+ break;\r
+ }\r
+#endif\r
+ xil_printf("Waiting for PHY to complete autonegotiation.\r\n");\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+ while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+ sleep(1);\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
+ &temp);\r
+ if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
+ xil_printf("Auto negotiation error \r\n");\r
+ }\r
+#endif\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+ &status);\r
+ }\r
+\r
+ xil_printf("autonegotiation complete \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
+#endif\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+ xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+ while(!(temp & 0x8000)) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+ }\r
+ if((temp & 0x0C00) == 0x0800) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+ return 1000;\r
+ }\r
+ else if((temp & 0x0C00) == 0x0400) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+ return 100;\r
+ }\r
+ else if((temp & 0x0C00) == 0x0000) {\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+ return 10;\r
+ } else {\r
+ xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
+ return 10;\r
+ }\r
+#else\r
+ if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
+ return 1000;\r
+ else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
+ return 100;\r
+ else /* 10Mbps */\r
+ return 10;\r
+#endif\r
+}\r
+#endif\r
+\r
+unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
+{\r
+ u16 control;\r
+ u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+ control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+ control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+ control |= IEEE_PAUSE_MASK;\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+ XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+ control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
+ control &= ~IEEE_CTRL_LINKSPEED_100M;\r
+ control &= ~IEEE_CTRL_LINKSPEED_10M;\r
+\r
+ if (speed == 1000) {\r
+ control |= IEEE_CTRL_LINKSPEED_1000M;\r
+ }\r
+\r
+ else if (speed == 100) {\r
+ control |= IEEE_CTRL_LINKSPEED_100M;\r
+ /* Dont advertise PHY speed of 1000 Mbps */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
+ /* Dont advertise PHY speed of 10 Mbps */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+ ADVERTISE_100);\r
+ }\r
+\r
+ else if (speed == 10) {\r
+ control |= IEEE_CTRL_LINKSPEED_10M;\r
+ /* Dont advertise PHY speed of 1000 Mbps */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+ 0);\r
+ /* Dont advertise PHY speed of 100 Mbps */\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+ ADVERTISE_10);\r
+ }\r
+\r
+ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+ control | IEEE_CTRL_RESET_MASK);\r
+ {\r
+ volatile int wait;\r
+ for (wait=0; wait < 100000; wait++);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
+{\r
+ volatile u32 slcrBaseAddress;\r
+#ifndef PEEP\r
+ u32 SlcrDiv0;\r
+ u32 SlcrDiv1=0;\r
+ u32 SlcrTxClkCntrl;\r
+#endif\r
+\r
+ *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
+\r
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+ slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
+ } else {\r
+ slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
+ }\r
+#ifdef PEEP\r
+ if (speed == 1000) {\r
+ *(volatile unsigned int *)(slcrBaseAddress) =\r
+ SLCR_GEM_1G_CLK_CTRL_VALUE;\r
+ } else if (speed == 100) {\r
+ *(volatile unsigned int *)(slcrBaseAddress) =\r
+ SLCR_GEM_100M_CLK_CTRL_VALUE;\r
+ } else {\r
+ *(volatile unsigned int *)(slcrBaseAddress) =\r
+ SLCR_GEM_10M_CLK_CTRL_VALUE;\r
+ }\r
+#else\r
+ if (speed == 1000) {\r
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+ } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+ }\r
+ } else if (speed == 100) {\r
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+ } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+ }\r
+ } else {\r
+ if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+ } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
+ SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
+ SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+ }\r
+ }\r
+ SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
+ SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
+ SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
+ SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
+ *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
+#endif\r
+ *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
+ return;\r
+}\r
+\r
+\r
+unsigned link_speed;\r
+unsigned Phy_Setup (XEmacPs *xemacpsp)\r
+{\r
+ unsigned long conv_present = 0;\r
+ unsigned long convspeeddupsetting = 0;\r
+ unsigned long convphyaddr = 0;\r
+\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
+ convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
+ conv_present = 1;\r
+#else\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
+ convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
+ conv_present = 1;\r
+#endif\r
+#endif\r
+\r
+#ifdef ipconfigNIC_LINKSPEED_AUTODETECT\r
+ link_speed = get_IEEE_phy_speed(xemacpsp);\r
+ if (link_speed == 1000) {\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+ } else if (link_speed == 100) {\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+ } else {\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+ }\r
+#elif defined(ipconfigNIC_LINKSPEED1000)\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+ link_speed = 1000;\r
+ configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+ sleep(1);\r
+#elif defined(ipconfigNIC_LINKSPEED100)\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+ link_speed = 100;\r
+ configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+ sleep(1);\r
+#elif defined(ipconfigNIC_LINKSPEED10)\r
+ SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+ link_speed = 10;\r
+ configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+ convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+ sleep(1);\r
+#endif\r
+ if (conv_present) {\r
+ XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
+ XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
+ }\r
+\r
+ xil_printf("link speed: %d\r\n", link_speed);\r
+ return link_speed;\r
+}\r
+\r
-/*
- * Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XTOPOLOGY_H_
-#define __XTOPOLOGY_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
-
-struct xtopology_t {
- unsigned emac_baseaddr;
- enum xemac_types emac_type;
- unsigned intc_baseaddr;
- unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
- unsigned scugic_baseaddr; /* valid only for Zynq */
- unsigned scugic_emac_intr; /* valid only for GEM */
-};
-
-extern int x_topology_n_emacs;
-extern struct xtopology_t x_topology[];
-
-int x_topology_find_index(unsigned base);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*\r
+ * Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XTOPOLOGY_H_\r
+#define __XTOPOLOGY_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };\r
+\r
+struct xtopology_t {\r
+ unsigned emac_baseaddr;\r
+ enum xemac_types emac_type;\r
+ unsigned intc_baseaddr;\r
+ unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */\r
+ unsigned scugic_baseaddr; /* valid only for Zynq */\r
+ unsigned scugic_emac_intr; /* valid only for GEM */\r
+};\r
+\r
+extern int x_topology_n_emacs;\r
+extern struct xtopology_t x_topology[];\r
+\r
+int x_topology_find_index(unsigned base);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
- /* FIX ME. */
- return pdFALSE;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
-{
- /* FIX ME. */
- return pdFALSE;
-}
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
- /* FIX ME. */
-}
-
-BaseType_t xGetPhyLinkStatus( void )
-{
- /* FIX ME. */
- return pdFALSE;
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+ /* FIX ME. */\r
+ return pdFALSE;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+ /* FIX ME. */\r
+ return pdFALSE;\r
+}\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+ /* FIX ME. */\r
+}\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+ /* FIX ME. */\r
+ return pdFALSE;\r
}
\ No newline at end of file
-/*
-FreeRTOS+TCP V2.0.11
-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>
-#include <stdarg.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 "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-#include "sam4e_xplained_pro.h"
-#include "hr_gettime.h"
-#include "conf_eth.h"
-#include "ksz8851snl.h"
-#include "ksz8851snl_reg.h"
-
-/* Some files from the Atmel Software Framework */
-#include <sysclk.h>
-#include <pdc/pdc.h>
-#include <spi/spi.h>
-
-/*
- Sending a packet:
-
- 1) Called by UP-task, add buffer to the TX-list:
- xNetworkInterfaceOutput()
- tx_buffers[ us_tx_head ] = pxNetworkBuffer;
- tx_busy[ us_tx_head ] = pdTRUE;
- us_tx_head++;
-
- 2) Called by EMAC-Task: start SPI transfer
- ksz8851snl_update()
- if( ul_spi_pdc_status == SPI_PDC_IDLE )
- {
- if( ( tx_busy[ us_tx_tail ] != pdFALSE ) &&
- ( us_pending_frame == 0 ) &&
- ( ul_had_intn_interrupt == 0 ) )
- {
- // disable all interrupts.
- ksz8851_reg_write( REG_INT_MASK, 0 );
- Bring KSZ8851SNL_CSN_GPIO low
- ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );
- ul_spi_pdc_status = SPI_PDC_TX_START;
- tx_cur_buffer = pxNetworkBuffer;
- }
- }
- 3) Wait for SPI RXBUFF interrupt
- SPI_Handler()
- if( ul_spi_pdc_status == SPI_PDC_TX_START )
- {
- if( SPI_Status & SPI_SR_RXBUFF )
- {
- ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;
- }
- }
-
- 4) Called by EMAC-Task: finish SPI transfer
- ksz8851snl_update()
- if( ul_spi_pdc_status == SPI_PDC_TX_COMPLETE )
- {
- ul_spi_pdc_status = SPI_PDC_IDLE;
- Bring KSZ8851SNL_CSN_GPIO high
- // TX step12: disable TXQ write access.
- ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
- // TX step12.1: enqueue frame in TXQ.
- ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );
-
- // RX step13: enable INT_RX flag.
- ksz8851_reg_write( REG_INT_MASK, INT_RX );
-
- // Buffer sent, free the corresponding buffer and mark descriptor as owned by software.
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
- tx_buffers[ us_tx_tail ] = NULL;
- tx_busy[ us_tx_tail ] = pdFALSE;
- us_tx_tail++
- }
-
- Receiving a packet:
-
- 1) Wait for a INTN interrupt
- INTN_Handler()
- ul_had_intn_interrupt = 1
- vTaskNotifyGiveFromISR(); // Wake up the EMAC task
-
- 2) Called by EMAC-Task: check for new fragments and start SPI transfer
- ksz8851snl_update()
- if( ul_spi_pdc_status == SPI_PDC_IDLE )
- {
- if( ( ul_had_intn_interrupt != 0 ) || ( us_pending_frame > 0 ) )
- {
- if( us_pending_frame == 0 )
- {
- us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
- if( us_pending_frame == 0 )
- {
- break;
- }
- }
- // RX step2: disable all interrupts.
- ksz8851_reg_write( REG_INT_MASK, 0 );
- Check if there is a valid packet: REG_RX_FHR_STATUS
- Read the length of the next fragment: REG_RX_FHR_BYTE_CNT
- ul_spi_pdc_status = SPI_PDC_RX_START;
- gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
- // Start SPI data transfer
- ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer, xReadLength );
- }
- }
-
- 3) Wait for SPI RXBUFF interrupt
- SPI_Handler()
- if( ul_spi_pdc_status == SPI_PDC_RX_START:
- {
- if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )
- {
- // Transfer complete, disable SPI RXBUFF interrupt.
- spi_disable_interrupt( KSZ8851SNL_SPI, SPI_IDR_RXBUFF );
-
- ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;
- }
- }
- }
-
- 4) Finish SPI transfer
- ksz8851snl_update()
- if( ul_spi_pdc_status == SPI_PDC_RX_COMPLETE )
- {
- ul_spi_pdc_status = SPI_PDC_IDLE;
- Bring KSZ8851SNL_CSN_GPIO high
- // RX step21: end RXQ read access.
- ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);
- // RX step22-23: update frame count to be read.
- us_pending_frame--
- // RX step24: enable INT_RX flag if transfer complete.
- if( us_pending_frame == 0 )
- {
- // Allow more RX interrupts.
- ksz8851_reg_write( REG_INT_MASK, INT_RX );
- }
-
- // Mark descriptor ready to be read.
- rx_ready[ rxHead ] = pdTRUE;
- rxHead++
- }
-*/
-
-#define PHY_REG_00_BMCR 0x00 // Basic mode control register
-#define PHY_REG_01_BMSR 0x01 // Basic mode status register
-#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
-#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
-#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
-#define PHY_REG_05_LPA 0x05 // Link partner ability reg
-#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
-#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
-#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
-
-#define BMSR_LINK_STATUS 0x0004 //!< Link status
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
- receiving packets. */
- #define PHY_LS_HIGH_CHECK_TIME_MS 15000
-#endif
-
-#ifndef PHY_LS_LOW_CHECK_TIME_MS
- /* Check if the LinkSStatus in the PHY is still low every second. */
- #define PHY_LS_LOW_CHECK_TIME_MS 1000
-#endif
-
-/* 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 )
-
-#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR
-
-#ifdef ipconfigHAS_TX_CRC_OFFLOADING
- #undef ipconfigHAS_TX_CRC_OFFLOADING
-#endif
-/* Override this define because the KSZ8851 is programmed to set all outgoing CRC's */
-#define ipconfigHAS_TX_CRC_OFFLOADING 1
-
-#ifndef EMAC_MAX_BLOCK_TIME_MS
- #define EMAC_MAX_BLOCK_TIME_MS 100ul
-#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 ( 6 * configMINIMAL_STACK_SIZE )
-#endif
-
-#define SPI_PDC_IDLE 0
-#define SPI_PDC_RX_START 1
-#define SPI_PDC_TX_ERROR 2
-#define SPI_PDC_RX_COMPLETE 3
-#define SPI_PDC_TX_START 4
-#define SPI_PDC_RX_ERROR 5
-#define SPI_PDC_TX_COMPLETE 6
-
-/**
- * ksz8851snl driver structure.
- */
-typedef struct {
- /** Set to 1 when owner is software (ready to read), 0 for Micrel. */
- uint32_t rx_ready[MICREL_RX_BUFFERS];
- /** Set to 1 when owner is Micrel, 0 for software. */
- uint32_t tx_busy[MICREL_TX_BUFFERS];
- /** RX NetworkBufferDescriptor_t pointer list */
- NetworkBufferDescriptor_t *rx_buffers[MICREL_RX_BUFFERS];
- /** TX NetworkBufferDescriptor_t pointer list */
- NetworkBufferDescriptor_t *tx_buffers[MICREL_TX_BUFFERS];
- NetworkBufferDescriptor_t *tx_cur_buffer;
-
- /** Circular buffer head pointer for packet received. */
- uint32_t us_rx_head;
- /** Circular buffer tail pointer for packet to be read. */
- uint32_t us_rx_tail;
- /** Circular buffer head pointer by upper layer (buffer to be sent). */
- uint32_t us_tx_head;
- /** Circular buffer tail pointer incremented by handlers (buffer sent). */
- uint32_t us_tx_tail;
-
- uint32_t ul_total_tx;
- uint32_t ul_total_rx;
- uint32_t tx_space;
-
- /** Still experimental: hash table to allow certain multicast addresses. */
- uint16_t pusHashTable[ 4 ];
-
- /* ul_spi_pdc_status has "SPI_PDC_xxx" values. */
- volatile uint32_t ul_spi_pdc_status;
-
- /* ul_had_intn_interrupt becomes true within the INTN interrupt. */
- volatile uint32_t ul_had_intn_interrupt;
-
- uint16_t us_pending_frame;
-} xKSZ8851_Device_t;
-
-/* SPI PDC register base.
-Declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */
-extern Pdc *g_p_spi_pdc;
-
-/* Temporary buffer for PDC reception.
-declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */
-extern uint8_t tmpbuf[1536];
-
-COMPILER_ALIGNED(8)
-static xKSZ8851_Device_t xMicrelDevice;
-
-static TaskHandle_t xTransmitHandle;
-
-/*-----------------------------------------------------------*/
-
-/*
- * Wait a fixed time for the link status to indicate the network is up.
- */
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler task that processes GMAC interrupts.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*
- * Try to obtain an Rx packet from the hardware.
- */
-static uint32_t prvEMACRxPoll( void );
-
-static inline unsigned long ulReadMDIO( unsigned uAddress );
-
-static void ksz8851snl_low_level_init( void );
-
-static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( 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 uint32_t ulPHYLinkStatus = 0;
-static volatile BaseType_t xGMACSwitchRequired;
-
-static void ksz8851snl_update( void );
-
-static void ksz8851snl_rx_init( void );
-
-static void ksz8851snl_tx_init( void );
-
-/* 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;
-
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-const TickType_t x5_Seconds = 5000UL;
-
- if( xEMACTaskHandle == NULL )
- {
- ksz8851snl_low_level_init();
-
- /* Wait at most 5 seconds for a Link Status in the PHY. */
- xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );
-
- /* 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 );
- }
-
- /* When returning non-zero, the stack will become active and
- start DHCP (in configured) */
- ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xResult;
-
- /* This function returns true if the Link Status in the PHY is high. */
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xResult = pdTRUE;
- }
- else
- {
- xResult = pdFALSE;
- }
-
- return xResult;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )
-{
-BaseType_t xResult = pdFALSE;
-int txHead = xMicrelDevice.us_tx_head;
-
- /* Make sure the next descriptor is free. */
- if( xMicrelDevice.tx_busy[ txHead ] != pdFALSE )
- {
- /* All TX buffers busy. */
- }
- else if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
- {
- /* Output: LS low. */
- }
- else
- {
- /* Pass the packet. */
- xMicrelDevice.tx_buffers[ txHead ] = pxNetworkBuffer;
- /* The descriptor is now owned by Micrel. */
- xMicrelDevice.tx_busy[ txHead ] = pdTRUE;
-
- /* Move the head pointer. */
- if( ++txHead == MICREL_TX_BUFFERS )
- {
- txHead = 0;
- }
- xMicrelDevice.us_tx_head = txHead;
- if( xEMACTaskHandle != NULL )
- {
- xTaskNotifyGive( xEMACTaskHandle );
- }
-
- #if( ipconfigZERO_COPY_TX_DRIVER != 1 )
- #warning Please ipconfigZERO_COPY_TX_DRIVER as 1
- #endif
- configASSERT( bReleaseAfterSend != pdFALSE );
- xResult = pdTRUE;
- }
- if( ( xResult == pdFALSE ) && ( bReleaseAfterSend != pdFALSE ) )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- }
- return xResult;
-}
-/*-----------------------------------------------------------*/
-
-/* This Micrel has numbered it's PHY registers in a different way.
-Translate the register index. */
-static int ks8851_phy_reg( int reg )
-{
- switch (reg) {
- case PHY_REG_00_BMCR:
- return REG_PHY_CNTL; // P1MBCR;
- case PHY_REG_01_BMSR:
- return REG_PHY_STATUS;
- case PHY_REG_02_PHYSID1:
- return REG_PHY_ID_LOW;
- case PHY_REG_03_PHYSID2:
- return REG_PHY_ID_HIGH;
- case PHY_REG_04_ADVERTISE:
- return REG_PHY_AUTO_NEGOTIATION;
- case PHY_REG_05_LPA:
- return REG_PHY_REMOTE_CAPABILITY;
- }
-
- return 0x0;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned uAddress )
-{
-uint16_t usPHYStatus;
-int ks8851_reg = ks8851_phy_reg( uAddress );
-
- if( ks8851_reg != 0 )
- {
- usPHYStatus = ksz8851_reg_read( ks8851_reg );
- }
- else
- {
- /* Other addresses not yet implemented. */
- usPHYStatus = 0;
- }
- return usPHYStatus;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime = xTaskGetTickCount();
-TickType_t xEndTime;
-BaseType_t xReturn;
-const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
-const uint32_t ulHz_Per_MHz = 1000000UL;
-
- for( ;; )
- {
- xEndTime = xTaskGetTickCount();
-
- if( ( xEndTime - xStartTime ) > xMaxTime )
- {
- /* Wated more than xMaxTime, return. */
- xReturn = pdFALSE;
- break;
- }
-
- /* Check the link status again. */
- ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- /* Link is up - return. */
- xReturn = pdTRUE;
- break;
- }
-
- /* Link is down - wait in the Blocked state for a short while (to allow
- other tasks to execute) before checking again. */
- vTaskDelay( xShortTime );
- }
-
- FreeRTOS_printf( ( "xGMACWaitLS: %ld freq %lu Mz\n",
- xReturn,
- sysclk_get_cpu_hz() / ulHz_Per_MHz ) );
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void vPioSetPinHigh(uint32_t ul_pin)
-{
- Pio *p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
- // Value to be driven on the I/O line: 1.
- p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
-}
-
-/**
- * \brief Handler for SPI interrupt.
- */
-void SPI_Handler(void)
-{
-BaseType_t xDoWakeup = pdFALSE;
-BaseType_t xKSZTaskWoken = pdFALSE;
-uint32_t ulCurrentSPIStatus;
-uint32_t ulEnabledSPIStatus;
-
- ulCurrentSPIStatus = spi_read_status( KSZ8851SNL_SPI );
- ulEnabledSPIStatus = spi_read_interrupt_mask( KSZ8851SNL_SPI );
- ulCurrentSPIStatus &= ulEnabledSPIStatus;
- spi_disable_interrupt( KSZ8851SNL_SPI, ulCurrentSPIStatus );
-
-
- switch( xMicrelDevice.ul_spi_pdc_status )
- {
- case SPI_PDC_RX_START:
- {
- if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )
- {
- pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_ERROR;
- xDoWakeup = pdTRUE;
- }
- else
- {
- if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )
- {
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;
- xDoWakeup = pdTRUE;
- }
- }
- }
- break;
-
- case SPI_PDC_TX_START:
- {
- /* Middle of TX. */
- if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )
- {
- pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_ERROR;
- xDoWakeup = pdTRUE;
- }
- else
- {
- if( ( ulCurrentSPIStatus & SPI_SR_ENDRX ) != 0 )
- {
- /* Enable RX complete interrupt. */
- spi_enable_interrupt( KSZ8851SNL_SPI, SPI_IER_RXBUFF );
- }
- /* End of TX. */
- if( ( ulCurrentSPIStatus & SPI_END_OF_TX ) != 0 )
- {
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;
- xDoWakeup = pdTRUE;
- }
- }
- }
- break;
- } /* switch( xMicrelDevice.ul_spi_pdc_status ) */
-
- if( xDoWakeup != pdFALSE )
- {
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xKSZTaskWoken );
- }
- }
- else
- {
- }
- portEND_SWITCHING_ISR( xKSZTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-static void INTN_Handler(uint32_t id, uint32_t mask)
-{
-BaseType_t xKSZTaskWoken = pdFALSE;
-
- if( ( id == INTN_ID ) &&
- ( mask == INTN_PIN_MSK ) )
- {
- /* Clear the PIO interrupt flags. */
- pio_get_interrupt_status( INTN_PIO );
-
- /* Set the INTN flag. */
- xMicrelDevice.ul_had_intn_interrupt++;
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &( xKSZTaskWoken ) );
- }
- }
- portEND_SWITCHING_ISR( xKSZTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-/**
- * \brief Populate the RX descriptor ring buffers with pbufs.
- *
- * \param p_ksz8851snl_dev Pointer to driver data structure.
- */
-static void ksz8851snl_rx_populate_queue( void )
-{
- uint32_t ul_index = 0;
- NetworkBufferDescriptor_t *pxNetworkBuffer;
-
- /* Set up the RX descriptors */
- for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {
- if( xMicrelDevice.rx_buffers[ ul_index ] == NULL )
- {
- /* Allocate a new NetworkBufferDescriptor_t with the maximum size. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipconfigNETWORK_MTU + 36, 100 );
- if( pxNetworkBuffer == NULL )
- {
- FreeRTOS_printf( ( "ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t allocation failure\n" ) );
- configASSERT( 1 == 2 );
- }
-
- /* Make sure lwIP is well configured so one NetworkBufferDescriptor_t can contain the maximum packet size. */
- //LWIP_ASSERT("ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t size too small!", pbuf_clen(pxNetworkBuffer) <= 1);
-
- /* Save NetworkBufferDescriptor_t pointer to be sent to lwIP upper layer. */
- xMicrelDevice.rx_buffers[ ul_index ] = pxNetworkBuffer;
- /* Pass it to Micrel for reception. */
- xMicrelDevice.rx_ready[ ul_index ] = pdFALSE;
- }
- }
-}
-
-unsigned tx_space, wait_tx_space, tx_status, fhr_status;
-unsigned rx_debug = 0;
-/**
- * \brief Update Micrel state machine and perform required actions.
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- */
-static void ksz8851snl_update()
-{
- uint16_t txmir = 0;
-
-/* Check for free PDC. */
- switch( xMicrelDevice.ul_spi_pdc_status )
- {
- case SPI_PDC_TX_ERROR:
- {
- uint32_t ulValue;
- // /* TX step11: end TX transfer. */
- gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
- vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
- vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
- vTaskDelay( 1 );
-
- /* Disable asynchronous transfer mode. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
- /* TX step12: disable TXQ write access. */
- ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
- ulValue = ksz8851snl_reset_tx();
-
- xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;
-
- FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );
- }
- break;
-
- case SPI_PDC_RX_ERROR:
- {
- uint32_t ulValue;
- /* TX step11: end TX transfer. */
- gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
- vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
- vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
- vTaskDelay( 1 );
-
- /* Disable asynchronous transfer mode. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
- /* TX step12: disable TXQ write access. */
- ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
- //ulValue = ksz8851snl_reset_rx();
- ulValue = ksz8851snl_reinit();
-
- xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );
-
- FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );
- }
- break;
- }
- switch( xMicrelDevice.ul_spi_pdc_status )
- {
- case SPI_PDC_IDLE:
- {
- int txTail = xMicrelDevice.us_tx_tail;
-
- /*
- * ========================== Handle RX ==========================
- */
- if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )
- {
- int rxHead = xMicrelDevice.us_rx_head;
- NetworkBufferDescriptor_t *pxNetworkBuffer;
-#warning try
- xMicrelDevice.ul_had_intn_interrupt = 0;
-
- if( xMicrelDevice.us_pending_frame == 0 )
- {
- uint16_t int_status;
- /* RX step1: read interrupt status for INT_RX flag. */
- int_status = ksz8851_reg_read( REG_INT_STATUS );
-
-
- /* RX step2: disable all interrupts. */
- ksz8851_reg_write( REG_INT_MASK, 0 );
-
- /* RX step3: clear INT_RX flag. */
- ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );
-
- /* RX step4-5: check for received frames. */
- xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
- if( xMicrelDevice.us_pending_frame == 0 )
- {
- /* RX step24: enable INT_RX flag. */
- ksz8851_reg_write(REG_INT_MASK, INT_RX);
- return;
- }
- }
-#warning try
- xMicrelDevice.ul_had_intn_interrupt = 0;
-
- /* Now xMicrelDevice.us_pending_frame != 0 */
-
- /* Don't break Micrel state machine, wait for a free descriptor first! */
- if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )
- {
- FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",
- xMicrelDevice.us_rx_tail, rxHead ) );
- return;
- }
- pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];
-
- if( pxNetworkBuffer == NULL )
- {
- ksz8851snl_rx_populate_queue();
- FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );
- return;
- }
-
- /* RX step6: get RX packet status. */
- fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
- if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )
- {
- ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);
- FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );
-
- /* RX step4-5: check for received frames. */
- xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
- if( xMicrelDevice.us_pending_frame == 0 )
- {
- /* RX step24: enable INT_RX flag. */
- ksz8851_reg_write(REG_INT_MASK, INT_RX);
- }
- ulISREvents |= EMAC_IF_ERR_EVENT;
- }
- else
- {
- size_t xLength;
- /* RX step7: read frame length. */
- xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;
-
- /* RX step8: Drop packet if len is invalid or no descriptor available. */
- if( xLength == 0 )
- {
- ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );
- FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );
- ulISREvents |= EMAC_IF_ERR_EVENT;
- }
- else
- {
- size_t xReadLength = xLength;
-
- xMicrelDevice.ul_total_rx++;
- /* RX step9: reset RX frame pointer. */
- ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);
-
- /* RX step10: start RXQ read access. */
- ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);
- /* RX step11-17: start asynchronous FIFO read operation. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;
- gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
- if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )
- {
- xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;
- }
-
- /* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */
- ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );
- /* Remove CRC and update buffer length. */
- xLength -= 4;
- pxNetworkBuffer->xDataLength = xLength;
- /* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */
- }
- }
- break;
- } /* ul_had_intn_interrupt || us_pending_frame */
- /*
- * ========================== Handle TX ==========================
- */
-
- /* Fetch next packet to be sent. */
- if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&
- ( xMicrelDevice.us_pending_frame == 0 ) &&
- ( xMicrelDevice.ul_had_intn_interrupt == 0 ) )
- {
- NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];
- size_t xLength = pxNetworkBuffer->xDataLength;
- int iIndex = xLength;
-
- xLength = 4 * ( ( xLength + 3 ) / 4 );
- while( iIndex < ( int ) xLength )
- {
- pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';
- iIndex++;
- }
- pxNetworkBuffer->xDataLength = xLength;
-
- /* TX step1: check if TXQ memory size is available for transmit. */
- txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
- txmir = txmir & TX_MEM_AVAILABLE_MASK;
-
- if( txmir < ( xLength + 8 ) )
- {
- if( wait_tx_space == pdFALSE )
- {
- tx_status = ksz8851_reg_read( REG_TX_STATUS );
- fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
- wait_tx_space = pdTRUE;
- }
- //return;
- rx_debug = 1;
- tx_space = txmir;
- }
- else
- {
- tx_space = txmir;
-
- /* TX step2: disable all interrupts. */
- ksz8851_reg_write( REG_INT_MASK, 0 );
-
- xMicrelDevice.tx_space -= xLength;
-
- /* TX step3: enable TXQ write access. */
- ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );
- /* TX step4-8: perform FIFO write operation. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;
- xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;
- /* Bring SPI SS low. */
- gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
- xMicrelDevice.ul_total_tx++;
-
- ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );
- }
- }
- }
- break; /* SPI_PDC_IDLE */
-
- case SPI_PDC_RX_COMPLETE:
- {
- int rxHead = xMicrelDevice.us_rx_head;
- /* RX step18-19: pad with dummy data to keep dword alignment. */
- /* Packet lengths will be rounded up to a multiple of "sizeof size_t". */
-// xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;
-// if( xLength != 0 )
-// {
-// ksz8851_fifo_dummy( 4 - xLength );
-// }
-
- /* RX step20: end RX transfer. */
- gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
- /* Disable asynchronous transfer mode. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
- /* RX step21: end RXQ read access. */
- ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);
-
- /* RX step22-23: update frame count to be read. */
- xMicrelDevice.us_pending_frame -= 1;
-
- /* RX step24: enable INT_RX flag if transfer complete. */
- if( xMicrelDevice.us_pending_frame == 0 )
- {
- ksz8851_reg_write(REG_INT_MASK, INT_RX);
- }
-
- /* Mark descriptor ready to be read. */
- xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;
- if( ++rxHead == MICREL_RX_BUFFERS )
- {
- rxHead = 0;
- }
- xMicrelDevice.us_rx_head = rxHead;
- if( rx_debug != 0 )
- {
- uint32_t txmir;
- rx_debug = 0;
- txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
- txmir = txmir & TX_MEM_AVAILABLE_MASK;
- }
- /* Tell prvEMACHandlerTask that RX packets are available. */
- ulISREvents |= EMAC_IF_RX_EVENT;
- } /* case SPI_PDC_RX_COMPLETE */
- break;
-
- case SPI_PDC_TX_COMPLETE:
- {
- int txTail = xMicrelDevice.us_tx_tail;
- NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];
-
- size_t xLength;
- /* TX step9-10: pad with dummy data to keep dword alignment. */
- /* Not necessary: length is already a multiple of 4. */
- xLength = pxNetworkBuffer->xDataLength & 3;
- if( xLength != 0 )
- {
-// ksz8851_fifo_dummy( 4 - xLength );
- }
-
-// /* TX step11: end TX transfer. */
- gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
- /* Disable asynchronous transfer mode. */
- xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
- /* TX step12: disable TXQ write access. */
- ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
- xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;
-
- /* TX step12.1: enqueue frame in TXQ. */
- ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );
-
- /* RX step13: enable INT_RX flag. */
-// ksz8851_reg_write( REG_INT_MASK, INT_RX );
- /* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
- xMicrelDevice.tx_buffers[ txTail ] = NULL;
- xMicrelDevice.tx_busy[ txTail ] = pdFALSE;
- if( ++txTail == MICREL_TX_BUFFERS )
- {
- txTail = 0;
- }
-
- xMicrelDevice.us_tx_tail = txTail;
- /* Experiment. */
- //xMicrelDevice.ul_had_intn_interrupt = 1;
- if( xTransmitHandle != NULL )
- {
- xTaskNotifyGive( xTransmitHandle );
- }
-#warning moved downward
- /* RX step13: enable INT_RX flag. */
- ksz8851_reg_write( REG_INT_MASK, INT_RX );
- /* Prevent the EMAC task from sleeping a single time. */
- ulISREvents |= EMAC_IF_TX_EVENT;
- } /* case SPI_PDC_TX_COMPLETE */
- break;
- } /* switch( xMicrelDevice.ul_spi_pdc_status ) */
-}
-
-/**
- * \brief Set up the RX descriptor ring buffers.
- *
- * This function sets up the descriptor list used for RX packets.
- *
- */
-static void ksz8851snl_rx_init()
-{
- uint32_t ul_index = 0;
-
- /* Init pointer index. */
- xMicrelDevice.us_rx_head = 0;
- xMicrelDevice.us_rx_tail = 0;
-
- /* Set up the RX descriptors. */
- for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {
- xMicrelDevice.rx_buffers[ul_index] = NULL;
- xMicrelDevice.rx_ready[ul_index] = pdFALSE;
- }
-
- /* Build RX buffer and descriptors. */
- ksz8851snl_rx_populate_queue();
-}
-
-/**
- * \brief Set up the TX descriptor ring buffers.
- *
- * This function sets up the descriptor list used for TX packets.
- *
- */
-static void ksz8851snl_tx_init()
-{
- uint32_t ul_index = 0;
-
- /* Init TX index pointer. */
- xMicrelDevice.us_tx_head = 0;
- xMicrelDevice.us_tx_tail = 0;
-
- /* Set up the TX descriptors */
- for( ul_index = 0; ul_index < MICREL_TX_BUFFERS; ul_index++ )
- {
- xMicrelDevice.tx_busy[ul_index] = pdFALSE;
- }
- xMicrelDevice.tx_space = 6144;
-}
-
-/**
- * \brief Initialize ksz8851snl ethernet controller.
- *
- * \note Called from ethernetif_init().
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- */
-static void ksz8851snl_low_level_init( void )
-{
- ksz8851snl_rx_init();
- ksz8851snl_tx_init();
-
- /* Enable NVIC interrupts. */
- NVIC_SetPriority(SPI_IRQn, INT_PRIORITY_SPI);
- NVIC_EnableIRQ(SPI_IRQn);
-
- /* Initialize SPI link. */
- if( ksz8851snl_init() < 0 )
- {
- FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );
- configASSERT(0 == 1);
- }
- memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );
- ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );
- ksz8851_reg_write( REG_MAC_HASH_2, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 1 ] ) );
- ksz8851_reg_write( REG_MAC_HASH_4, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 2 ] ) );
- ksz8851_reg_write( REG_MAC_HASH_6, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 3 ] ) );
-
- /* Initialize interrupt line INTN. */
- configure_intn( INTN_Handler );
-}
-
-/**
- * \brief Use pre-allocated pbuf as DMA source and return the incoming packet.
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- *
- * \return a pbuf filled with the received packet (including MAC header).
- * 0 on memory error.
- */
-static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void )
-{
-NetworkBufferDescriptor_t *pxNetworkBuffer = NULL;
-int rxTail = xMicrelDevice.us_rx_tail;
-
- /* Check that descriptor is owned by software (ie packet received). */
- if( xMicrelDevice.rx_ready[ rxTail ] != pdFALSE )
- {
-
- /* Fetch pre-allocated buffer */
- pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxTail ];
-
- /* Remove this pbuf from its descriptor. */
- xMicrelDevice.rx_buffers[ rxTail ] = NULL;
-
- /* Clears rx_ready and sets rx_buffers. */
- ksz8851snl_rx_populate_queue();
-
- if( ++rxTail == MICREL_RX_BUFFERS )
- {
- rxTail = 0;
- }
- xMicrelDevice.us_rx_tail = rxTail;
- }
-
- return pxNetworkBuffer;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvEMACRxPoll( void )
-{
-NetworkBufferDescriptor_t *pxNetworkBuffer;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-uint32_t ulReturnValue = 0;
-
- for( ;; )
- {
- /* Only for logging. */
- int rxTail = xMicrelDevice.us_rx_tail;
- EthernetHeader_t *pxEthernetHeader;
-
- pxNetworkBuffer = ksz8851snl_low_level_input();
-
- if( pxNetworkBuffer == NULL )
- {
- break;
- }
- pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-
- if( ( pxEthernetHeader->usFrameType != ipIPv4_FRAME_TYPE ) &&
- ( pxEthernetHeader->usFrameType != ipARP_FRAME_TYPE ) )
- {
- FreeRTOS_printf( ( "Frame type %02X received\n", pxEthernetHeader->usFrameType ) );
- }
- ulReturnValue++;
-
- xRxEvent.pvData = ( void * )pxNetworkBuffer;
- /* Send the descriptor to the IP task for processing. */
- if( xSendEventStructToIPTask( &xRxEvent, 100UL ) != pdTRUE )
- {
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- iptraceETHERNET_RX_EVENT_LOST();
- FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
- }
- }
-
- return ulReturnValue;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-TickType_t xLoggingTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
-#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
- UBaseType_t uxLastMinQueueSpace = 0;
-#endif
-
- /* Remove compiler warnings about unused parameters. */
- ( void ) pvParameters;
-
- configASSERT( xEMACTaskHandle );
-
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- xLoggingTime = xTaskGetTickCount();
-
- for( ;; )
- {
- uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
- if( uxLastMinBufferCount != uxCurrentCount )
- {
- /* The logging produced below may be helpful
- while tuning +TCP: see how many buffers are in use. */
- uxLastMinBufferCount = uxCurrentCount;
- FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
- uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
- }
-
- #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 */
-
- /* Run the state-machine of the ksz8851 driver. */
- ksz8851snl_update();
-
- if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
- {
- /* No events to process now, wait for the next. */
- ulTaskNotifyTake( pdTRUE, ulMaxBlockTime );
- }
-
- if( ( xTaskGetTickCount() - xLoggingTime ) > 10000 )
- {
- xLoggingTime += 10000;
- FreeRTOS_printf( ( "Now Tx/Rx %7d /%7d\n",
- xMicrelDevice.ul_total_tx, xMicrelDevice.ul_total_rx ) );
- }
-
- 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;
- }
-
- if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
- {
- /* Future extension: logging about errors that occurred. */
- ulISREvents &= ~EMAC_IF_ERR_EVENT;
- }
-
- if( xResult > 0 )
- {
- /* As long as packets are being received, assume that
- the Link Status is high. */
- ulPHYLinkStatus |= BMSR_LINK_STATUS;
- /* A packet was received. No need to check for the PHY status now,
- but set a timer to check it later on. */
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- xResult = 0;
- }
- else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) &&
- ( xMicrelDevice.ul_spi_pdc_status == SPI_PDC_IDLE ) )
- {
- /* Check the link status again. */
- xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
- {
- ulPHYLinkStatus = xStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
- }
-
- vTaskSetTimeOutState( &xPhyTime );
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
- }
- else
- {
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
- }
- }
- }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "sam4e_xplained_pro.h"\r
+#include "hr_gettime.h"\r
+#include "conf_eth.h"\r
+#include "ksz8851snl.h"\r
+#include "ksz8851snl_reg.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+#include <sysclk.h>\r
+#include <pdc/pdc.h>\r
+#include <spi/spi.h>\r
+\r
+/*\r
+ Sending a packet:\r
+\r
+ 1) Called by UP-task, add buffer to the TX-list:\r
+ xNetworkInterfaceOutput()\r
+ tx_buffers[ us_tx_head ] = pxNetworkBuffer;\r
+ tx_busy[ us_tx_head ] = pdTRUE;\r
+ us_tx_head++;\r
+\r
+ 2) Called by EMAC-Task: start SPI transfer\r
+ ksz8851snl_update()\r
+ if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+ {\r
+ if( ( tx_busy[ us_tx_tail ] != pdFALSE ) &&\r
+ ( us_pending_frame == 0 ) &&\r
+ ( ul_had_intn_interrupt == 0 ) )\r
+ {\r
+ // disable all interrupts.\r
+ ksz8851_reg_write( REG_INT_MASK, 0 );\r
+ Bring KSZ8851SNL_CSN_GPIO low\r
+ ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+ ul_spi_pdc_status = SPI_PDC_TX_START;\r
+ tx_cur_buffer = pxNetworkBuffer;\r
+ }\r
+ }\r
+ 3) Wait for SPI RXBUFF interrupt\r
+ SPI_Handler()\r
+ if( ul_spi_pdc_status == SPI_PDC_TX_START )\r
+ {\r
+ if( SPI_Status & SPI_SR_RXBUFF )\r
+ {\r
+ ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+ }\r
+ }\r
+\r
+ 4) Called by EMAC-Task: finish SPI transfer\r
+ ksz8851snl_update()\r
+ if( ul_spi_pdc_status == SPI_PDC_TX_COMPLETE )\r
+ {\r
+ ul_spi_pdc_status = SPI_PDC_IDLE;\r
+ Bring KSZ8851SNL_CSN_GPIO high\r
+ // TX step12: disable TXQ write access.\r
+ ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+ // TX step12.1: enqueue frame in TXQ.\r
+ ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+ // RX step13: enable INT_RX flag.\r
+ ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+\r
+ // Buffer sent, free the corresponding buffer and mark descriptor as owned by software.\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+ tx_buffers[ us_tx_tail ] = NULL;\r
+ tx_busy[ us_tx_tail ] = pdFALSE;\r
+ us_tx_tail++\r
+ }\r
+\r
+ Receiving a packet:\r
+\r
+ 1) Wait for a INTN interrupt\r
+ INTN_Handler()\r
+ ul_had_intn_interrupt = 1\r
+ vTaskNotifyGiveFromISR(); // Wake up the EMAC task\r
+\r
+ 2) Called by EMAC-Task: check for new fragments and start SPI transfer\r
+ ksz8851snl_update()\r
+ if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+ {\r
+ if( ( ul_had_intn_interrupt != 0 ) || ( us_pending_frame > 0 ) )\r
+ {\r
+ if( us_pending_frame == 0 )\r
+ {\r
+ us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+ if( us_pending_frame == 0 )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ // RX step2: disable all interrupts.\r
+ ksz8851_reg_write( REG_INT_MASK, 0 );\r
+ Check if there is a valid packet: REG_RX_FHR_STATUS\r
+ Read the length of the next fragment: REG_RX_FHR_BYTE_CNT\r
+ ul_spi_pdc_status = SPI_PDC_RX_START;\r
+ gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);\r
+ // Start SPI data transfer\r
+ ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer, xReadLength );\r
+ }\r
+ }\r
+\r
+ 3) Wait for SPI RXBUFF interrupt\r
+ SPI_Handler()\r
+ if( ul_spi_pdc_status == SPI_PDC_RX_START:\r
+ {\r
+ if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+ {\r
+ // Transfer complete, disable SPI RXBUFF interrupt.\r
+ spi_disable_interrupt( KSZ8851SNL_SPI, SPI_IDR_RXBUFF );\r
+\r
+ ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+ }\r
+ }\r
+ }\r
+\r
+ 4) Finish SPI transfer\r
+ ksz8851snl_update()\r
+ if( ul_spi_pdc_status == SPI_PDC_RX_COMPLETE )\r
+ {\r
+ ul_spi_pdc_status = SPI_PDC_IDLE;\r
+ Bring KSZ8851SNL_CSN_GPIO high\r
+ // RX step21: end RXQ read access.\r
+ ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+ // RX step22-23: update frame count to be read.\r
+ us_pending_frame--\r
+ // RX step24: enable INT_RX flag if transfer complete.\r
+ if( us_pending_frame == 0 )\r
+ {\r
+ // Allow more RX interrupts.\r
+ ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+ }\r
+\r
+ // Mark descriptor ready to be read.\r
+ rx_ready[ rxHead ] = pdTRUE;\r
+ rxHead++\r
+ }\r
+*/\r
+\r
+#define PHY_REG_00_BMCR 0x00 // Basic mode control register\r
+#define PHY_REG_01_BMSR 0x01 // Basic mode status register\r
+#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1\r
+#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2\r
+#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg\r
+#define PHY_REG_05_LPA 0x05 // Link partner ability reg\r
+#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register\r
+#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX\r
+#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED\r
+\r
+#define BMSR_LINK_STATUS 0x0004 //!< Link status\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+ receiving packets. */\r
+ #define PHY_LS_HIGH_CHECK_TIME_MS 15000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+ /* Check if the LinkSStatus in the PHY is still low every second. */\r
+ #define PHY_LS_LOW_CHECK_TIME_MS 1000\r
+#endif\r
+\r
+/* Interrupt events to process. Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT 1UL\r
+#define EMAC_IF_TX_EVENT 2UL\r
+#define EMAC_IF_ERR_EVENT 4UL\r
+#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR\r
+\r
+#ifdef ipconfigHAS_TX_CRC_OFFLOADING\r
+ #undef ipconfigHAS_TX_CRC_OFFLOADING\r
+#endif\r
+/* Override this define because the KSZ8851 is programmed to set all outgoing CRC's */\r
+#define ipconfigHAS_TX_CRC_OFFLOADING 1\r
+\r
+#ifndef EMAC_MAX_BLOCK_TIME_MS\r
+ #define EMAC_MAX_BLOCK_TIME_MS 100ul\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+ #define configEMAC_TASK_STACK_SIZE ( 6 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+#define SPI_PDC_IDLE 0\r
+#define SPI_PDC_RX_START 1\r
+#define SPI_PDC_TX_ERROR 2\r
+#define SPI_PDC_RX_COMPLETE 3\r
+#define SPI_PDC_TX_START 4\r
+#define SPI_PDC_RX_ERROR 5\r
+#define SPI_PDC_TX_COMPLETE 6\r
+\r
+/**\r
+ * ksz8851snl driver structure.\r
+ */\r
+typedef struct {\r
+ /** Set to 1 when owner is software (ready to read), 0 for Micrel. */\r
+ uint32_t rx_ready[MICREL_RX_BUFFERS];\r
+ /** Set to 1 when owner is Micrel, 0 for software. */\r
+ uint32_t tx_busy[MICREL_TX_BUFFERS];\r
+ /** RX NetworkBufferDescriptor_t pointer list */\r
+ NetworkBufferDescriptor_t *rx_buffers[MICREL_RX_BUFFERS];\r
+ /** TX NetworkBufferDescriptor_t pointer list */\r
+ NetworkBufferDescriptor_t *tx_buffers[MICREL_TX_BUFFERS];\r
+ NetworkBufferDescriptor_t *tx_cur_buffer;\r
+\r
+ /** Circular buffer head pointer for packet received. */\r
+ uint32_t us_rx_head;\r
+ /** Circular buffer tail pointer for packet to be read. */\r
+ uint32_t us_rx_tail;\r
+ /** Circular buffer head pointer by upper layer (buffer to be sent). */\r
+ uint32_t us_tx_head;\r
+ /** Circular buffer tail pointer incremented by handlers (buffer sent). */\r
+ uint32_t us_tx_tail;\r
+\r
+ uint32_t ul_total_tx;\r
+ uint32_t ul_total_rx;\r
+ uint32_t tx_space;\r
+\r
+ /** Still experimental: hash table to allow certain multicast addresses. */\r
+ uint16_t pusHashTable[ 4 ];\r
+\r
+ /* ul_spi_pdc_status has "SPI_PDC_xxx" values. */\r
+ volatile uint32_t ul_spi_pdc_status;\r
+\r
+ /* ul_had_intn_interrupt becomes true within the INTN interrupt. */\r
+ volatile uint32_t ul_had_intn_interrupt;\r
+\r
+ uint16_t us_pending_frame;\r
+} xKSZ8851_Device_t;\r
+\r
+/* SPI PDC register base.\r
+Declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern Pdc *g_p_spi_pdc;\r
+\r
+/* Temporary buffer for PDC reception.\r
+declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern uint8_t tmpbuf[1536];\r
+\r
+COMPILER_ALIGNED(8)\r
+static xKSZ8851_Device_t xMicrelDevice;\r
+\r
+static TaskHandle_t xTransmitHandle;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( void );\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress );\r
+\r
+static void ksz8851snl_low_level_init( void );\r
+\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing. Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+static void ksz8851snl_update( void );\r
+\r
+static void ksz8851snl_rx_init( void );\r
+\r
+static void ksz8851snl_tx_init( void );\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor. The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+ if( xEMACTaskHandle == NULL )\r
+ {\r
+ ksz8851snl_low_level_init();\r
+\r
+ /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+ xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+ /* The handler task is created at the highest possible priority to\r
+ ensure the interrupt handler can return directly to it. */\r
+ xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+ configASSERT( xEMACTaskHandle );\r
+ }\r
+\r
+ /* When returning non-zero, the stack will become active and\r
+ start DHCP (in configured) */\r
+ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+ /* This function returns true if the Link Status in the PHY is high. */\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xResult = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ xResult = pdFALSE;\r
+ }\r
+\r
+ return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+int txHead = xMicrelDevice.us_tx_head;\r
+\r
+ /* Make sure the next descriptor is free. */\r
+ if( xMicrelDevice.tx_busy[ txHead ] != pdFALSE )\r
+ {\r
+ /* All TX buffers busy. */\r
+ }\r
+ else if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+ {\r
+ /* Output: LS low. */\r
+ }\r
+ else\r
+ {\r
+ /* Pass the packet. */\r
+ xMicrelDevice.tx_buffers[ txHead ] = pxNetworkBuffer;\r
+ /* The descriptor is now owned by Micrel. */\r
+ xMicrelDevice.tx_busy[ txHead ] = pdTRUE;\r
+\r
+ /* Move the head pointer. */\r
+ if( ++txHead == MICREL_TX_BUFFERS )\r
+ {\r
+ txHead = 0;\r
+ }\r
+ xMicrelDevice.us_tx_head = txHead;\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ xTaskNotifyGive( xEMACTaskHandle );\r
+ }\r
+\r
+ #if( ipconfigZERO_COPY_TX_DRIVER != 1 )\r
+ #warning Please ipconfigZERO_COPY_TX_DRIVER as 1\r
+ #endif\r
+ configASSERT( bReleaseAfterSend != pdFALSE );\r
+ xResult = pdTRUE;\r
+ }\r
+ if( ( xResult == pdFALSE ) && ( bReleaseAfterSend != pdFALSE ) )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ }\r
+ return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This Micrel has numbered it's PHY registers in a different way.\r
+Translate the register index. */\r
+static int ks8851_phy_reg( int reg )\r
+{\r
+ switch (reg) {\r
+ case PHY_REG_00_BMCR:\r
+ return REG_PHY_CNTL; // P1MBCR;\r
+ case PHY_REG_01_BMSR:\r
+ return REG_PHY_STATUS;\r
+ case PHY_REG_02_PHYSID1:\r
+ return REG_PHY_ID_LOW;\r
+ case PHY_REG_03_PHYSID2:\r
+ return REG_PHY_ID_HIGH;\r
+ case PHY_REG_04_ADVERTISE:\r
+ return REG_PHY_AUTO_NEGOTIATION;\r
+ case PHY_REG_05_LPA:\r
+ return REG_PHY_REMOTE_CAPABILITY;\r
+ }\r
+\r
+ return 0x0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress )\r
+{\r
+uint16_t usPHYStatus;\r
+int ks8851_reg = ks8851_phy_reg( uAddress );\r
+\r
+ if( ks8851_reg != 0 )\r
+ {\r
+ usPHYStatus = ksz8851_reg_read( ks8851_reg );\r
+ }\r
+ else\r
+ {\r
+ /* Other addresses not yet implemented. */\r
+ usPHYStatus = 0;\r
+ }\r
+ return usPHYStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+const uint32_t ulHz_Per_MHz = 1000000UL;\r
+\r
+ for( ;; )\r
+ {\r
+ xEndTime = xTaskGetTickCount();\r
+\r
+ if( ( xEndTime - xStartTime ) > xMaxTime )\r
+ {\r
+ /* Wated more than xMaxTime, return. */\r
+ xReturn = pdFALSE;\r
+ break;\r
+ }\r
+\r
+ /* Check the link status again. */\r
+ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ /* Link is up - return. */\r
+ xReturn = pdTRUE;\r
+ break;\r
+ }\r
+\r
+ /* Link is down - wait in the Blocked state for a short while (to allow\r
+ other tasks to execute) before checking again. */\r
+ vTaskDelay( xShortTime );\r
+ }\r
+\r
+ FreeRTOS_printf( ( "xGMACWaitLS: %ld freq %lu Mz\n",\r
+ xReturn,\r
+ sysclk_get_cpu_hz() / ulHz_Per_MHz ) );\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vPioSetPinHigh(uint32_t ul_pin)\r
+{\r
+ Pio *p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));\r
+ // Value to be driven on the I/O line: 1.\r
+ p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);\r
+}\r
+\r
+/**\r
+ * \brief Handler for SPI interrupt.\r
+ */\r
+void SPI_Handler(void)\r
+{\r
+BaseType_t xDoWakeup = pdFALSE;\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+uint32_t ulCurrentSPIStatus;\r
+uint32_t ulEnabledSPIStatus;\r
+\r
+ ulCurrentSPIStatus = spi_read_status( KSZ8851SNL_SPI );\r
+ ulEnabledSPIStatus = spi_read_interrupt_mask( KSZ8851SNL_SPI );\r
+ ulCurrentSPIStatus &= ulEnabledSPIStatus;\r
+ spi_disable_interrupt( KSZ8851SNL_SPI, ulCurrentSPIStatus );\r
+\r
+\r
+ switch( xMicrelDevice.ul_spi_pdc_status )\r
+ {\r
+ case SPI_PDC_RX_START:\r
+ {\r
+ if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+ {\r
+ pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_ERROR;\r
+ xDoWakeup = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+ {\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+ xDoWakeup = pdTRUE;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+\r
+ case SPI_PDC_TX_START:\r
+ {\r
+ /* Middle of TX. */\r
+ if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+ {\r
+ pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_ERROR;\r
+ xDoWakeup = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ if( ( ulCurrentSPIStatus & SPI_SR_ENDRX ) != 0 )\r
+ {\r
+ /* Enable RX complete interrupt. */\r
+ spi_enable_interrupt( KSZ8851SNL_SPI, SPI_IER_RXBUFF );\r
+ }\r
+ /* End of TX. */\r
+ if( ( ulCurrentSPIStatus & SPI_END_OF_TX ) != 0 )\r
+ {\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+ xDoWakeup = pdTRUE;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ } /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+\r
+ if( xDoWakeup != pdFALSE )\r
+ {\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xKSZTaskWoken );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ }\r
+ portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void INTN_Handler(uint32_t id, uint32_t mask)\r
+{\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+\r
+ if( ( id == INTN_ID ) &&\r
+ ( mask == INTN_PIN_MSK ) )\r
+ {\r
+ /* Clear the PIO interrupt flags. */\r
+ pio_get_interrupt_status( INTN_PIO );\r
+\r
+ /* Set the INTN flag. */\r
+ xMicrelDevice.ul_had_intn_interrupt++;\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &( xKSZTaskWoken ) );\r
+ }\r
+ }\r
+ portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Populate the RX descriptor ring buffers with pbufs.\r
+ *\r
+ * \param p_ksz8851snl_dev Pointer to driver data structure.\r
+ */\r
+static void ksz8851snl_rx_populate_queue( void )\r
+{\r
+ uint32_t ul_index = 0;\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+ /* Set up the RX descriptors */\r
+ for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+ if( xMicrelDevice.rx_buffers[ ul_index ] == NULL )\r
+ {\r
+ /* Allocate a new NetworkBufferDescriptor_t with the maximum size. */\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipconfigNETWORK_MTU + 36, 100 );\r
+ if( pxNetworkBuffer == NULL )\r
+ {\r
+ FreeRTOS_printf( ( "ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t allocation failure\n" ) );\r
+ configASSERT( 1 == 2 );\r
+ }\r
+\r
+ /* Make sure lwIP is well configured so one NetworkBufferDescriptor_t can contain the maximum packet size. */\r
+ //LWIP_ASSERT("ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t size too small!", pbuf_clen(pxNetworkBuffer) <= 1);\r
+\r
+ /* Save NetworkBufferDescriptor_t pointer to be sent to lwIP upper layer. */\r
+ xMicrelDevice.rx_buffers[ ul_index ] = pxNetworkBuffer;\r
+ /* Pass it to Micrel for reception. */\r
+ xMicrelDevice.rx_ready[ ul_index ] = pdFALSE;\r
+ }\r
+ }\r
+}\r
+\r
+unsigned tx_space, wait_tx_space, tx_status, fhr_status;\r
+unsigned rx_debug = 0;\r
+/**\r
+ * \brief Update Micrel state machine and perform required actions.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_update()\r
+{\r
+ uint16_t txmir = 0;\r
+\r
+/* Check for free PDC. */\r
+ switch( xMicrelDevice.ul_spi_pdc_status )\r
+ {\r
+ case SPI_PDC_TX_ERROR:\r
+ {\r
+ uint32_t ulValue;\r
+ // /* TX step11: end TX transfer. */\r
+ gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+ vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+ vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+ vTaskDelay( 1 );\r
+\r
+ /* Disable asynchronous transfer mode. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+ /* TX step12: disable TXQ write access. */\r
+ ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+ ulValue = ksz8851snl_reset_tx();\r
+\r
+ xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+ FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );\r
+ }\r
+ break;\r
+\r
+ case SPI_PDC_RX_ERROR:\r
+ {\r
+ uint32_t ulValue;\r
+ /* TX step11: end TX transfer. */\r
+ gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+ vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+ vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+ vTaskDelay( 1 );\r
+\r
+ /* Disable asynchronous transfer mode. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+ /* TX step12: disable TXQ write access. */\r
+ ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+ //ulValue = ksz8851snl_reset_rx();\r
+ ulValue = ksz8851snl_reinit();\r
+\r
+ xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );\r
+\r
+ FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );\r
+ }\r
+ break;\r
+ }\r
+ switch( xMicrelDevice.ul_spi_pdc_status )\r
+ {\r
+ case SPI_PDC_IDLE:\r
+ {\r
+ int txTail = xMicrelDevice.us_tx_tail;\r
+\r
+ /*\r
+ * ========================== Handle RX ==========================\r
+ */\r
+ if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )\r
+ {\r
+ int rxHead = xMicrelDevice.us_rx_head;\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#warning try\r
+ xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+ if( xMicrelDevice.us_pending_frame == 0 )\r
+ {\r
+ uint16_t int_status;\r
+ /* RX step1: read interrupt status for INT_RX flag. */\r
+ int_status = ksz8851_reg_read( REG_INT_STATUS );\r
+\r
+\r
+ /* RX step2: disable all interrupts. */\r
+ ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+ /* RX step3: clear INT_RX flag. */\r
+ ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );\r
+\r
+ /* RX step4-5: check for received frames. */\r
+ xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+ if( xMicrelDevice.us_pending_frame == 0 )\r
+ {\r
+ /* RX step24: enable INT_RX flag. */\r
+ ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+ return;\r
+ }\r
+ }\r
+#warning try\r
+ xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+ /* Now xMicrelDevice.us_pending_frame != 0 */\r
+\r
+ /* Don't break Micrel state machine, wait for a free descriptor first! */\r
+ if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )\r
+ {\r
+ FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",\r
+ xMicrelDevice.us_rx_tail, rxHead ) );\r
+ return;\r
+ }\r
+ pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];\r
+\r
+ if( pxNetworkBuffer == NULL )\r
+ {\r
+ ksz8851snl_rx_populate_queue();\r
+ FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );\r
+ return;\r
+ }\r
+\r
+ /* RX step6: get RX packet status. */\r
+ fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+ if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )\r
+ {\r
+ ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);\r
+ FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );\r
+\r
+ /* RX step4-5: check for received frames. */\r
+ xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+ if( xMicrelDevice.us_pending_frame == 0 )\r
+ {\r
+ /* RX step24: enable INT_RX flag. */\r
+ ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+ }\r
+ ulISREvents |= EMAC_IF_ERR_EVENT;\r
+ }\r
+ else\r
+ {\r
+ size_t xLength;\r
+ /* RX step7: read frame length. */\r
+ xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;\r
+\r
+ /* RX step8: Drop packet if len is invalid or no descriptor available. */\r
+ if( xLength == 0 )\r
+ {\r
+ ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );\r
+ FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );\r
+ ulISREvents |= EMAC_IF_ERR_EVENT;\r
+ }\r
+ else\r
+ {\r
+ size_t xReadLength = xLength;\r
+\r
+ xMicrelDevice.ul_total_rx++;\r
+ /* RX step9: reset RX frame pointer. */\r
+ ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);\r
+\r
+ /* RX step10: start RXQ read access. */\r
+ ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);\r
+ /* RX step11-17: start asynchronous FIFO read operation. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;\r
+ gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+ if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )\r
+ {\r
+ xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;\r
+ }\r
+\r
+ /* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */\r
+ ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );\r
+ /* Remove CRC and update buffer length. */\r
+ xLength -= 4;\r
+ pxNetworkBuffer->xDataLength = xLength;\r
+ /* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */\r
+ }\r
+ }\r
+ break;\r
+ } /* ul_had_intn_interrupt || us_pending_frame */\r
+ /*\r
+ * ========================== Handle TX ==========================\r
+ */\r
+\r
+ /* Fetch next packet to be sent. */\r
+ if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&\r
+ ( xMicrelDevice.us_pending_frame == 0 ) &&\r
+ ( xMicrelDevice.ul_had_intn_interrupt == 0 ) )\r
+ {\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+ size_t xLength = pxNetworkBuffer->xDataLength;\r
+ int iIndex = xLength;\r
+\r
+ xLength = 4 * ( ( xLength + 3 ) / 4 );\r
+ while( iIndex < ( int ) xLength )\r
+ {\r
+ pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';\r
+ iIndex++;\r
+ }\r
+ pxNetworkBuffer->xDataLength = xLength;\r
+\r
+ /* TX step1: check if TXQ memory size is available for transmit. */\r
+ txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+ txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+\r
+ if( txmir < ( xLength + 8 ) )\r
+ {\r
+ if( wait_tx_space == pdFALSE )\r
+ {\r
+ tx_status = ksz8851_reg_read( REG_TX_STATUS );\r
+ fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+ wait_tx_space = pdTRUE;\r
+ }\r
+ //return;\r
+ rx_debug = 1;\r
+ tx_space = txmir;\r
+ }\r
+ else\r
+ {\r
+ tx_space = txmir;\r
+\r
+ /* TX step2: disable all interrupts. */\r
+ ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+ xMicrelDevice.tx_space -= xLength;\r
+\r
+ /* TX step3: enable TXQ write access. */\r
+ ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );\r
+ /* TX step4-8: perform FIFO write operation. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;\r
+ xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;\r
+ /* Bring SPI SS low. */\r
+ gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+ xMicrelDevice.ul_total_tx++;\r
+\r
+ ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+ }\r
+ }\r
+ }\r
+ break; /* SPI_PDC_IDLE */\r
+\r
+ case SPI_PDC_RX_COMPLETE:\r
+ {\r
+ int rxHead = xMicrelDevice.us_rx_head;\r
+ /* RX step18-19: pad with dummy data to keep dword alignment. */\r
+ /* Packet lengths will be rounded up to a multiple of "sizeof size_t". */\r
+// xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;\r
+// if( xLength != 0 )\r
+// {\r
+// ksz8851_fifo_dummy( 4 - xLength );\r
+// }\r
+\r
+ /* RX step20: end RX transfer. */\r
+ gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+ /* Disable asynchronous transfer mode. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+ /* RX step21: end RXQ read access. */\r
+ ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+\r
+ /* RX step22-23: update frame count to be read. */\r
+ xMicrelDevice.us_pending_frame -= 1;\r
+\r
+ /* RX step24: enable INT_RX flag if transfer complete. */\r
+ if( xMicrelDevice.us_pending_frame == 0 )\r
+ {\r
+ ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+ }\r
+\r
+ /* Mark descriptor ready to be read. */\r
+ xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;\r
+ if( ++rxHead == MICREL_RX_BUFFERS )\r
+ {\r
+ rxHead = 0;\r
+ }\r
+ xMicrelDevice.us_rx_head = rxHead;\r
+ if( rx_debug != 0 )\r
+ {\r
+ uint32_t txmir;\r
+ rx_debug = 0;\r
+ txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+ txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+ }\r
+ /* Tell prvEMACHandlerTask that RX packets are available. */\r
+ ulISREvents |= EMAC_IF_RX_EVENT;\r
+ } /* case SPI_PDC_RX_COMPLETE */\r
+ break;\r
+\r
+ case SPI_PDC_TX_COMPLETE:\r
+ {\r
+ int txTail = xMicrelDevice.us_tx_tail;\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+\r
+ size_t xLength;\r
+ /* TX step9-10: pad with dummy data to keep dword alignment. */\r
+ /* Not necessary: length is already a multiple of 4. */\r
+ xLength = pxNetworkBuffer->xDataLength & 3;\r
+ if( xLength != 0 )\r
+ {\r
+// ksz8851_fifo_dummy( 4 - xLength );\r
+ }\r
+\r
+// /* TX step11: end TX transfer. */\r
+ gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+ /* Disable asynchronous transfer mode. */\r
+ xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+ /* TX step12: disable TXQ write access. */\r
+ ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+ xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+ /* TX step12.1: enqueue frame in TXQ. */\r
+ ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+ /* RX step13: enable INT_RX flag. */\r
+// ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+ /* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+ xMicrelDevice.tx_buffers[ txTail ] = NULL;\r
+ xMicrelDevice.tx_busy[ txTail ] = pdFALSE;\r
+ if( ++txTail == MICREL_TX_BUFFERS )\r
+ {\r
+ txTail = 0;\r
+ }\r
+\r
+ xMicrelDevice.us_tx_tail = txTail;\r
+ /* Experiment. */\r
+ //xMicrelDevice.ul_had_intn_interrupt = 1;\r
+ if( xTransmitHandle != NULL )\r
+ {\r
+ xTaskNotifyGive( xTransmitHandle );\r
+ }\r
+#warning moved downward\r
+ /* RX step13: enable INT_RX flag. */\r
+ ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+ /* Prevent the EMAC task from sleeping a single time. */\r
+ ulISREvents |= EMAC_IF_TX_EVENT;\r
+ } /* case SPI_PDC_TX_COMPLETE */\r
+ break;\r
+ } /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+}\r
+\r
+/**\r
+ * \brief Set up the RX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for RX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_rx_init()\r
+{\r
+ uint32_t ul_index = 0;\r
+\r
+ /* Init pointer index. */\r
+ xMicrelDevice.us_rx_head = 0;\r
+ xMicrelDevice.us_rx_tail = 0;\r
+\r
+ /* Set up the RX descriptors. */\r
+ for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+ xMicrelDevice.rx_buffers[ul_index] = NULL;\r
+ xMicrelDevice.rx_ready[ul_index] = pdFALSE;\r
+ }\r
+\r
+ /* Build RX buffer and descriptors. */\r
+ ksz8851snl_rx_populate_queue();\r
+}\r
+\r
+/**\r
+ * \brief Set up the TX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for TX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_tx_init()\r
+{\r
+ uint32_t ul_index = 0;\r
+\r
+ /* Init TX index pointer. */\r
+ xMicrelDevice.us_tx_head = 0;\r
+ xMicrelDevice.us_tx_tail = 0;\r
+\r
+ /* Set up the TX descriptors */\r
+ for( ul_index = 0; ul_index < MICREL_TX_BUFFERS; ul_index++ )\r
+ {\r
+ xMicrelDevice.tx_busy[ul_index] = pdFALSE;\r
+ }\r
+ xMicrelDevice.tx_space = 6144;\r
+}\r
+\r
+/**\r
+ * \brief Initialize ksz8851snl ethernet controller.\r
+ *\r
+ * \note Called from ethernetif_init().\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_low_level_init( void )\r
+{\r
+ ksz8851snl_rx_init();\r
+ ksz8851snl_tx_init();\r
+\r
+ /* Enable NVIC interrupts. */\r
+ NVIC_SetPriority(SPI_IRQn, INT_PRIORITY_SPI);\r
+ NVIC_EnableIRQ(SPI_IRQn);\r
+\r
+ /* Initialize SPI link. */\r
+ if( ksz8851snl_init() < 0 )\r
+ {\r
+ FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );\r
+ configASSERT(0 == 1);\r
+ }\r
+ memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );\r
+ ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );\r
+ ksz8851_reg_write( REG_MAC_HASH_2, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 1 ] ) );\r
+ ksz8851_reg_write( REG_MAC_HASH_4, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 2 ] ) );\r
+ ksz8851_reg_write( REG_MAC_HASH_6, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 3 ] ) );\r
+\r
+ /* Initialize interrupt line INTN. */\r
+ configure_intn( INTN_Handler );\r
+}\r
+\r
+/**\r
+ * \brief Use pre-allocated pbuf as DMA source and return the incoming packet.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ *\r
+ * \return a pbuf filled with the received packet (including MAC header).\r
+ * 0 on memory error.\r
+ */\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer = NULL;\r
+int rxTail = xMicrelDevice.us_rx_tail;\r
+\r
+ /* Check that descriptor is owned by software (ie packet received). */\r
+ if( xMicrelDevice.rx_ready[ rxTail ] != pdFALSE )\r
+ {\r
+\r
+ /* Fetch pre-allocated buffer */\r
+ pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxTail ];\r
+\r
+ /* Remove this pbuf from its descriptor. */\r
+ xMicrelDevice.rx_buffers[ rxTail ] = NULL;\r
+\r
+ /* Clears rx_ready and sets rx_buffers. */\r
+ ksz8851snl_rx_populate_queue();\r
+\r
+ if( ++rxTail == MICREL_RX_BUFFERS )\r
+ {\r
+ rxTail = 0;\r
+ }\r
+ xMicrelDevice.us_rx_tail = rxTail;\r
+ }\r
+\r
+ return pxNetworkBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulReturnValue = 0;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Only for logging. */\r
+ int rxTail = xMicrelDevice.us_rx_tail;\r
+ EthernetHeader_t *pxEthernetHeader;\r
+\r
+ pxNetworkBuffer = ksz8851snl_low_level_input();\r
+ \r
+ if( pxNetworkBuffer == NULL )\r
+ {\r
+ break;\r
+ }\r
+ pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+ if( ( pxEthernetHeader->usFrameType != ipIPv4_FRAME_TYPE ) &&\r
+ ( pxEthernetHeader->usFrameType != ipARP_FRAME_TYPE ) )\r
+ {\r
+ FreeRTOS_printf( ( "Frame type %02X received\n", pxEthernetHeader->usFrameType ) );\r
+ }\r
+ ulReturnValue++;\r
+\r
+ xRxEvent.pvData = ( void * )pxNetworkBuffer;\r
+ /* Send the descriptor to the IP task for processing. */\r
+ if( xSendEventStructToIPTask( &xRxEvent, 100UL ) != pdTRUE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+ }\r
+ }\r
+\r
+ return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+TickType_t xLoggingTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ UBaseType_t uxLastMinQueueSpace = 0;\r
+#endif\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+\r
+ configASSERT( xEMACTaskHandle );\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ xLoggingTime = xTaskGetTickCount();\r
+\r
+ for( ;; )\r
+ {\r
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+ if( uxLastMinBufferCount != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+ }\r
+\r
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+ if( uxLastMinQueueSpace != uxCurrentCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinQueueSpace = uxCurrentCount;\r
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+ }\r
+ }\r
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+ /* Run the state-machine of the ksz8851 driver. */\r
+ ksz8851snl_update();\r
+\r
+ if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+ {\r
+ /* No events to process now, wait for the next. */\r
+ ulTaskNotifyTake( pdTRUE, ulMaxBlockTime );\r
+ }\r
+\r
+ if( ( xTaskGetTickCount() - xLoggingTime ) > 10000 )\r
+ {\r
+ xLoggingTime += 10000;\r
+ FreeRTOS_printf( ( "Now Tx/Rx %7d /%7d\n",\r
+ xMicrelDevice.ul_total_tx, xMicrelDevice.ul_total_rx ) );\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+ {\r
+ ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+ /* Wait for the EMAC interrupt to indicate that another packet has been\r
+ received. */\r
+ xResult = prvEMACRxPoll();\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+ {\r
+ /* Future extension: code to release TX buffers if zero-copy is used. */\r
+ ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+ }\r
+\r
+ if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+ {\r
+ /* Future extension: logging about errors that occurred. */\r
+ ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+ }\r
+\r
+ if( xResult > 0 )\r
+ {\r
+ /* As long as packets are being received, assume that\r
+ the Link Status is high. */\r
+ ulPHYLinkStatus |= BMSR_LINK_STATUS;\r
+ /* A packet was received. No need to check for the PHY status now,\r
+ but set a timer to check it later on. */\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ xResult = 0;\r
+ }\r
+ else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) &&\r
+ ( xMicrelDevice.ul_spi_pdc_status == SPI_PDC_IDLE ) )\r
+ {\r
+ /* Check the link status again. */\r
+ xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+ {\r
+ ulPHYLinkStatus = xStatus;\r
+ FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+ }\r
+\r
+ vTaskSetTimeOutState( &xPhyTime );\r
+ if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+ }\r
+ else\r
+ {\r
+ xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+ }\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "FreeRTOS_DNS.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-#include "wifi-decl.h"
-#include "wmerrno.h"
-#include "wifi.h"
-
-#include <wmlog.h>
-
-#define net_e(...) \
- wmlog_e("freertos_tcp", ##__VA_ARGS__)
-#define net_w(...) \
- wmlog_w("freertos_tcp", ##__VA_ARGS__)
-#define net_d(...) \
- wmlog("freertos_tcp", ##__VA_ARGS__)
-
-#if 0 //this is lwip structure.
-#define MAX_INTERFACES_SUPPORTED 3
-static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];
-#endif
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
-#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
-
-/** 255.255.255.255 */
-#define IPADDR_NONE ((u32_t)0xffffffffUL)
-/** 127.0.0.1 */
-#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
-/** 0.0.0.0 */
-#define IPADDR_ANY ((u32_t)0x00000000UL)
-/** 255.255.255.255 */
-#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
-
-/** 255.255.255.255 */
-#define INADDR_NONE IPADDR_NONE
-/** 127.0.0.1 */
-#define INADDR_LOOPBACK IPADDR_LOOPBACK
-/** 0.0.0.0 */
-#define INADDR_ANY IPADDR_ANY
-/** 255.255.255.255 */
-#define INADDR_BROADCAST IPADDR_BROADCAST
-
-enum if_state_t {
- INTERFACE_DOWN = 0,
- INTERFACE_UP,
-};
-struct ip_addr {
- u32_t addr;
-};
-
-#define MLAN_BSS_TYPE_STA 0
-
-extern uint8_t outbuf[2048];
-extern bool mlan_is_amsdu(const t_u8 *rcvdata);
-extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);
-extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);
-extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer);
-static volatile uint32_t xInterfaceState = INTERFACE_DOWN;
-
-static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)
-{
- int interface = BSS_TYPE_STA;
- t_u8 *payload = NULL;
- t_u16 payload_len = 0;
- const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
-
- NetworkBufferDescriptor_t *pxNetworkBuffer;
- IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
- payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);
-
- if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {
- net_d("Dropping packet\r\n");
- return WM_SUCCESS;
- }
-
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);
-
- if (pxNetworkBuffer != NULL) {
- /* Set the packet size, in case a larger buffer was returned. */
- pxNetworkBuffer->xDataLength = payload_len;
-
- /* Copy the packet data. */
- memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);
-
- xRxEvent.pvData = (void *) pxNetworkBuffer;
- if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
- wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);
- vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
- return WM_FAIL;
- }
- }
- return WM_SUCCESS;
-}
-
-/* Callback function called from the wifi module */
-void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,
- const t_u16 datalen)
-{
- if (interface == BSS_TYPE_STA)
- process_data_packet(rcvdata, datalen);
-}
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
- uint8_t ret;
- mac_addr_t mac_addr;
-
- ret = wifi_get_device_mac_addr(&mac_addr);
- if (ret != WM_SUCCESS) {
- net_d("Failed to get mac address");
- }
-
- FreeRTOS_UpdateMACAddress(mac_addr.mac);
-
- return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;
-}
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
- /* FIX ME. */
-}
-
-BaseType_t xGetPhyLinkStatus( void )
-{
- /* FIX ME. */
- return pdFALSE;
-}
-void vNetworkNotifyIFDown()
-{
- IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
- xInterfaceState = INTERFACE_DOWN;
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {
- /* Could not send the message, so it is still pending. */
- net_e("Could not send network down event");
- }
- else {
- /* Message was sent so it is not pending. */
- net_d("Sent network down event");
- }
-}
-
-void vNetworkNotifyIFUp()
-{
- xInterfaceState = INTERFACE_UP;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
-{
- uint8_t pkt_len;
-
- if (pxNetworkBuffer == NULL ||
- pxNetworkBuffer->pucEthernetBuffer == NULL ||
- pxNetworkBuffer->xDataLength == 0) {
- net_d("Incorrect params");
- return pdFALSE;
- }
- memset(outbuf, 0x00, sizeof(outbuf));
- pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */
- memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,
- pxNetworkBuffer->xDataLength);
- int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);
- if (ret != WM_SUCCESS) {
- net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
- }
-
- if (xReleaseAfterSend != pdFALSE) {
- vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
- }
-
- return ret == WM_SUCCESS ? pdTRUE : pdFALSE;
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "wifi-decl.h"\r
+#include "wmerrno.h"\r
+#include "wifi.h"\r
+\r
+#include <wmlog.h>\r
+\r
+#define net_e(...) \\r
+ wmlog_e("freertos_tcp", ##__VA_ARGS__)\r
+#define net_w(...) \\r
+ wmlog_w("freertos_tcp", ##__VA_ARGS__)\r
+#define net_d(...) \\r
+ wmlog("freertos_tcp", ##__VA_ARGS__)\r
+\r
+#if 0 //this is lwip structure.\r
+#define MAX_INTERFACES_SUPPORTED 3\r
+static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];\r
+#endif\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)\r
+#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)\r
+\r
+/** 255.255.255.255 */\r
+#define IPADDR_NONE ((u32_t)0xffffffffUL)\r
+/** 127.0.0.1 */\r
+#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)\r
+/** 0.0.0.0 */\r
+#define IPADDR_ANY ((u32_t)0x00000000UL)\r
+/** 255.255.255.255 */\r
+#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)\r
+\r
+/** 255.255.255.255 */\r
+#define INADDR_NONE IPADDR_NONE\r
+/** 127.0.0.1 */\r
+#define INADDR_LOOPBACK IPADDR_LOOPBACK\r
+/** 0.0.0.0 */\r
+#define INADDR_ANY IPADDR_ANY\r
+/** 255.255.255.255 */\r
+#define INADDR_BROADCAST IPADDR_BROADCAST\r
+\r
+enum if_state_t {\r
+ INTERFACE_DOWN = 0,\r
+ INTERFACE_UP,\r
+};\r
+struct ip_addr {\r
+ u32_t addr;\r
+};\r
+\r
+#define MLAN_BSS_TYPE_STA 0\r
+\r
+extern uint8_t outbuf[2048];\r
+extern bool mlan_is_amsdu(const t_u8 *rcvdata);\r
+extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);\r
+extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);\r
+extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer);\r
+static volatile uint32_t xInterfaceState = INTERFACE_DOWN;\r
+\r
+static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)\r
+{\r
+ int interface = BSS_TYPE_STA;\r
+ t_u8 *payload = NULL;\r
+ t_u16 payload_len = 0;\r
+ const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+ payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);\r
+\r
+ if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {\r
+ net_d("Dropping packet\r\n");\r
+ return WM_SUCCESS;\r
+ }\r
+\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);\r
+\r
+ if (pxNetworkBuffer != NULL) {\r
+ /* Set the packet size, in case a larger buffer was returned. */\r
+ pxNetworkBuffer->xDataLength = payload_len;\r
+\r
+ /* Copy the packet data. */\r
+ memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);\r
+\r
+ xRxEvent.pvData = (void *) pxNetworkBuffer;\r
+ if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {\r
+ wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);\r
+ vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+ return WM_FAIL;\r
+ }\r
+ }\r
+ return WM_SUCCESS;\r
+}\r
+\r
+/* Callback function called from the wifi module */\r
+void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,\r
+ const t_u16 datalen)\r
+{\r
+ if (interface == BSS_TYPE_STA)\r
+ process_data_packet(rcvdata, datalen);\r
+}\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+ uint8_t ret;\r
+ mac_addr_t mac_addr;\r
+\r
+ ret = wifi_get_device_mac_addr(&mac_addr);\r
+ if (ret != WM_SUCCESS) {\r
+ net_d("Failed to get mac address");\r
+ }\r
+\r
+ FreeRTOS_UpdateMACAddress(mac_addr.mac);\r
+\r
+ return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;\r
+}\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+ /* FIX ME. */\r
+}\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+ /* FIX ME. */\r
+ return pdFALSE;\r
+}\r
+void vNetworkNotifyIFDown()\r
+{\r
+ IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };\r
+ xInterfaceState = INTERFACE_DOWN;\r
+ if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {\r
+ /* Could not send the message, so it is still pending. */\r
+ net_e("Could not send network down event");\r
+ }\r
+ else {\r
+ /* Message was sent so it is not pending. */\r
+ net_d("Sent network down event");\r
+ }\r
+}\r
+\r
+void vNetworkNotifyIFUp()\r
+{\r
+ xInterfaceState = INTERFACE_UP;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+ uint8_t pkt_len;\r
+\r
+ if (pxNetworkBuffer == NULL ||\r
+ pxNetworkBuffer->pucEthernetBuffer == NULL ||\r
+ pxNetworkBuffer->xDataLength == 0) {\r
+ net_d("Incorrect params");\r
+ return pdFALSE;\r
+ }\r
+ memset(outbuf, 0x00, sizeof(outbuf));\r
+ pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */\r
+ memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,\r
+ pxNetworkBuffer->xDataLength);\r
+ int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);\r
+ if (ret != WM_SUCCESS) {\r
+ net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);\r
+ }\r
+\r
+ if (xReleaseAfterSend != pdFALSE) {\r
+ vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+ }\r
+\r
+ return ret == WM_SUCCESS ? pdTRUE : pdFALSE;\r
+}\r
-/*
- * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
- * Authors include Hein Tibosch and Richard Barry
- *
- *******************************************************************************
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
- *** ***
- *** ***
- *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
- *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
- *** download): ***
- *** ***
- *** FreeRTOS+TCP is functional and has been used in commercial products ***
- *** for some time. Be aware however that we are still refining its ***
- *** design, the source code does not yet quite conform to the strict ***
- *** coding and style standards mandated by Real Time Engineers ltd., and ***
- *** the documentation and testing is not necessarily complete. ***
- *** ***
- *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
- *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
- *** the sole discretion of Real Time Engineers Ltd., be offered versions ***
- *** under a license other than that described below. ***
- *** ***
- *** ***
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
- *******************************************************************************
- *
- * FreeRTOS+TCP can be used under two different free open source licenses. The
- * license that applies is dependent on the processor on which FreeRTOS+TCP is
- * executed, as follows:
- *
- * If FreeRTOS+TCP is executed on one of the processors listed under the Special
- * License Arrangements heading of the FreeRTOS+TCP license information web
- * page, then it can be used under the terms of the FreeRTOS Open Source
- * License. If FreeRTOS+TCP is used on any other processor, then it can be used
- * under the terms of the GNU General Public License V2. Links to the relevant
- * licenses follow:
- *
- * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
- * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
- * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
- *
- * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
- * use FreeRTOS+TCP unless you agree that you use the software 'as is'.
- * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
- * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
- * implied, expressed, or statutory.
- *
- * 1 tab == 4 spaces!
- *
- * http://www.FreeRTOS.org
- * http://www.FreeRTOS.org/plus
- * http://www.FreeRTOS.org/labs
- *
- */
-
-/******************************************************************************
-*
-* See the following web page for essential buffer allocation scheme usage and
-* configuration details:
-* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
-*
-******************************************************************************/
-
-/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
- * THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used,
- * heap_4 can be used. */
-
-/* Standard includes. */
-#include <stdint.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-
-#include "NetworkConfig.h"
-
-/* The obtained network buffer must be large enough to hold a packet that might
- * replace the packet that was requested to be sent. */
-#if ipconfigUSE_TCP == 1
- #define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t )
-#else
- #define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )
-#endif /* ipconfigUSE_TCP == 1 */
-
-/*_RB_ This is too complex not to have an explanation. */
-#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
- #define ASSERT_CONCAT_( a, b ) a ## b
- #define ASSERT_CONCAT( a, b ) ASSERT_CONCAT_( a, b )
- #define STATIC_ASSERT( e ) \
- ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) }
-
- STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
-#endif
-
-/* A list of free (available) NetworkBufferDescriptor_t structures. */
-static List_t xFreeBuffersList;
-
-/* Some statistics about the use of buffers. */
-static size_t uxMinimumFreeNetworkBuffers;
-
-/* Declares the pool of NetworkBufferDescriptor_t structures that are available
- * to the system. All the network buffers referenced from xFreeBuffersList exist
- * in this array. The array is not accessed directly except during initialisation,
- * when the xFreeBuffersList is filled (as all the buffers are free when the system
- * is booted). */
-static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
-
-/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
- * network buffers have a variable size: resizing may be necessary */
-const BaseType_t xBufferAllocFixedSize = pdFALSE;
-
-/* The semaphore used to obtain network buffers. */
-static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
-
-/*-----------------------------------------------------------*/
-
-#ifdef PIC32_USE_ETHERNET
-
- /* PIC32 specific stuff */
- /* */
-
- /* MAC packet acknowledgment, once MAC is done with it */
- static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
- const void * param );
-
- /* allocates a MAC packet that holds a data buffer that can be used by both: */
- /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
- /* - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */
- /* from the beginning of the buffer: */
- /* - 4 bytes pointer to the network descriptor (FreeRTOS) */
- /* - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */
- /* - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */
- /* */
- /* NOTE: segLoadLen should NOT include: */
- /* - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */
- /* - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
- /* These are added by the MAC packet allocation! */
- /* */
- static uint8_t * PIC32_PktAlloc( uint16_t pktLen,
- uint16_t segLoadLen,
- TCPIP_MAC_PACKET_ACK_FUNC ackF,
- TCPIP_MAC_PACKET ** pPtrPkt )
- {
- uint8_t * pBuff = 0;
-
- /* allocate standard packet */
- TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 );
-
- /* set the MAC packet pointer in the packet */
- if( pPkt != 0 )
- {
- pBuff = pPkt->pDSeg->segLoad;
- TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET );
- configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
- *ppkt = pPkt; /* store the packet it comes from */
- pPkt->ackFunc = ackF;
- pPkt->ackParam = 0;
- }
-
- if( pPtrPkt != 0 )
- {
- *pPtrPkt = pPkt;
- }
-
- return pBuff;
- }
-
-
-
- /* standard PIC32 MAC allocation function for a MAC packet */
- /* this packet saves room for the FreeRTOS network descriptor */
- /* at the beginning of the data buffer */
- /* see NetworkBufferAllocate */
- /* Note: flags parameter is ignored since that's used in the Harmony stack only */
- TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
- uint16_t segLoadLen,
- TCPIP_MAC_PACKET_FLAGS flags )
- {
- TCPIP_MAC_PACKET * pPkt;
-
- PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt );
-
- return pPkt;
- }
-
- /* standard PIC32 MAC packet acknowledgment */
- /* function called once MAC is done with it */
- static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
- const void * param )
- {
- configASSERT( ( pPkt != 0 ) );
-
- TCPIP_PKT_PacketFree( pPkt );
-
- return false;
- }
-
- /* associates the current MAC packet with a network descriptor */
- /* mainly for RX packet */
- void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
- NetworkBufferDescriptor_t * pxBufferDescriptor,
- size_t pktLength )
- {
- uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad;
-
- pxBufferDescriptor->pucEthernetBuffer = pPktBuff;
- pxBufferDescriptor->xDataLength = pktLength;
-
- /* make sure this is a properly allocated packet */
- TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET );
- configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-
- if( *ppkt != pRxPkt )
- {
- configASSERT( false );
- }
-
- /* set the proper descriptor info */
- NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING );
- configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
- *ppDcpt = pxBufferDescriptor;
- }
-
- /* debug functionality */
- void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt )
- {
- TCPIP_PKT_PacketFree( pPkt );
- configASSERT( false );
- }
-
- /* FreeRTOS allocation functions */
-
- /* allocates a buffer that can be used by both: */
- /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
- /* - the Harmony MAC driver: TCPIP_MAC_PACKET */
- /* See PIC32_PktAlloc for details */
- /* */
- /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */
- /* or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
- /* These are added by the MAC packet allocation! */
- /* */
- uint8_t * NetworkBufferAllocate( size_t reqLength )
- {
- return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 );
- }
-
- /* deallocates a network buffer previously allocated */
- /* with NetworkBufferAllocate */
- void NetworkBufferFree( uint8_t * pNetworkBuffer )
- {
- if( pNetworkBuffer != 0 )
- {
- TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
- configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
- TCPIP_MAC_PACKET * pPkt = *ppkt;
- configASSERT( ( pPkt != 0 ) );
-
- if( pPkt->ackFunc != 0 )
- {
- ( *pPkt->ackFunc )( pPkt, pPkt->ackParam );
- }
- else
- { /* ??? */
- PIC32_MacPacketOrphan( pPkt );
- }
- }
- }
-
-#endif /* #ifdef PIC32_USE_ETHERNET */
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkBuffersInitialise( void )
-{
- BaseType_t xReturn, x;
-
- /* Only initialise the buffers and their associated kernel objects if they
- * have not been initialised before. */
- if( xNetworkBufferSemaphore == NULL )
- {
- xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
- configASSERT( xNetworkBufferSemaphore );
-
- if( xNetworkBufferSemaphore != NULL )
- {
- #if ( configQUEUE_REGISTRY_SIZE > 0 )
- {
- vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
- }
- #endif /* configQUEUE_REGISTRY_SIZE */
-
- /* If the trace recorder code is included name the semaphore for viewing
- * in FreeRTOS+Trace. */
- #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
- {
- extern QueueHandle_t xNetworkEventQueue;
- vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
- vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
- }
- #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
-
- vListInitialise( &xFreeBuffersList );
-
- /* Initialise all the network buffers. No storage is allocated to
- * the buffers yet. */
- for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
- {
- /* Initialise and set the owner of the buffer list items. */
- xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
- vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
- listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
-
- /* Currently, all buffers are available for use. */
- vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
- }
-
- uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
- }
- }
-
- if( xNetworkBufferSemaphore == NULL )
- {
- xReturn = pdFAIL;
- }
- else
- {
- xReturn = pdPASS;
- }
-
- return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )
-{
- uint8_t * pucEthernetBuffer;
- size_t xSize = *pxRequestedSizeBytes;
-
- if( xSize < baMINIMAL_BUFFER_SIZE )
- {
- /* Buffers must be at least large enough to hold a TCP-packet with
- * headers, or an ARP packet, in case TCP is not included. */
- xSize = baMINIMAL_BUFFER_SIZE;
- }
-
- /* Round up xSize to the nearest multiple of N bytes,
- * where N equals 'sizeof( size_t )'. */
- if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
- {
- xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
- }
-
- *pxRequestedSizeBytes = xSize;
-
- /* Allocate a buffer large enough to store the requested Ethernet frame size
- * and a pointer to a network buffer structure (hence the addition of
- * ipBUFFER_PADDING bytes). */
-
- #ifdef PIC32_USE_ETHERNET
- pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
- #else
- pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- configASSERT( pucEthernetBuffer );
-
- if( pucEthernetBuffer != NULL )
- {
- /* Enough space is left at the start of the buffer to place a pointer to
- * the network buffer structure that references this Ethernet buffer.
- * Return a pointer to the start of the Ethernet buffer itself. */
- #ifndef PIC32_USE_ETHERNET
- pucEthernetBuffer += ipBUFFER_PADDING;
- #endif /* #ifndef PIC32_USE_ETHERNET */
- }
-
- return pucEthernetBuffer;
-}
-/*-----------------------------------------------------------*/
-
-void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer )
-{
- /* There is space before the Ethernet buffer in which a pointer to the
- * network buffer that references this Ethernet buffer is stored. Remove the
- * space before freeing the buffer. */
- #ifdef PIC32_USE_ETHERNET
- NetworkBufferFree( pucEthernetBuffer );
- #else
- if( pucEthernetBuffer != NULL )
- {
- pucEthernetBuffer -= ipBUFFER_PADDING;
- vPortFree( ( void * ) pucEthernetBuffer );
- }
- #endif /* #ifdef PIC32_USE_ETHERNET */
-}
-/*-----------------------------------------------------------*/
-
-NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
- TickType_t xBlockTimeTicks )
-{
- NetworkBufferDescriptor_t * pxReturn = NULL;
- size_t uxCount;
-
- if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
- {
- /* ARP packets can replace application packets, so the storage must be
- * at least large enough to hold an ARP. */
- xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
- }
-
- #ifdef PIC32_USE_ETHERNET
- if( xRequestedSizeBytes != 0u )
- {
- #endif /* #ifdef PIC32_USE_ETHERNET */
- xRequestedSizeBytes += 2u;
-
- if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
- {
- xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
- }
- #ifdef PIC32_USE_ETHERNET
- }
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- /* If there is a semaphore available, there is a network buffer available. */
- if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
- {
- /* Protect the structure as it is accessed from tasks and interrupts. */
- taskENTER_CRITICAL();
- {
- pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
- uxListRemove( &( pxReturn->xBufferListItem ) );
- }
- taskEXIT_CRITICAL();
-
- /* Reading UBaseType_t, no critical section needed. */
- uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
-
- if( uxMinimumFreeNetworkBuffers > uxCount )
- {
- uxMinimumFreeNetworkBuffers = uxCount;
- }
-
- /* Allocate storage of exactly the requested size to the buffer. */
- configASSERT( pxReturn->pucEthernetBuffer == NULL );
-
- if( xRequestedSizeBytes > 0 )
- {
- /* Extra space is obtained so a pointer to the network buffer can
- * be stored at the beginning of the buffer. */
-
- #ifdef PIC32_USE_ETHERNET
- pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
- #else
- pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- if( pxReturn->pucEthernetBuffer == NULL )
- {
- /* The attempt to allocate storage for the buffer payload failed,
- * so the network buffer structure cannot be used and must be
- * released. */
- vReleaseNetworkBufferAndDescriptor( pxReturn );
- pxReturn = NULL;
- }
- else
- {
- /* Store a pointer to the network buffer structure in the
- * buffer storage area, then move the buffer pointer on past the
- * stored pointer so the pointer value is not overwritten by the
- * application when the buffer is used. */
- #ifdef PIC32_USE_ETHERNET
- *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn;
- #else
- *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
- pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- /* Store the actual size of the allocated buffer, which may be
- * greater than the original requested size. */
- pxReturn->xDataLength = xRequestedSizeBytes;
-
- #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
- {
- /* make sure the buffer is not linked */
- pxReturn->pxNextBuffer = NULL;
- }
- #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
- }
- }
- else
- {
- /* A descriptor is being returned without an associated buffer being
- * allocated. */
- }
- }
-
- if( pxReturn == NULL )
- {
- iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
- }
- else
- {
- iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
- }
-
- return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
- BaseType_t xListItemAlreadyInFreeList;
-
- /* Ensure the buffer is returned to the list of free buffers before the
- * counting semaphore is 'given' to say a buffer is available. Release the
- * storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED
- * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
- * MEMORY. For example, heap_2 must not be used, heap_4 can be used. */
- vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
- pxNetworkBuffer->pucEthernetBuffer = NULL;
-
- taskENTER_CRITICAL();
- {
- xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
-
- if( xListItemAlreadyInFreeList == pdFALSE )
- {
- vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
- }
- }
- taskEXIT_CRITICAL();
-
- /*
- * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
- * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
- */
- if( xListItemAlreadyInFreeList == pdFALSE )
- {
- if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
- {
- iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
- }
- }
- else
- {
- iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
- }
-}
-/*-----------------------------------------------------------*/
-
-/*
- * Returns the number of free network buffers
- */
-UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
-{
- return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
-}
-/*-----------------------------------------------------------*/
-
-UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
-{
- return uxMinimumFreeNetworkBuffers;
-}
-/*-----------------------------------------------------------*/
-
-NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,
- size_t xNewSizeBytes )
-{
- size_t xOriginalLength;
- uint8_t * pucBuffer;
-
- #ifdef PIC32_USE_ETHERNET
- xOriginalLength = pxNetworkBuffer->xDataLength;
- #else
- xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
- xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
-
- if( pucBuffer == NULL )
- {
- /* In case the allocation fails, return NULL. */
- pxNetworkBuffer = NULL;
- }
- else
- {
- pxNetworkBuffer->xDataLength = xNewSizeBytes;
- if( xNewSizeBytes > xOriginalLength )
- {
- xNewSizeBytes = xOriginalLength;
- }
-
- #ifdef PIC32_USE_ETHERNET
- memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes );
- *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer;
- #else
- memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
- #endif /* #ifdef PIC32_USE_ETHERNET */
-
- vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
- pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
- }
-
- return pxNetworkBuffer;
-}
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *** ***\r
+ *** ***\r
+ *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***\r
+ *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***\r
+ *** download): ***\r
+ *** ***\r
+ *** FreeRTOS+TCP is functional and has been used in commercial products ***\r
+ *** for some time. Be aware however that we are still refining its ***\r
+ *** design, the source code does not yet quite conform to the strict ***\r
+ *** coding and style standards mandated by Real Time Engineers ltd., and ***\r
+ *** the documentation and testing is not necessarily complete. ***\r
+ *** ***\r
+ *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***\r
+ *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***\r
+ *** the sole discretion of Real Time Engineers Ltd., be offered versions ***\r
+ *** under a license other than that described below. ***\r
+ *** ***\r
+ *** ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses. The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License. If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2. Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/******************************************************************************\r
+*\r
+* See the following web page for essential buffer allocation scheme usage and\r
+* configuration details:\r
+* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html\r
+*\r
+******************************************************************************/\r
+\r
+/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR\r
+ * THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used,\r
+ * heap_4 can be used. */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+\r
+#include "NetworkConfig.h"\r
+\r
+/* The obtained network buffer must be large enough to hold a packet that might\r
+ * replace the packet that was requested to be sent. */\r
+#if ipconfigUSE_TCP == 1\r
+ #define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t )\r
+#else\r
+ #define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+/*_RB_ This is too complex not to have an explanation. */\r
+#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+ #define ASSERT_CONCAT_( a, b ) a ## b\r
+ #define ASSERT_CONCAT( a, b ) ASSERT_CONCAT_( a, b )\r
+ #define STATIC_ASSERT( e ) \\r
+ ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) }\r
+\r
+ STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );\r
+#endif\r
+\r
+/* A list of free (available) NetworkBufferDescriptor_t structures. */\r
+static List_t xFreeBuffersList;\r
+\r
+/* Some statistics about the use of buffers. */\r
+static size_t uxMinimumFreeNetworkBuffers;\r
+\r
+/* Declares the pool of NetworkBufferDescriptor_t structures that are available\r
+ * to the system. All the network buffers referenced from xFreeBuffersList exist\r
+ * in this array. The array is not accessed directly except during initialisation,\r
+ * when the xFreeBuffersList is filled (as all the buffers are free when the system\r
+ * is booted). */\r
+static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];\r
+\r
+/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the\r
+ * network buffers have a variable size: resizing may be necessary */\r
+const BaseType_t xBufferAllocFixedSize = pdFALSE;\r
+\r
+/* The semaphore used to obtain network buffers. */\r
+static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#ifdef PIC32_USE_ETHERNET\r
+\r
+ /* PIC32 specific stuff */\r
+ /* */\r
+\r
+ /* MAC packet acknowledgment, once MAC is done with it */\r
+ static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,\r
+ const void * param );\r
+\r
+ /* allocates a MAC packet that holds a data buffer that can be used by both: */\r
+ /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */\r
+ /* - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */\r
+ /* from the beginning of the buffer: */\r
+ /* - 4 bytes pointer to the network descriptor (FreeRTOS) */\r
+ /* - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */\r
+ /* - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */\r
+ /* */\r
+ /* NOTE: segLoadLen should NOT include: */\r
+ /* - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */\r
+ /* - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */\r
+ /* These are added by the MAC packet allocation! */\r
+ /* */\r
+ static uint8_t * PIC32_PktAlloc( uint16_t pktLen,\r
+ uint16_t segLoadLen,\r
+ TCPIP_MAC_PACKET_ACK_FUNC ackF,\r
+ TCPIP_MAC_PACKET ** pPtrPkt )\r
+ {\r
+ uint8_t * pBuff = 0;\r
+\r
+ /* allocate standard packet */\r
+ TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 );\r
+\r
+ /* set the MAC packet pointer in the packet */\r
+ if( pPkt != 0 )\r
+ {\r
+ pBuff = pPkt->pDSeg->segLoad;\r
+ TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET );\r
+ configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+ *ppkt = pPkt; /* store the packet it comes from */\r
+ pPkt->ackFunc = ackF;\r
+ pPkt->ackParam = 0;\r
+ }\r
+\r
+ if( pPtrPkt != 0 )\r
+ {\r
+ *pPtrPkt = pPkt;\r
+ }\r
+\r
+ return pBuff;\r
+ }\r
+\r
+\r
+\r
+ /* standard PIC32 MAC allocation function for a MAC packet */\r
+ /* this packet saves room for the FreeRTOS network descriptor */\r
+ /* at the beginning of the data buffer */\r
+ /* see NetworkBufferAllocate */\r
+ /* Note: flags parameter is ignored since that's used in the Harmony stack only */\r
+ TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
+ uint16_t segLoadLen,\r
+ TCPIP_MAC_PACKET_FLAGS flags )\r
+ {\r
+ TCPIP_MAC_PACKET * pPkt;\r
+\r
+ PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt );\r
+\r
+ return pPkt;\r
+ }\r
+\r
+ /* standard PIC32 MAC packet acknowledgment */\r
+ /* function called once MAC is done with it */\r
+ static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,\r
+ const void * param )\r
+ {\r
+ configASSERT( ( pPkt != 0 ) );\r
+\r
+ TCPIP_PKT_PacketFree( pPkt );\r
+\r
+ return false;\r
+ }\r
+\r
+ /* associates the current MAC packet with a network descriptor */\r
+ /* mainly for RX packet */\r
+ void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
+ NetworkBufferDescriptor_t * pxBufferDescriptor,\r
+ size_t pktLength )\r
+ {\r
+ uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad;\r
+\r
+ pxBufferDescriptor->pucEthernetBuffer = pPktBuff;\r
+ pxBufferDescriptor->xDataLength = pktLength;\r
+\r
+ /* make sure this is a properly allocated packet */\r
+ TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET );\r
+ configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+\r
+ if( *ppkt != pRxPkt )\r
+ {\r
+ configASSERT( false );\r
+ }\r
+\r
+ /* set the proper descriptor info */\r
+ NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING );\r
+ configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+ *ppDcpt = pxBufferDescriptor;\r
+ }\r
+\r
+ /* debug functionality */\r
+ void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt )\r
+ {\r
+ TCPIP_PKT_PacketFree( pPkt );\r
+ configASSERT( false );\r
+ }\r
+\r
+ /* FreeRTOS allocation functions */\r
+\r
+ /* allocates a buffer that can be used by both: */\r
+ /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */\r
+ /* - the Harmony MAC driver: TCPIP_MAC_PACKET */\r
+ /* See PIC32_PktAlloc for details */\r
+ /* */\r
+ /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */\r
+ /* or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */\r
+ /* These are added by the MAC packet allocation! */\r
+ /* */\r
+ uint8_t * NetworkBufferAllocate( size_t reqLength )\r
+ {\r
+ return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 );\r
+ }\r
+\r
+ /* deallocates a network buffer previously allocated */\r
+ /* with NetworkBufferAllocate */\r
+ void NetworkBufferFree( uint8_t * pNetworkBuffer )\r
+ {\r
+ if( pNetworkBuffer != 0 )\r
+ {\r
+ TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
+ configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+ TCPIP_MAC_PACKET * pPkt = *ppkt;\r
+ configASSERT( ( pPkt != 0 ) );\r
+\r
+ if( pPkt->ackFunc != 0 )\r
+ {\r
+ ( *pPkt->ackFunc )( pPkt, pPkt->ackParam );\r
+ }\r
+ else\r
+ { /* ??? */\r
+ PIC32_MacPacketOrphan( pPkt );\r
+ }\r
+ }\r
+ }\r
+\r
+#endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkBuffersInitialise( void )\r
+{\r
+ BaseType_t xReturn, x;\r
+\r
+ /* Only initialise the buffers and their associated kernel objects if they\r
+ * have not been initialised before. */\r
+ if( xNetworkBufferSemaphore == NULL )\r
+ {\r
+ xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );\r
+ configASSERT( xNetworkBufferSemaphore );\r
+\r
+ if( xNetworkBufferSemaphore != NULL )\r
+ {\r
+ #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
+ {\r
+ vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );\r
+ }\r
+ #endif /* configQUEUE_REGISTRY_SIZE */\r
+\r
+ /* If the trace recorder code is included name the semaphore for viewing\r
+ * in FreeRTOS+Trace. */\r
+ #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )\r
+ {\r
+ extern QueueHandle_t xNetworkEventQueue;\r
+ vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );\r
+ vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );\r
+ }\r
+ #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */\r
+\r
+ vListInitialise( &xFreeBuffersList );\r
+\r
+ /* Initialise all the network buffers. No storage is allocated to\r
+ * the buffers yet. */\r
+ for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )\r
+ {\r
+ /* Initialise and set the owner of the buffer list items. */\r
+ xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;\r
+ vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+ listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );\r
+\r
+ /* Currently, all buffers are available for use. */\r
+ vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+ }\r
+\r
+ uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;\r
+ }\r
+ }\r
+\r
+ if( xNetworkBufferSemaphore == NULL )\r
+ {\r
+ xReturn = pdFAIL;\r
+ }\r
+ else\r
+ {\r
+ xReturn = pdPASS;\r
+ }\r
+\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )\r
+{\r
+ uint8_t * pucEthernetBuffer;\r
+ size_t xSize = *pxRequestedSizeBytes;\r
+\r
+ if( xSize < baMINIMAL_BUFFER_SIZE )\r
+ {\r
+ /* Buffers must be at least large enough to hold a TCP-packet with\r
+ * headers, or an ARP packet, in case TCP is not included. */\r
+ xSize = baMINIMAL_BUFFER_SIZE;\r
+ }\r
+\r
+ /* Round up xSize to the nearest multiple of N bytes,\r
+ * where N equals 'sizeof( size_t )'. */\r
+ if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+ {\r
+ xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+ }\r
+\r
+ *pxRequestedSizeBytes = xSize;\r
+\r
+ /* Allocate a buffer large enough to store the requested Ethernet frame size\r
+ * and a pointer to a network buffer structure (hence the addition of\r
+ * ipBUFFER_PADDING bytes). */\r
+\r
+ #ifdef PIC32_USE_ETHERNET\r
+ pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );\r
+ #else\r
+ pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+ configASSERT( pucEthernetBuffer );\r
+\r
+ if( pucEthernetBuffer != NULL )\r
+ {\r
+ /* Enough space is left at the start of the buffer to place a pointer to\r
+ * the network buffer structure that references this Ethernet buffer.\r
+ * Return a pointer to the start of the Ethernet buffer itself. */\r
+ #ifndef PIC32_USE_ETHERNET\r
+ pucEthernetBuffer += ipBUFFER_PADDING;\r
+ #endif /* #ifndef PIC32_USE_ETHERNET */\r
+ }\r
+\r
+ return pucEthernetBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer )\r
+{\r
+ /* There is space before the Ethernet buffer in which a pointer to the\r
+ * network buffer that references this Ethernet buffer is stored. Remove the\r
+ * space before freeing the buffer. */\r
+ #ifdef PIC32_USE_ETHERNET\r
+ NetworkBufferFree( pucEthernetBuffer );\r
+ #else\r
+ if( pucEthernetBuffer != NULL )\r
+ {\r
+ pucEthernetBuffer -= ipBUFFER_PADDING;\r
+ vPortFree( ( void * ) pucEthernetBuffer );\r
+ }\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,\r
+ TickType_t xBlockTimeTicks )\r
+{\r
+ NetworkBufferDescriptor_t * pxReturn = NULL;\r
+ size_t uxCount;\r
+\r
+ if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )\r
+ {\r
+ /* ARP packets can replace application packets, so the storage must be\r
+ * at least large enough to hold an ARP. */\r
+ xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;\r
+ }\r
+\r
+ #ifdef PIC32_USE_ETHERNET\r
+ if( xRequestedSizeBytes != 0u )\r
+ {\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+ xRequestedSizeBytes += 2u;\r
+\r
+ if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+ {\r
+ xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+ }\r
+ #ifdef PIC32_USE_ETHERNET\r
+ }\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+ /* If there is a semaphore available, there is a network buffer available. */\r
+ if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
+ {\r
+ /* Protect the structure as it is accessed from tasks and interrupts. */\r
+ taskENTER_CRITICAL();\r
+ {\r
+ pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
+ uxListRemove( &( pxReturn->xBufferListItem ) );\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ /* Reading UBaseType_t, no critical section needed. */\r
+ uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+\r
+ if( uxMinimumFreeNetworkBuffers > uxCount )\r
+ {\r
+ uxMinimumFreeNetworkBuffers = uxCount;\r
+ }\r
+\r
+ /* Allocate storage of exactly the requested size to the buffer. */\r
+ configASSERT( pxReturn->pucEthernetBuffer == NULL );\r
+\r
+ if( xRequestedSizeBytes > 0 )\r
+ {\r
+ /* Extra space is obtained so a pointer to the network buffer can\r
+ * be stored at the beginning of the buffer. */\r
+\r
+ #ifdef PIC32_USE_ETHERNET\r
+ pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );\r
+ #else\r
+ pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+ if( pxReturn->pucEthernetBuffer == NULL )\r
+ {\r
+ /* The attempt to allocate storage for the buffer payload failed,\r
+ * so the network buffer structure cannot be used and must be\r
+ * released. */\r
+ vReleaseNetworkBufferAndDescriptor( pxReturn );\r
+ pxReturn = NULL;\r
+ }\r
+ else\r
+ {\r
+ /* Store a pointer to the network buffer structure in the\r
+ * buffer storage area, then move the buffer pointer on past the\r
+ * stored pointer so the pointer value is not overwritten by the\r
+ * application when the buffer is used. */\r
+ #ifdef PIC32_USE_ETHERNET\r
+ *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn;\r
+ #else\r
+ *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;\r
+ pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+ /* Store the actual size of the allocated buffer, which may be\r
+ * greater than the original requested size. */\r
+ pxReturn->xDataLength = xRequestedSizeBytes;\r
+\r
+ #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+ {\r
+ /* make sure the buffer is not linked */\r
+ pxReturn->pxNextBuffer = NULL;\r
+ }\r
+ #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* A descriptor is being returned without an associated buffer being\r
+ * allocated. */\r
+ }\r
+ }\r
+\r
+ if( pxReturn == NULL )\r
+ {\r
+ iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
+ }\r
+ else\r
+ {\r
+ iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
+ }\r
+\r
+ return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+ BaseType_t xListItemAlreadyInFreeList;\r
+\r
+ /* Ensure the buffer is returned to the list of free buffers before the\r
+ * counting semaphore is 'given' to say a buffer is available. Release the\r
+ * storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED\r
+ * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP\r
+ * MEMORY. For example, heap_2 must not be used, heap_4 can be used. */\r
+ vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+ pxNetworkBuffer->pucEthernetBuffer = NULL;\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+\r
+ if( xListItemAlreadyInFreeList == pdFALSE )\r
+ {\r
+ vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ /*\r
+ * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.\r
+ * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.\r
+ */\r
+ if( xListItemAlreadyInFreeList == pdFALSE )\r
+ {\r
+ if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )\r
+ {\r
+ iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Returns the number of free network buffers\r
+ */\r
+UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )\r
+{\r
+ return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxGetMinimumFreeNetworkBuffers( void )\r
+{\r
+ return uxMinimumFreeNetworkBuffers;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,\r
+ size_t xNewSizeBytes )\r
+{\r
+ size_t xOriginalLength;\r
+ uint8_t * pucBuffer;\r
+\r
+ #ifdef PIC32_USE_ETHERNET\r
+ xOriginalLength = pxNetworkBuffer->xDataLength;\r
+ #else\r
+ xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;\r
+ xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+ \r
+ pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );\r
+\r
+ if( pucBuffer == NULL )\r
+ {\r
+ /* In case the allocation fails, return NULL. */\r
+ pxNetworkBuffer = NULL;\r
+ }\r
+ else\r
+ {\r
+ pxNetworkBuffer->xDataLength = xNewSizeBytes;\r
+ if( xNewSizeBytes > xOriginalLength )\r
+ {\r
+ xNewSizeBytes = xOriginalLength;\r
+ }\r
+\r
+ #ifdef PIC32_USE_ETHERNET\r
+ memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes );\r
+ *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer;\r
+ #else\r
+ memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );\r
+ #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+ vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+ pxNetworkBuffer->pucEthernetBuffer = pucBuffer;\r
+ }\r
+\r
+ return pxNetworkBuffer;\r
+}\r
-/*******************************************************************************
-* Network Interface file
-*
-* Summary:
-* Network Interface file for FreeRTOS-Plus-TCP stack
-*
-* Description:
-* - Interfaces PIC32 to the FreeRTOS TCP/IP stack
-*******************************************************************************/
-
-/*******************************************************************************
-* File Name: pic32_NetworkInterface.c
-* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
-*
-* 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
-*******************************************************************************/
-#include <sys/kmem.h>
-
-#include "FreeRTOS.h"
-#include "semphr.h"
-#include "event_groups.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-
-
-#include "NetworkInterface.h"
-#include "NetworkConfig.h"
-
-#include "peripheral/eth/plib_eth.h"
-
-#include "system_config.h"
-#include "system/console/sys_console.h"
-#include "system/debug/sys_debug.h"
-#include "system/command/sys_command.h"
-
-#include "driver/ethmac/drv_ethmac.h"
-#include "driver/miim/drv_miim.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-#include "tcpip/src/link_list.h"
-
-#ifdef PIC32_USE_ETHERNET
-
- /* local definitions and data */
-
- /* debug messages */
- #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )
- #define PIC32_MAC_DbgPrint( format, ... ) SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )
- #else
- #define PIC32_MAC_DbgPrint( format, ... )
- #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */
-
- typedef enum
- {
- PIC32_MAC_EVENT_INIT_NONE = 0x000, /* no event/invalid */
-
- PIC32_MAC_EVENT_INIT_DONE = 0x001, /* initialization done event */
- PIC32_MAC_EVENT_TIMEOUT = 0x002, /* periodic timeout event */
- PIC32_MAC_EVENT_IF_PENDING = 0x004, /* an interface event signal: RX, TX, errors. etc. */
- } PIC32_MAC_EVENT_TYPE;
-
- typedef enum
- {
- eMACInit, /* Must initialise MAC. */
- eMACPass, /* Initialisation was successful. */
- eMACFailed, /* Initialisation failed. */
- } eMAC_INIT_STATUS_TYPE;
-
- static TCPIP_STACK_HEAP_HANDLE macHeapHandle;
-
- static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */
-
- static SYS_MODULE_OBJ macObjHandle; /* the MAC object instance, obtained at initialization */
- static TCPIP_MAC_HANDLE macCliHandle; /* client handle */
- static volatile SYS_STATUS macObjStatus; /* current MAC status */
-
- static TaskHandle_t macTaskHandle;
-
- static TimerHandle_t macTmrHandle;
-
- static bool macLinkStatus; /* true if link is ON */
-
- static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
-
- /* local prototypes */
- static bool StartInitMac( void );
- static void StartInitCleanup( void );
-
- static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );
-
- static bool MacSyncFunction( void * synchHandle,
- TCPIP_MAC_SYNCH_REQUEST req );
-
- /* the PIC32 MAC task function */
- static void MacHandlerTask( void * params );
-
- /* MAC interrupt event function */
- static void MAC_EventFunction( TCPIP_MAC_EVENT event,
- const void * eventParam );
-
- /* timer callback for link maintenance, etc; */
- static void MacTmrCallback( TimerHandle_t xTimer );
-
- /* MAC RX packets functions */
- static void MacRxPackets( void );
- static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );
-
-
- /* memory allocation mapping to FreeRTOS */
- static void * _malloc( size_t nBytes )
- {
- return pvPortMalloc( nBytes );
- }
-
- /*-----------------------------------------------------------*/
-
- static void * _calloc( size_t nElems,
- size_t elemSize )
- {
- size_t nBytes = nElems * elemSize;
-
- void * ptr = pvPortMalloc( nBytes );
-
- if( ptr != 0 )
- {
- memset( ptr, 0, nBytes );
- }
-
- return ptr;
- }
-
- /*-----------------------------------------------------------*/
-
- static void _free( void * pBuff )
- {
- vPortFree( pBuff );
- }
-
- /* extern references */
- /* */
- /* use the configuration data from the system_init.c */
- extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];
-
- /* BufferAllocation_2.c:: packet allocation function */
- extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
- uint16_t segLoadLen,
- TCPIP_MAC_PACKET_FLAGS flags );
-
- extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
- NetworkBufferDescriptor_t * pxBufferDescriptor,
- size_t pktLength );
- extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );
-
- /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */
- /* we build it here! */
-
- /* make sure we're running with external heap! Redirect to FreeRTOS. */
- #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )
- #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"
- #endif
-
- static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =
- {
- .heapType = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,
- .heapFlags = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,
- .heapUsage = TCPIP_STACK_HEAP_USE_DEFAULT,
- .malloc_fnc = _malloc,
- .calloc_fnc = _calloc,
- .free_fnc = _free,
- };
-
- #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
- static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
- int argc,
- char ** argv );
- static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
- int argc,
- char ** argv );
- static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,
- int argc,
- char ** argv );
-
- static const SYS_CMD_DESCRIPTOR macCmdTbl[] =
- {
- { "macinfo", _Command_MacInfo, ": Check MAC statistics" },
- { "netinfo", _Command_NetInfo, ": Net info" },
- { "version", _Command_Version, ": Version info" },
- };
- #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-
-
- /* FreeRTOS implementation functions */
- BaseType_t xNetworkInterfaceInitialise( void )
- {
- BaseType_t xResult;
-
- if( xMacInitStatus == eMACInit )
- {
- /* This is the first time this function is called. */
- if( StartInitMac() != false )
- {
- /* Indicate that the MAC initialisation succeeded. */
- xMacInitStatus = eMACPass;
- }
- else
- {
- xMacInitStatus = eMACFailed;
- }
- }
-
- if( xMacInitStatus == eMACPass )
- {
- xResult = xGetPhyLinkStatus();
- }
- else
- {
- xResult = pdFAIL;
- }
-
- PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );
-
- return xResult;
- }
-
-
- /*-----------------------------------------------------------*/
-
- BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
- BaseType_t xReleaseAfterSend )
- {
- TCPIP_MAC_RES macRes;
- TCPIP_MAC_PACKET * pTxPkt;
-
- BaseType_t retRes = pdFALSE;
-
-
- if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
- {
- TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
- configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
- pTxPkt = *ppkt;
- configASSERT( pTxPkt != 0 );
-
- /* prepare the packet for transmission */
- /* set the correct data length: */
- configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );
- pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;
- pTxPkt->next = 0; /* unlink it */
- macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );
-
- if( macRes >= 0 )
- {
- retRes = pdTRUE;
- pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */
- iptraceNETWORK_INTERFACE_TRANSMIT();
- }
-
- /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */
-
- /* The buffer has been sent so can be released. */
- if( xReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
- }
-
- return retRes;
- }
-
-
- /************************************* Section: helper functions ************************************************** */
- /* */
-
- void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )
- {
- #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
- PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );
- #else
- #error "MAC Address: not supported architecture!"
- #endif
- }
-
-
- /*-----------------------------------------------------------*/
-
- const void * const PIC32_GetMacConfigData( void )
- {
- #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
- extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;
-
- return &tcpipMACPIC32INTInitData;
- #else
- #error "MAC Address: not supported architecture!"
- #endif
- }
-
- /************************************* Section: worker code ************************************************** */
- /* */
-
-
- static bool StartInitMac( void )
- {
- TCPIP_MAC_MODULE_CTRL macCtrl;
- SYS_MODULE_INIT moduleInit;
- EventBits_t evBits;
-
-
- /* perform some initialization of all variables so that we can cleanup what failed */
- /* if something failed, the routine will be called again and again by FreeRTOS! */
- macHeapHandle = 0;
- macObjHandle = 0;
- macCliHandle = 0;
- macTmrHandle = 0;
- macTaskHandle = 0;
- macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */
- macObjStatus = SYS_STATUS_UNINITIALIZED;
- macLinkStatus = false;
-
- int netUpFail = 0;
-
- while( true )
- {
- /* start the allocator */
- macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );
-
- if( macHeapHandle == 0 )
- {
- netUpFail = 1;
- break;
- }
-
- if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )
- {
- netUpFail = 2;
- break;
- }
-
- moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;
-
- /* Initialize the MAC. MAC address is defined to 0x000000000000 in
- * FreeRTOSConfig.h and therefore it will be initialized to the
- * factory programmed MAC address. */
- SetMacCtrl( &macCtrl );
- /* Set the mac address in the FreeRTOS+TCP stack. */
- FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );
-
- TCPIP_MAC_INIT macInit =
- {
- .moduleInit = { moduleInit.value },
- .macControl = &macCtrl,
- .moduleData = PIC32_GetMacConfigData(),
- };
-
- macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );
-
- if( macObjHandle == SYS_MODULE_OBJ_INVALID )
- {
- macObjHandle = 0;
- netUpFail = 4;
- break;
- }
-
- /* open the MAC */
- macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );
-
- if( macCliHandle == DRV_HANDLE_INVALID )
- {
- macCliHandle = 0;
- netUpFail = 5;
- break;
- }
-
- if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )
- {
- netUpFail = 6;
- break;
- }
-
- /* completed the MAC initialization */
- /* continue the initialization */
- macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );
-
- if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )
- {
- netUpFail = 8;
- break;
- }
-
- /* spawn the PIC32 MAC task function */
- /* and wait for its event signal */
- macObjStatus = SYS_STATUS_BUSY;
-
- if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )
- { /* failed */
- netUpFail = 9;
- break;
- }
-
- xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );
-
- if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )
- { /* timed out */
- netUpFail = 10;
- break;
- }
-
- if( macObjStatus != SYS_STATUS_READY )
- { /* failed somehow ??? */
- netUpFail = 11;
- break;
- }
-
- netUpFail = 0;
- break;
- }
-
- if( netUpFail == 0 )
- {
- PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );
-
- #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
- /* create command group */
- if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )
- {
- PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );
- }
- #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-
- return true;
- }
- else
- {
- StartInitCleanup();
- PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );
-
- return false;
- }
- }
-
- /*-----------------------------------------------------------*/
-
- static void StartInitCleanup( void )
- {
- if( macHeapHandle != 0 )
- {
- TCPIP_HEAP_Delete( macHeapHandle );
- macHeapHandle = 0;
- }
-
- if( macObjHandle != 0 )
- {
- ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );
- macObjHandle = 0;
- }
-
- if( macTmrHandle != 0 )
- {
- xTimerDelete( macTmrHandle, portMAX_DELAY );
- macTmrHandle = 0;
- }
-
- if( macTaskHandle != 0 )
- {
- vTaskDelete( macTaskHandle );
- macTaskHandle = 0;
- }
- }
-
- /*-----------------------------------------------------------*/
-
- static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )
- {
- TCPIP_MAC_ADDR macAdd;
- uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* not set MAC address */
-
- pMacCtrl->nIfs = 1;
-
- pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;
- pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;
- pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;
- pMacCtrl->memH = macHeapHandle;
-
-
- pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;
- pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;
- pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;
-
- pMacCtrl->synchF = MacSyncFunction;
-
- pMacCtrl->eventF = MAC_EventFunction;
- pMacCtrl->eventParam = 0;
-
- pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;
- pMacCtrl->netIx = 0;
- pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;
- pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;
-
- macAdd.v[ 0 ] = configMAC_ADDR0;
- macAdd.v[ 1 ] = configMAC_ADDR1;
- macAdd.v[ 2 ] = configMAC_ADDR2;
- macAdd.v[ 3 ] = configMAC_ADDR3;
- macAdd.v[ 4 ] = configMAC_ADDR4;
- macAdd.v[ 5 ] = configMAC_ADDR5;
-
- if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )
- { /* if unspecified we use the factory pre-programmed address */
- PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );
- }
- else
- { /* use the config suggested one */
- memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );
- }
- }
-
- /*-----------------------------------------------------------*/
-
- static bool MacSyncFunction( void * synchHandle,
- TCPIP_MAC_SYNCH_REQUEST req )
- {
- switch( req )
- {
- case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:
- vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );
-
- return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;
-
- case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:
- vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );
- *( SemaphoreHandle_t * ) synchHandle = NULL;
-
- return true;
-
- case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:
-
- return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;
-
- case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:
-
- return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;
-
- case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:
- vTaskSuspendAll();
-
- return true;
-
- case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:
- xTaskResumeAll();
-
- return true;
-
- default:
-
- return false;
- }
- }
-
-
- /*-----------------------------------------------------------*/
-
- static void MacHandlerTask( void * params )
- {
- EventBits_t evBits;
-
- /* perform the MAC initialization */
- while( macObjStatus == SYS_STATUS_BUSY )
- {
- /* process the underlying MAC module tasks */
- ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
-
- SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );
-
- if( macStatus == SYS_STATUS_BUSY )
- { /* still pending */
- vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );
- }
- else
- { /* completed ...somehow */
- macObjStatus = macStatus;
-
- xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );
-
- if( macStatus != SYS_STATUS_READY )
- { /* failed miserably */
- vTaskDelete( 0 );
- }
-
- /* done, up and running */
- }
- }
-
- while( true )
- {
- xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );
-
- if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )
- { /* timeout occurred... */
- ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
- bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */
-
- if( macLinkStatus != linkCurr )
- { /* link status changed; some event could ve fired here if needed */
- PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );
- macLinkStatus = linkCurr;
- }
- }
-
- if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )
- { /* IF events signal */
- TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );
-
- if( activeEvents != TCPIP_MAC_EV_NONE )
- {
- /* acknowledge the events */
- ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );
-
- /* check for RX */
- if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )
- { /* RX packets available */
- MacRxPackets();
- }
-
- /* call the driver process function; */
- /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */
- ( macObject->TCPIP_MAC_Process )( macCliHandle );
- }
- }
-
- /* do what you have to do and then wait for another event... */
- }
- }
-
- /*-----------------------------------------------------------*/
-
- static void MacTmrCallback( TimerHandle_t xTimer )
- {
- xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );
- }
-
- /* MAC interrupt event function */
- /* MAC signals an event, probably from within ISR */
- /* we care just for RX related events */
- static void MAC_EventFunction( TCPIP_MAC_EVENT event,
- const void * eventParam )
- {
- BaseType_t xHigherPriorityTaskWoken;
-
- if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )
- {
- xHigherPriorityTaskWoken = pdFALSE;
- xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );
-
- if( xHigherPriorityTaskWoken )
- {
- portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
- }
- }
- }
-
- /*-----------------------------------------------------------*/
-
- BaseType_t xGetPhyLinkStatus( void )
- {
- return macLinkStatus == true ? pdPASS : pdFAIL;
- }
-
-
- /* receive packets from the MAC driver */
- static void MacRxPackets( void )
- {
- TCPIP_MAC_PACKET * pRxPkt;
-
- /* get all the new MAC packets */
- while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )
- {
- MacProcessRxPacket( pRxPkt );
- }
- }
-
- /*-----------------------------------------------------------*/
-
- static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )
- {
- bool pktSuccess, pktLost;
- size_t pktLength;
- TCPIP_MAC_DATA_SEGMENT * pSeg;
- uint8_t * pPktBuff;
- NetworkBufferDescriptor_t * pxBufferDescriptor;
- IPStackEvent_t xRxEvent;
-
- pxBufferDescriptor = 0;
- pktSuccess = pktLost = false;
-
- while( true )
- {
- pktLength = 0;
- int nSegs = 0;
- pSeg = pRxPkt->pDSeg;
- pPktBuff = pSeg->segLoad;
-
- /* calculate the packet size */
- do
- {
- pktLength += pSeg->segLen;
- pSeg = pSeg->next;
- nSegs++;
- } while( pSeg != 0 );
-
- if( nSegs > 1 )
- { /* no support in FreeRTOS for multi segment packets! */
- break;
- }
-
- /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */
- /* but FreeRTOS needs the whole frame! */
- pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );
-
- if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )
- {
- break;
- }
-
- /* get the network descriptor (no data buffer) to hold this packet */
- pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );
-
- if( pxBufferDescriptor == 0 )
- {
- pktLost = true;
- break;
- }
-
- PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );
-
- xRxEvent.eEventType = eNetworkRxEvent;
- xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
- /* Send the data to the TCP/IP stack */
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
- { /* failed */
- pktLost = true;
- }
- else
- { /* success */
- pktSuccess = true;
- iptraceNETWORK_INTERFACE_RECEIVE();
- }
-
- break;
- }
-
- if( !pktSuccess )
- { /* smth went wrong; nothing sent to the */
- if( pxBufferDescriptor != 0 )
- {
- pxBufferDescriptor->pucEthernetBuffer = 0;
- vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
- }
-
- if( pktLost )
- {
- iptraceETHERNET_RX_EVENT_LOST();
- }
-
- /* acknowledge the packet to the MAC driver */
- if( pRxPkt->ackFunc )
- {
- ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );
- }
- else
- {
- PIC32_MacPacketOrphan( pRxPkt );
- }
- }
- }
-
- #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
- /* */
- static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
- int argc,
- char ** argv )
- {
- TCPIP_MAC_RES macRes;
- TCPIP_MAC_RX_STATISTICS rxStatistics;
- TCPIP_MAC_TX_STATISTICS txStatistics;
- TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];
- TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;
- int jx, hwEntries;
- char entryName[ sizeof( pRegEntry->registerName ) + 1 ];
-
- const void * cmdIoParam = pCmdIO->cmdIoParam;
-
- if( argc != 1 )
- {
- ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );
- ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );
-
- return false;
- }
-
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );
- macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );
-
- if( macRes == TCPIP_MAC_RES_OK )
- {
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",
- rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",
- txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );
- }
- else
- {
- ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
- }
-
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );
- macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );
-
- if( macRes == TCPIP_MAC_RES_OK )
- {
- entryName[ sizeof( entryName ) - 1 ] = 0;
-
- for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )
- {
- strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );
- }
- }
- else
- {
- ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
- }
-
- return true;
- }
-
- /*-----------------------------------------------------------*/
-
- static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
- int argc,
- char ** argv )
- {
- const void * cmdIoParam = pCmdIO->cmdIoParam;
-
- union
- {
- uint32_t ul;
- uint8_t b[ 4 ];
- }
- sUl;
-
- sUl.ul = FreeRTOS_GetIPAddress();
-
- bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;
-
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );
- ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );
-
- return true;
- }
-
-#include "aws_application_version.h"
-
-static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)
-{
- configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n", xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );
- return 0;
-}
-
- #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-#endif /* #ifdef PIC32_USE_ETHERNET */
+/*******************************************************************************\r
+* Network Interface file\r
+*\r
+* Summary:\r
+* Network Interface file for FreeRTOS-Plus-TCP stack\r
+*\r
+* Description:\r
+* - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
+*******************************************************************************/\r
+\r
+/*******************************************************************************\r
+* File Name: pic32_NetworkInterface.c\r
+* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\r
+*\r
+* Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+* this software and associated documentation files (the "Software"), to deal in\r
+* the Software without restriction, including without limitation the rights to\r
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\r
+* of the Software, and to permit persons to whom the Software is furnished to do\r
+* so, subject to the following conditions:\r
+* The above copyright notice and this permission notice shall be included in all\r
+* copies or substantial portions of the Software.\r
+*\r
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+* SOFTWARE\r
+*******************************************************************************/\r
+#include <sys/kmem.h>\r
+\r
+#include "FreeRTOS.h"\r
+#include "semphr.h"\r
+#include "event_groups.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkConfig.h"\r
+\r
+#include "peripheral/eth/plib_eth.h"\r
+\r
+#include "system_config.h"\r
+#include "system/console/sys_console.h"\r
+#include "system/debug/sys_debug.h"\r
+#include "system/command/sys_command.h"\r
+\r
+#include "driver/ethmac/drv_ethmac.h"\r
+#include "driver/miim/drv_miim.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+#include "tcpip/src/link_list.h"\r
+\r
+#ifdef PIC32_USE_ETHERNET\r
+\r
+ /* local definitions and data */\r
+\r
+ /* debug messages */\r
+ #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )\r
+ #define PIC32_MAC_DbgPrint( format, ... ) SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )\r
+ #else\r
+ #define PIC32_MAC_DbgPrint( format, ... )\r
+ #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */\r
+\r
+ typedef enum\r
+ {\r
+ PIC32_MAC_EVENT_INIT_NONE = 0x000, /* no event/invalid */\r
+\r
+ PIC32_MAC_EVENT_INIT_DONE = 0x001, /* initialization done event */\r
+ PIC32_MAC_EVENT_TIMEOUT = 0x002, /* periodic timeout event */\r
+ PIC32_MAC_EVENT_IF_PENDING = 0x004, /* an interface event signal: RX, TX, errors. etc. */\r
+ } PIC32_MAC_EVENT_TYPE;\r
+\r
+ typedef enum\r
+ {\r
+ eMACInit, /* Must initialise MAC. */\r
+ eMACPass, /* Initialisation was successful. */\r
+ eMACFailed, /* Initialisation failed. */\r
+ } eMAC_INIT_STATUS_TYPE;\r
+\r
+ static TCPIP_STACK_HEAP_HANDLE macHeapHandle;\r
+\r
+ static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */\r
+\r
+ static SYS_MODULE_OBJ macObjHandle; /* the MAC object instance, obtained at initialization */\r
+ static TCPIP_MAC_HANDLE macCliHandle; /* client handle */\r
+ static volatile SYS_STATUS macObjStatus; /* current MAC status */\r
+\r
+ static TaskHandle_t macTaskHandle;\r
+\r
+ static TimerHandle_t macTmrHandle;\r
+\r
+ static bool macLinkStatus; /* true if link is ON */\r
+\r
+ static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
+\r
+ /* local prototypes */\r
+ static bool StartInitMac( void );\r
+ static void StartInitCleanup( void );\r
+\r
+ static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );\r
+\r
+ static bool MacSyncFunction( void * synchHandle,\r
+ TCPIP_MAC_SYNCH_REQUEST req );\r
+\r
+ /* the PIC32 MAC task function */\r
+ static void MacHandlerTask( void * params );\r
+\r
+ /* MAC interrupt event function */\r
+ static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
+ const void * eventParam );\r
+\r
+ /* timer callback for link maintenance, etc; */\r
+ static void MacTmrCallback( TimerHandle_t xTimer );\r
+\r
+ /* MAC RX packets functions */\r
+ static void MacRxPackets( void );\r
+ static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );\r
+\r
+\r
+ /* memory allocation mapping to FreeRTOS */\r
+ static void * _malloc( size_t nBytes )\r
+ {\r
+ return pvPortMalloc( nBytes );\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void * _calloc( size_t nElems,\r
+ size_t elemSize )\r
+ {\r
+ size_t nBytes = nElems * elemSize;\r
+\r
+ void * ptr = pvPortMalloc( nBytes );\r
+\r
+ if( ptr != 0 )\r
+ {\r
+ memset( ptr, 0, nBytes );\r
+ }\r
+\r
+ return ptr;\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void _free( void * pBuff )\r
+ {\r
+ vPortFree( pBuff );\r
+ }\r
+\r
+ /* extern references */\r
+ /* */\r
+ /* use the configuration data from the system_init.c */\r
+ extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];\r
+\r
+ /* BufferAllocation_2.c:: packet allocation function */\r
+ extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
+ uint16_t segLoadLen,\r
+ TCPIP_MAC_PACKET_FLAGS flags );\r
+\r
+ extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
+ NetworkBufferDescriptor_t * pxBufferDescriptor,\r
+ size_t pktLength );\r
+ extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );\r
+\r
+ /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */\r
+ /* we build it here! */\r
+\r
+ /* make sure we're running with external heap! Redirect to FreeRTOS. */\r
+ #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )\r
+ #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"\r
+ #endif\r
+\r
+ static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =\r
+ {\r
+ .heapType = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,\r
+ .heapFlags = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,\r
+ .heapUsage = TCPIP_STACK_HEAP_USE_DEFAULT,\r
+ .malloc_fnc = _malloc,\r
+ .calloc_fnc = _calloc,\r
+ .free_fnc = _free,\r
+ };\r
+\r
+ #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+ static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+ int argc,\r
+ char ** argv );\r
+ static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+ int argc,\r
+ char ** argv );\r
+ static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+ int argc,\r
+ char ** argv );\r
+\r
+ static const SYS_CMD_DESCRIPTOR macCmdTbl[] =\r
+ {\r
+ { "macinfo", _Command_MacInfo, ": Check MAC statistics" },\r
+ { "netinfo", _Command_NetInfo, ": Net info" },\r
+ { "version", _Command_Version, ": Version info" },\r
+ };\r
+ #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+\r
+\r
+ /* FreeRTOS implementation functions */\r
+ BaseType_t xNetworkInterfaceInitialise( void )\r
+ {\r
+ BaseType_t xResult;\r
+\r
+ if( xMacInitStatus == eMACInit )\r
+ {\r
+ /* This is the first time this function is called. */\r
+ if( StartInitMac() != false )\r
+ {\r
+ /* Indicate that the MAC initialisation succeeded. */\r
+ xMacInitStatus = eMACPass;\r
+ }\r
+ else\r
+ {\r
+ xMacInitStatus = eMACFailed;\r
+ }\r
+ }\r
+\r
+ if( xMacInitStatus == eMACPass )\r
+ {\r
+ xResult = xGetPhyLinkStatus();\r
+ }\r
+ else\r
+ {\r
+ xResult = pdFAIL;\r
+ }\r
+\r
+ PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );\r
+\r
+ return xResult;\r
+ }\r
+\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+ BaseType_t xReleaseAfterSend )\r
+ {\r
+ TCPIP_MAC_RES macRes;\r
+ TCPIP_MAC_PACKET * pTxPkt;\r
+\r
+ BaseType_t retRes = pdFALSE;\r
+\r
+\r
+ if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
+ {\r
+ TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
+ configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+ pTxPkt = *ppkt;\r
+ configASSERT( pTxPkt != 0 );\r
+\r
+ /* prepare the packet for transmission */\r
+ /* set the correct data length: */\r
+ configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );\r
+ pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;\r
+ pTxPkt->next = 0; /* unlink it */\r
+ macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );\r
+\r
+ if( macRes >= 0 )\r
+ {\r
+ retRes = pdTRUE;\r
+ pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */\r
+ iptraceNETWORK_INTERFACE_TRANSMIT();\r
+ }\r
+\r
+ /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */\r
+\r
+ /* The buffer has been sent so can be released. */\r
+ if( xReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+ }\r
+\r
+ return retRes;\r
+ }\r
+\r
+\r
+ /************************************* Section: helper functions ************************************************** */\r
+ /* */\r
+\r
+ void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )\r
+ {\r
+ #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
+ PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );\r
+ #else\r
+ #error "MAC Address: not supported architecture!"\r
+ #endif\r
+ }\r
+\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ const void * const PIC32_GetMacConfigData( void )\r
+ {\r
+ #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
+ extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;\r
+\r
+ return &tcpipMACPIC32INTInitData;\r
+ #else\r
+ #error "MAC Address: not supported architecture!"\r
+ #endif\r
+ }\r
+\r
+ /************************************* Section: worker code ************************************************** */\r
+ /* */\r
+\r
+\r
+ static bool StartInitMac( void )\r
+ {\r
+ TCPIP_MAC_MODULE_CTRL macCtrl;\r
+ SYS_MODULE_INIT moduleInit;\r
+ EventBits_t evBits;\r
+\r
+\r
+ /* perform some initialization of all variables so that we can cleanup what failed */\r
+ /* if something failed, the routine will be called again and again by FreeRTOS! */\r
+ macHeapHandle = 0;\r
+ macObjHandle = 0;\r
+ macCliHandle = 0;\r
+ macTmrHandle = 0;\r
+ macTaskHandle = 0;\r
+ macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */\r
+ macObjStatus = SYS_STATUS_UNINITIALIZED;\r
+ macLinkStatus = false;\r
+\r
+ int netUpFail = 0;\r
+\r
+ while( true )\r
+ {\r
+ /* start the allocator */\r
+ macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );\r
+\r
+ if( macHeapHandle == 0 )\r
+ {\r
+ netUpFail = 1;\r
+ break;\r
+ }\r
+\r
+ if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )\r
+ {\r
+ netUpFail = 2;\r
+ break;\r
+ }\r
+\r
+ moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;\r
+\r
+ /* Initialize the MAC. MAC address is defined to 0x000000000000 in\r
+ * FreeRTOSConfig.h and therefore it will be initialized to the\r
+ * factory programmed MAC address. */\r
+ SetMacCtrl( &macCtrl );\r
+ /* Set the mac address in the FreeRTOS+TCP stack. */\r
+ FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );\r
+\r
+ TCPIP_MAC_INIT macInit =\r
+ {\r
+ .moduleInit = { moduleInit.value },\r
+ .macControl = &macCtrl,\r
+ .moduleData = PIC32_GetMacConfigData(),\r
+ };\r
+\r
+ macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );\r
+\r
+ if( macObjHandle == SYS_MODULE_OBJ_INVALID )\r
+ {\r
+ macObjHandle = 0;\r
+ netUpFail = 4;\r
+ break;\r
+ }\r
+\r
+ /* open the MAC */\r
+ macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );\r
+\r
+ if( macCliHandle == DRV_HANDLE_INVALID )\r
+ {\r
+ macCliHandle = 0;\r
+ netUpFail = 5;\r
+ break;\r
+ }\r
+\r
+ if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )\r
+ {\r
+ netUpFail = 6;\r
+ break;\r
+ }\r
+\r
+ /* completed the MAC initialization */\r
+ /* continue the initialization */\r
+ macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );\r
+\r
+ if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )\r
+ {\r
+ netUpFail = 8;\r
+ break;\r
+ }\r
+\r
+ /* spawn the PIC32 MAC task function */\r
+ /* and wait for its event signal */\r
+ macObjStatus = SYS_STATUS_BUSY;\r
+\r
+ if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )\r
+ { /* failed */\r
+ netUpFail = 9;\r
+ break;\r
+ }\r
+\r
+ xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );\r
+\r
+ if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )\r
+ { /* timed out */\r
+ netUpFail = 10;\r
+ break;\r
+ }\r
+\r
+ if( macObjStatus != SYS_STATUS_READY )\r
+ { /* failed somehow ??? */\r
+ netUpFail = 11;\r
+ break;\r
+ }\r
+\r
+ netUpFail = 0;\r
+ break;\r
+ }\r
+\r
+ if( netUpFail == 0 )\r
+ {\r
+ PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );\r
+\r
+ #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+ /* create command group */\r
+ if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )\r
+ {\r
+ PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );\r
+ }\r
+ #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ StartInitCleanup();\r
+ PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );\r
+\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void StartInitCleanup( void )\r
+ {\r
+ if( macHeapHandle != 0 )\r
+ {\r
+ TCPIP_HEAP_Delete( macHeapHandle );\r
+ macHeapHandle = 0;\r
+ }\r
+\r
+ if( macObjHandle != 0 )\r
+ {\r
+ ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );\r
+ macObjHandle = 0;\r
+ }\r
+\r
+ if( macTmrHandle != 0 )\r
+ {\r
+ xTimerDelete( macTmrHandle, portMAX_DELAY );\r
+ macTmrHandle = 0;\r
+ }\r
+\r
+ if( macTaskHandle != 0 )\r
+ {\r
+ vTaskDelete( macTaskHandle );\r
+ macTaskHandle = 0;\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )\r
+ {\r
+ TCPIP_MAC_ADDR macAdd;\r
+ uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* not set MAC address */\r
+\r
+ pMacCtrl->nIfs = 1;\r
+\r
+ pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;\r
+ pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;\r
+ pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;\r
+ pMacCtrl->memH = macHeapHandle;\r
+\r
+\r
+ pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;\r
+ pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;\r
+ pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;\r
+\r
+ pMacCtrl->synchF = MacSyncFunction;\r
+\r
+ pMacCtrl->eventF = MAC_EventFunction;\r
+ pMacCtrl->eventParam = 0;\r
+\r
+ pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;\r
+ pMacCtrl->netIx = 0;\r
+ pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;\r
+ pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;\r
+\r
+ macAdd.v[ 0 ] = configMAC_ADDR0;\r
+ macAdd.v[ 1 ] = configMAC_ADDR1;\r
+ macAdd.v[ 2 ] = configMAC_ADDR2;\r
+ macAdd.v[ 3 ] = configMAC_ADDR3;\r
+ macAdd.v[ 4 ] = configMAC_ADDR4;\r
+ macAdd.v[ 5 ] = configMAC_ADDR5;\r
+\r
+ if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )\r
+ { /* if unspecified we use the factory pre-programmed address */\r
+ PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );\r
+ }\r
+ else\r
+ { /* use the config suggested one */\r
+ memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static bool MacSyncFunction( void * synchHandle,\r
+ TCPIP_MAC_SYNCH_REQUEST req )\r
+ {\r
+ switch( req )\r
+ {\r
+ case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:\r
+ vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );\r
+\r
+ return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;\r
+\r
+ case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:\r
+ vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );\r
+ *( SemaphoreHandle_t * ) synchHandle = NULL;\r
+\r
+ return true;\r
+\r
+ case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:\r
+\r
+ return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;\r
+\r
+ case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:\r
+\r
+ return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;\r
+\r
+ case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:\r
+ vTaskSuspendAll();\r
+\r
+ return true;\r
+\r
+ case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:\r
+ xTaskResumeAll();\r
+\r
+ return true;\r
+\r
+ default:\r
+\r
+ return false;\r
+ }\r
+ }\r
+\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void MacHandlerTask( void * params )\r
+ {\r
+ EventBits_t evBits;\r
+\r
+ /* perform the MAC initialization */\r
+ while( macObjStatus == SYS_STATUS_BUSY )\r
+ {\r
+ /* process the underlying MAC module tasks */\r
+ ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
+\r
+ SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );\r
+\r
+ if( macStatus == SYS_STATUS_BUSY )\r
+ { /* still pending */\r
+ vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );\r
+ }\r
+ else\r
+ { /* completed ...somehow */\r
+ macObjStatus = macStatus;\r
+\r
+ xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );\r
+\r
+ if( macStatus != SYS_STATUS_READY )\r
+ { /* failed miserably */\r
+ vTaskDelete( 0 );\r
+ }\r
+\r
+ /* done, up and running */\r
+ }\r
+ }\r
+\r
+ while( true )\r
+ {\r
+ xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );\r
+\r
+ if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )\r
+ { /* timeout occurred... */\r
+ ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
+ bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */\r
+\r
+ if( macLinkStatus != linkCurr )\r
+ { /* link status changed; some event could ve fired here if needed */\r
+ PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );\r
+ macLinkStatus = linkCurr;\r
+ }\r
+ }\r
+\r
+ if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )\r
+ { /* IF events signal */\r
+ TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );\r
+\r
+ if( activeEvents != TCPIP_MAC_EV_NONE )\r
+ {\r
+ /* acknowledge the events */\r
+ ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );\r
+\r
+ /* check for RX */\r
+ if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )\r
+ { /* RX packets available */\r
+ MacRxPackets();\r
+ }\r
+\r
+ /* call the driver process function; */\r
+ /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */\r
+ ( macObject->TCPIP_MAC_Process )( macCliHandle );\r
+ }\r
+ }\r
+\r
+ /* do what you have to do and then wait for another event... */\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void MacTmrCallback( TimerHandle_t xTimer )\r
+ {\r
+ xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );\r
+ }\r
+\r
+ /* MAC interrupt event function */\r
+ /* MAC signals an event, probably from within ISR */\r
+ /* we care just for RX related events */\r
+ static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
+ const void * eventParam )\r
+ {\r
+ BaseType_t xHigherPriorityTaskWoken;\r
+\r
+ if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )\r
+ {\r
+ xHigherPriorityTaskWoken = pdFALSE;\r
+ xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );\r
+\r
+ if( xHigherPriorityTaskWoken )\r
+ {\r
+ portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
+ }\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ BaseType_t xGetPhyLinkStatus( void )\r
+ {\r
+ return macLinkStatus == true ? pdPASS : pdFAIL;\r
+ }\r
+\r
+\r
+ /* receive packets from the MAC driver */\r
+ static void MacRxPackets( void )\r
+ {\r
+ TCPIP_MAC_PACKET * pRxPkt;\r
+\r
+ /* get all the new MAC packets */\r
+ while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )\r
+ {\r
+ MacProcessRxPacket( pRxPkt );\r
+ }\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )\r
+ {\r
+ bool pktSuccess, pktLost;\r
+ size_t pktLength;\r
+ TCPIP_MAC_DATA_SEGMENT * pSeg;\r
+ uint8_t * pPktBuff;\r
+ NetworkBufferDescriptor_t * pxBufferDescriptor;\r
+ IPStackEvent_t xRxEvent;\r
+\r
+ pxBufferDescriptor = 0;\r
+ pktSuccess = pktLost = false;\r
+\r
+ while( true )\r
+ {\r
+ pktLength = 0;\r
+ int nSegs = 0;\r
+ pSeg = pRxPkt->pDSeg;\r
+ pPktBuff = pSeg->segLoad;\r
+\r
+ /* calculate the packet size */\r
+ do\r
+ {\r
+ pktLength += pSeg->segLen;\r
+ pSeg = pSeg->next;\r
+ nSegs++;\r
+ } while( pSeg != 0 );\r
+\r
+ if( nSegs > 1 )\r
+ { /* no support in FreeRTOS for multi segment packets! */\r
+ break;\r
+ }\r
+\r
+ /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */\r
+ /* but FreeRTOS needs the whole frame! */\r
+ pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );\r
+\r
+ if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )\r
+ {\r
+ break;\r
+ }\r
+\r
+ /* get the network descriptor (no data buffer) to hold this packet */\r
+ pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );\r
+\r
+ if( pxBufferDescriptor == 0 )\r
+ {\r
+ pktLost = true;\r
+ break;\r
+ }\r
+\r
+ PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );\r
+\r
+ xRxEvent.eEventType = eNetworkRxEvent;\r
+ xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+ /* Send the data to the TCP/IP stack */\r
+ if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+ { /* failed */\r
+ pktLost = true;\r
+ }\r
+ else\r
+ { /* success */\r
+ pktSuccess = true;\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ if( !pktSuccess )\r
+ { /* smth went wrong; nothing sent to the */\r
+ if( pxBufferDescriptor != 0 )\r
+ {\r
+ pxBufferDescriptor->pucEthernetBuffer = 0;\r
+ vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+ }\r
+\r
+ if( pktLost )\r
+ {\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+\r
+ /* acknowledge the packet to the MAC driver */\r
+ if( pRxPkt->ackFunc )\r
+ {\r
+ ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );\r
+ }\r
+ else\r
+ {\r
+ PIC32_MacPacketOrphan( pRxPkt );\r
+ }\r
+ }\r
+ }\r
+\r
+ #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+ /* */\r
+ static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+ int argc,\r
+ char ** argv )\r
+ {\r
+ TCPIP_MAC_RES macRes;\r
+ TCPIP_MAC_RX_STATISTICS rxStatistics;\r
+ TCPIP_MAC_TX_STATISTICS txStatistics;\r
+ TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];\r
+ TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;\r
+ int jx, hwEntries;\r
+ char entryName[ sizeof( pRegEntry->registerName ) + 1 ];\r
+\r
+ const void * cmdIoParam = pCmdIO->cmdIoParam;\r
+\r
+ if( argc != 1 )\r
+ {\r
+ ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );\r
+ ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );\r
+\r
+ return false;\r
+ }\r
+\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );\r
+ macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );\r
+\r
+ if( macRes == TCPIP_MAC_RES_OK )\r
+ {\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",\r
+ rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",\r
+ txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );\r
+ }\r
+ else\r
+ {\r
+ ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
+ }\r
+\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );\r
+ macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );\r
+\r
+ if( macRes == TCPIP_MAC_RES_OK )\r
+ {\r
+ entryName[ sizeof( entryName ) - 1 ] = 0;\r
+\r
+ for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )\r
+ {\r
+ strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+ int argc,\r
+ char ** argv )\r
+ {\r
+ const void * cmdIoParam = pCmdIO->cmdIoParam;\r
+\r
+ union\r
+ {\r
+ uint32_t ul;\r
+ uint8_t b[ 4 ];\r
+ }\r
+ sUl;\r
+\r
+ sUl.ul = FreeRTOS_GetIPAddress();\r
+\r
+ bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;\r
+\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );\r
+ ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );\r
+\r
+ return true;\r
+ }\r
+\r
+#include "aws_application_version.h"\r
+\r
+static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)\r
+{\r
+ configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n", xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );\r
+ return 0;\r
+}\r
+\r
+ #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+#endif /* #ifdef PIC32_USE_ETHERNET */\r
-/*******************************************************************************
-* Network Interface file
-*
-* Summary:
-* Network Interface file for FreeRTOS-Plus-TCP stack
-*
-* Description:
-* - Interfaces PIC32 to the FreeRTOS TCP/IP stack
-*******************************************************************************/
-
-/*******************************************************************************
-* File Name: pic32_NetworkInterface.c
-* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
-*
-* 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
-*******************************************************************************/
-#ifndef PIC32_USE_ETHERNET
-#include <sys/kmem.h>
-
-#include "FreeRTOS.h"
-#include "semphr.h"
-#include "event_groups.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-#include "peripheral/eth/plib_eth.h"
-
-#include "system_config.h"
-#include "system/console/sys_console.h"
-#include "system/debug/sys_debug.h"
-#include "system/command/sys_command.h"
-
-#include "driver/ethmac/drv_ethmac.h"
-#include "driver/miim/drv_miim.h"
-#include "m2m_types.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-#include "tcpip/src/link_list.h"
-#include "wilc1000_task.h"
-
-#include "NetworkConfig.h"
-
-
- #include "iot_wifi.h"
-
- /* local definitions and data */
-
-
- /* FreeRTOS implementation functions */
- BaseType_t xNetworkInterfaceInitialise( void )
- {
- WIFINetworkParams_t xNetworkParams;
-
- xNetworkParams.pcSSID = clientcredentialWIFI_SSID;
- xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );
- xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;
- xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );
- xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;
- xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */
-
- /*Turn WiFi ON */
- if( WIFI_On() != eWiFiSuccess )
- {
- return pdFAIL;
- }
-
- /* Connect to the AP */
- if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )
- {
- return pdFAIL;
- }
-
- return pdPASS;
- }
-
-
- /*-----------------------------------------------------------*/
-
- BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
- BaseType_t xReleaseAfterSend )
- {
- BaseType_t retRes = pdFALSE;
-
- if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
- {
- /* There you go */
- if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )
- {
- retRes = pdTRUE;
- }
-
- /* The buffer has been sent so can be released. */
- if( xReleaseAfterSend != pdFALSE )
- {
- vReleaseNetworkBufferAndDescriptor( pxDescriptor );
- }
- }
-
- return retRes;
- }
-
-
- /************************************* Section: helper functions ************************************************** */
- /* */
-
-
-
- /************************************* Section: worker code ************************************************** */
- /* */
-
- void xNetworkFrameReceived( uint32_t len,
- uint8_t const * const frame )
- {
- bool pktSuccess, pktLost;
- NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;
- IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
- pktSuccess = pktLost = false;
-
- while( true )
- {
- if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )
- {
- break;
- }
-
- /* get the network descriptor (no data buffer) to hold this packet */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );
-
- if( pxNetworkBuffer == NULL )
- {
- pktLost = true;
- break;
- }
-
- /* Set the actual packet length, in case a larger buffer was
- returned. */
- pxNetworkBuffer->xDataLength = len;
-
- /* Copy the packet. */
- memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );
-
- /* Send the data to the TCP/IP stack. */
- xRxEvent.pvData = ( void * ) pxNetworkBuffer;
-
- if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
- { /* failed */
- pktLost = true;
- }
- else
- { /* success */
- pktSuccess = true;
- iptraceNETWORK_INTERFACE_RECEIVE();
- }
-
- break;
- }
-
- if( !pktSuccess )
- { /* smth went wrong; nothing sent to the */
- if( pxNetworkBuffer != NULL )
- {
- pxNetworkBuffer->pucEthernetBuffer = 0;
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- }
-
- if( pktLost )
- {
- iptraceETHERNET_RX_EVENT_LOST();
- }
- }
- }
-
-#endif /* #ifndef PIC32_USE_ETHERNET */
+/*******************************************************************************\r
+* Network Interface file\r
+*\r
+* Summary:\r
+* Network Interface file for FreeRTOS-Plus-TCP stack\r
+*\r
+* Description:\r
+* - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
+*******************************************************************************/\r
+\r
+/*******************************************************************************\r
+* File Name: pic32_NetworkInterface.c\r
+* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\r
+*\r
+* Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+* this software and associated documentation files (the "Software"), to deal in\r
+* the Software without restriction, including without limitation the rights to\r
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\r
+* of the Software, and to permit persons to whom the Software is furnished to do\r
+* so, subject to the following conditions:\r
+* The above copyright notice and this permission notice shall be included in all\r
+* copies or substantial portions of the Software.\r
+*\r
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+* SOFTWARE\r
+*******************************************************************************/\r
+#ifndef PIC32_USE_ETHERNET\r
+#include <sys/kmem.h>\r
+\r
+#include "FreeRTOS.h"\r
+#include "semphr.h"\r
+#include "event_groups.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "peripheral/eth/plib_eth.h"\r
+\r
+#include "system_config.h"\r
+#include "system/console/sys_console.h"\r
+#include "system/debug/sys_debug.h"\r
+#include "system/command/sys_command.h"\r
+\r
+#include "driver/ethmac/drv_ethmac.h"\r
+#include "driver/miim/drv_miim.h"\r
+#include "m2m_types.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+#include "tcpip/src/link_list.h"\r
+#include "wilc1000_task.h"\r
+\r
+#include "NetworkConfig.h"\r
+\r
+\r
+ #include "iot_wifi.h"\r
+\r
+ /* local definitions and data */\r
+\r
+\r
+ /* FreeRTOS implementation functions */\r
+ BaseType_t xNetworkInterfaceInitialise( void )\r
+ {\r
+ WIFINetworkParams_t xNetworkParams;\r
+\r
+ xNetworkParams.pcSSID = clientcredentialWIFI_SSID;\r
+ xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );\r
+ xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;\r
+ xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );\r
+ xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;\r
+ xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */\r
+\r
+ /*Turn WiFi ON */\r
+ if( WIFI_On() != eWiFiSuccess )\r
+ {\r
+ return pdFAIL;\r
+ }\r
+\r
+ /* Connect to the AP */\r
+ if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )\r
+ {\r
+ return pdFAIL;\r
+ }\r
+\r
+ return pdPASS;\r
+ }\r
+\r
+\r
+ /*-----------------------------------------------------------*/\r
+\r
+ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+ BaseType_t xReleaseAfterSend )\r
+ {\r
+ BaseType_t retRes = pdFALSE;\r
+\r
+ if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
+ {\r
+ /* There you go */\r
+ if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )\r
+ {\r
+ retRes = pdTRUE;\r
+ }\r
+\r
+ /* The buffer has been sent so can be released. */\r
+ if( xReleaseAfterSend != pdFALSE )\r
+ {\r
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+ }\r
+ }\r
+\r
+ return retRes;\r
+ }\r
+\r
+\r
+ /************************************* Section: helper functions ************************************************** */\r
+ /* */\r
+\r
+\r
+\r
+ /************************************* Section: worker code ************************************************** */\r
+ /* */\r
+\r
+ void xNetworkFrameReceived( uint32_t len,\r
+ uint8_t const * const frame )\r
+ {\r
+ bool pktSuccess, pktLost;\r
+ NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;\r
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+ pktSuccess = pktLost = false;\r
+\r
+ while( true )\r
+ {\r
+ if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )\r
+ {\r
+ break;\r
+ }\r
+\r
+ /* get the network descriptor (no data buffer) to hold this packet */\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );\r
+\r
+ if( pxNetworkBuffer == NULL )\r
+ {\r
+ pktLost = true;\r
+ break;\r
+ }\r
+\r
+ /* Set the actual packet length, in case a larger buffer was \r
+ returned. */\r
+ pxNetworkBuffer->xDataLength = len;\r
+ \r
+ /* Copy the packet. */\r
+ memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );\r
+\r
+ /* Send the data to the TCP/IP stack. */\r
+ xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+ if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+ { /* failed */\r
+ pktLost = true;\r
+ }\r
+ else\r
+ { /* success */\r
+ pktSuccess = true;\r
+ iptraceNETWORK_INTERFACE_RECEIVE();\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ if( !pktSuccess )\r
+ { /* smth went wrong; nothing sent to the */\r
+ if( pxNetworkBuffer != NULL )\r
+ {\r
+ pxNetworkBuffer->pucEthernetBuffer = 0;\r
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+ }\r
+\r
+ if( pktLost )\r
+ {\r
+ iptraceETHERNET_RX_EVENT_LOST();\r
+ }\r
+ }\r
+ }\r
+\r
+#endif /* #ifndef PIC32_USE_ETHERNET */\r
Documentation and download available at http://www.FreeRTOS.org/\r
\r
-Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released TBD\r
+Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released February 7 2020\r
\r
See http://www.FreeRTOS.org/FreeRTOS-V10.3.x.html\r
\r
* MACROS AND DEFINITIONS\r
*----------------------------------------------------------*/\r
\r
-#define tskKERNEL_VERSION_NUMBER "V10.2.1"\r
+#define tskKERNEL_VERSION_NUMBER "V10.3.0"\r
#define tskKERNEL_VERSION_MAJOR 10\r
-#define tskKERNEL_VERSION_MINOR 2\r
-#define tskKERNEL_VERSION_BUILD 1\r
+#define tskKERNEL_VERSION_MINOR 3\r
+#define tskKERNEL_VERSION_BUILD 0\r
\r
/* MPU region parameters passed in ulParameters\r
* of MemoryRegion_t struct. */\r
--- /dev/null
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,11\r
+[InternetShortcut]\r
+IDList=\r
+URL=https://www.freertos.org/FreeRTOS-V10.3.x.html\r