mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 02:32:42 -05:00 
			
		
		
		
	Update the FreeRTOS+UDP LPC18xx MAC driver to use the LPCOpen drivers.
This commit is contained in:
		
							parent
							
								
									54c62d429f
								
							
						
					
					
						commit
						f9d0a153b4
					
				
					 5 changed files with 446 additions and 911 deletions
				
			
		| 
						 | 
				
			
			@ -53,13 +53,14 @@
 | 
			
		|||
#include "FreeRTOS_IP_Private.h"
 | 
			
		||||
#include "FreeRTOS_Sockets.h"
 | 
			
		||||
#include "NetworkBufferManagement.h"
 | 
			
		||||
 | 
			
		||||
/* Driver includes. */
 | 
			
		||||
#include "lpc18xx_emac.h"
 | 
			
		||||
#include "lpc18xx_43xx_EMAC_LPCOpen.h"
 | 
			
		||||
 | 
			
		||||
/* Demo includes. */
 | 
			
		||||
#include "NetworkInterface.h"
 | 
			
		||||
 | 
			
		||||
/* Library includes. */
 | 
			
		||||
#include "board.h"
 | 
			
		||||
 | 
			
		||||
#if configMAC_INTERRUPT_PRIORITY > configMAC_INTERRUPT_PRIORITY
 | 
			
		||||
	#error configMAC_INTERRUPT_PRIORITY must be greater than or equal to configMAC_INTERRUPT_PRIORITY (higher numbers mean lower logical priority)
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -93,23 +94,19 @@ extern xQueueHandle xNetworkEventQueue;
 | 
			
		|||
 | 
			
		||||
/* The semaphore used to wake the deferred interrupt handler task when an Rx
 | 
			
		||||
interrupt is received. */
 | 
			
		||||
static xSemaphoreHandle xEMACRxEventSemaphore = NULL;
 | 
			
		||||
xSemaphoreHandle xEMACRxEventSemaphore = NULL;
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
portBASE_TYPE xNetworkInterfaceInitialise( void )
 | 
			
		||||
{
 | 
			
		||||
EMAC_CFG_Type Emac_Config;
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
extern uint8_t ucMACAddress[ 6 ];
 | 
			
		||||
 | 
			
		||||
	Emac_Config.pbEMAC_Addr = ucMACAddress;
 | 
			
		||||
	xReturn = EMAC_Init( &Emac_Config );
 | 
			
		||||
	xReturn = xEMACInit( ucMACAddress );
 | 
			
		||||
 | 
			
		||||
	if( xReturn == pdPASS )
 | 
			
		||||
	{
 | 
			
		||||
		LPC_ETHERNET->DMA_INT_EN =  DMA_INT_NOR_SUM | DMA_INT_RECEIVE;
 | 
			
		||||
 | 
			
		||||
		/* Create the event semaphore if it has not already been created. */
 | 
			
		||||
		if( xEMACRxEventSemaphore == NULL )
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -121,25 +118,19 @@ extern uint8_t ucMACAddress[ 6 ];
 | 
			
		|||
				vTraceSetQueueName( xEMACRxEventSemaphore, "MAC_RX" );
 | 
			
		||||
			}
 | 
			
		||||
			#endif /*  ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			configASSERT( xEMACRxEventSemaphore );
 | 
			
		||||
 | 
			
		||||
			/* The Rx deferred interrupt handler task is created at the highest
 | 
			
		||||
			possible priority to ensure the interrupt handler can return directly to
 | 
			
		||||
			it no matter which task was running when the interrupt occurred. */
 | 
			
		||||
		xTaskCreate( 	prvEMACDeferredInterruptHandlerTask,		/* The function that implements the task. */
 | 
			
		||||
			xTaskCreate( 	prvEMACDeferredInterruptHandlerTask,/* The function that implements the task. */
 | 
			
		||||
							( const signed char * const ) "MACTsk",
 | 
			
		||||
							configMINIMAL_STACK_SIZE,	/* Stack allocated to the task (defined in words, not bytes). */
 | 
			
		||||
							NULL, 						/* The task parameter is not used. */
 | 
			
		||||
							configMAX_PRIORITIES - 1, 	/* The priority assigned to the task. */
 | 
			
		||||
							NULL );						/* The handle is not required, so NULL is passed. */
 | 
			
		||||
 | 
			
		||||
		/* Enable the interrupt and set its priority as configured.  THIS
 | 
			
		||||
		DRIVER REQUIRES configMAC_INTERRUPT_PRIORITY TO BE DEFINED, PREFERABLY
 | 
			
		||||
		IN FreeRTOSConfig.h. */
 | 
			
		||||
		NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
 | 
			
		||||
		NVIC_EnableIRQ( ETHERNET_IRQn );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
| 
						 | 
				
			
			@ -154,10 +145,10 @@ int32_t x;
 | 
			
		|||
	/* Attempt to obtain access to a Tx descriptor. */
 | 
			
		||||
	for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		if( EMAC_CheckTransmitIndex() == TRUE )
 | 
			
		||||
		if( xEMACIsTxDescriptorAvailable() == TRUE )
 | 
			
		||||
		{
 | 
			
		||||
			/* Assign the buffer being transmitted to the Tx descriptor. */
 | 
			
		||||
			EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );
 | 
			
		||||
			vEMACAssignBufferToDescriptor( pxNetworkBuffer->pucEthernetBuffer );
 | 
			
		||||
 | 
			
		||||
			/* The EMAC now owns the buffer and will free it when it has been
 | 
			
		||||
			transmitted.  Set pucBuffer to NULL to ensure the buffer is not
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +157,7 @@ int32_t x;
 | 
			
		|||
			pxNetworkBuffer->pucEthernetBuffer = NULL;
 | 
			
		||||
 | 
			
		||||
			/* Initiate the Tx. */
 | 
			
		||||
			EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
 | 
			
		||||
			vEMACStartNextTransmission( pxNetworkBuffer->xDataLength );
 | 
			
		||||
			iptraceNETWORK_INTERFACE_TRANSMIT();
 | 
			
		||||
 | 
			
		||||
			/* The Tx has been initiated. */
 | 
			
		||||
| 
						 | 
				
			
			@ -188,36 +179,6 @@ int32_t x;
 | 
			
		|||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void ETH_IRQHandler( void )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulInterruptCause;
 | 
			
		||||
 | 
			
		||||
	ulInterruptCause = LPC_ETHERNET->DMA_STAT ;
 | 
			
		||||
 | 
			
		||||
	/* Clear the interrupt. */
 | 
			
		||||
	LPC_ETHERNET->DMA_STAT |= ( DMA_INT_NOR_SUM | DMA_INT_RECEIVE );
 | 
			
		||||
 | 
			
		||||
	/* 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 & ( 1 << 13 ) ) != 0U )
 | 
			
		||||
	{
 | 
			
		||||
		LPC_ETHERNET->DMA_STAT |= ( 1 << 13 );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unblock the deferred interrupt handler task if the event was an Rx. */
 | 
			
		||||
	if( ( ulInterruptCause & DMA_INT_RECEIVE ) != 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 prvEMACDeferredInterruptHandlerTask( void *pvParameters )
 | 
			
		||||
{
 | 
			
		||||
xNetworkBufferDescriptor_t *pxNetworkBuffer;
 | 
			
		||||
| 
						 | 
				
			
			@ -237,7 +198,7 @@ xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
 | 
			
		|||
		while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
 | 
			
		||||
 | 
			
		||||
		/* At least one packet has been received. */
 | 
			
		||||
		while( EMAC_CheckReceiveIndex() != FALSE )
 | 
			
		||||
		while( xEMACRxDataAvailable() != FALSE )
 | 
			
		||||
		{
 | 
			
		||||
			/* The buffer filled by the DMA is going to be passed into the IP
 | 
			
		||||
			stack.  Allocate another buffer for the DMA descriptor. */
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +211,7 @@ xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
 | 
			
		|||
				the DMA.  pxNetworkBuffer will then hold a reference to the
 | 
			
		||||
				buffer that already contains the data without any data having
 | 
			
		||||
				been copied between buffers. */
 | 
			
		||||
				EMAC_NextPacketToRead( pxNetworkBuffer );
 | 
			
		||||
				vEMACSwapEmptyBufferForRxedData( pxNetworkBuffer );
 | 
			
		||||
 | 
			
		||||
				#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 1
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +265,7 @@ xIPStackEvent_t xRxEvent = { eEthernetRxEvent, NULL };
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			/* Release the descriptor. */
 | 
			
		||||
			EMAC_UpdateRxConsumeIndex();
 | 
			
		||||
			vEMACReturnRxDescriptor();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,339 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the FreeRTOS+UDP distribution.  The FreeRTOS+UDP license
 | 
			
		||||
 * terms are different to the FreeRTOS license terms.
 | 
			
		||||
 *
 | 
			
		||||
 * FreeRTOS+UDP uses a dual license model that allows the software to be used 
 | 
			
		||||
 * under a standard GPL open source license, or a commercial license.  The 
 | 
			
		||||
 * standard GPL license (unlike the modified GPL license under which FreeRTOS 
 | 
			
		||||
 * itself is distributed) requires that all software statically linked with 
 | 
			
		||||
 * FreeRTOS+UDP is also distributed under the same GPL V2 license terms.  
 | 
			
		||||
 * Details of both license options follow:
 | 
			
		||||
 *
 | 
			
		||||
 * - Open source licensing -
 | 
			
		||||
 * FreeRTOS+UDP is a free download and may be used, modified, evaluated and
 | 
			
		||||
 * distributed without charge provided the user adheres to version two of the
 | 
			
		||||
 * GNU General Public License (GPL) and does not remove the copyright notice or
 | 
			
		||||
 * this text.  The GPL V2 text is available on the gnu.org web site, and on the
 | 
			
		||||
 * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
 | 
			
		||||
 *
 | 
			
		||||
 * - Commercial licensing -
 | 
			
		||||
 * Businesses and individuals that for commercial or other reasons cannot comply
 | 
			
		||||
 * with the terms of the GPL V2 license must obtain a commercial license before 
 | 
			
		||||
 * incorporating FreeRTOS+UDP into proprietary software for distribution in any 
 | 
			
		||||
 * form.  Commercial licenses can be purchased from http://shop.freertos.org/udp 
 | 
			
		||||
 * and do not require any source files to be changed.
 | 
			
		||||
 *
 | 
			
		||||
 * FreeRTOS+UDP is distributed in the hope that it will be useful.  You cannot
 | 
			
		||||
 * use FreeRTOS+UDP unless you agree that you use the software 'as is'.
 | 
			
		||||
 * FreeRTOS+UDP 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/udp
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
#include "semphr.h"
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS+UDP includes. */
 | 
			
		||||
#include "FreeRTOS_UDP_IP.h"
 | 
			
		||||
#include "FreeRTOS_IP_Private.h"
 | 
			
		||||
#include "NetworkBufferManagement.h"
 | 
			
		||||
 | 
			
		||||
/* Library includes. */
 | 
			
		||||
#include "board.h"
 | 
			
		||||
 | 
			
		||||
/* Descriptors that reference received buffers are expected to have both the
 | 
			
		||||
first and last frame bits set because buffers are dimensioned to hold complete
 | 
			
		||||
Ethernet frames. */
 | 
			
		||||
#define emacEXPECTED_RX_STATUS_MASK	( RDES_LS | RDES_FS )
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set the Rx and Tx descriptors into their expected initial state.
 | 
			
		||||
 */
 | 
			
		||||
static void prvResetRxDescriptors( void );
 | 
			
		||||
static void prvResetTxDescriptors( void );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns the length of the data pointed to by the next Rx descriptor.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t prvReceivedDataLength( void );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Rx and Tx descriptors and data array. */
 | 
			
		||||
static volatile IP_ENET_001_ENHRXDESC_T xRXDescriptors[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
static volatile IP_ENET_001_ENHTXDESC_T xTxDescriptors[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
 | 
			
		||||
/* Indexes into the Rx and Tx descriptor arrays. */
 | 
			
		||||
static unsigned int xRxDescriptorIndex = 0;
 | 
			
		||||
static unsigned int xTxDescriptorIndex = 0;
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
portBASE_TYPE xEMACInit( uint8_t ucMACAddress[ 6 ] )
 | 
			
		||||
{
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
uint32_t ulPHYStatus;
 | 
			
		||||
 | 
			
		||||
	/* Configure the hardware. */
 | 
			
		||||
	Chip_ENET_Init( LPC_ETHERNET );
 | 
			
		||||
 | 
			
		||||
	if( lpc_phy_init( pdTRUE, vTaskDelay ) == SUCCESS )
 | 
			
		||||
	{
 | 
			
		||||
		/* The MAC address is passed in as the function parameter. */
 | 
			
		||||
		Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );
 | 
			
		||||
 | 
			
		||||
		/* Wait for autonegotiation to complete. */
 | 
			
		||||
		do
 | 
			
		||||
		{
 | 
			
		||||
			vTaskDelay( 100 );
 | 
			
		||||
			ulPHYStatus = lpcPHYStsPoll();
 | 
			
		||||
		} while( ( ulPHYStatus & PHY_LINK_CONNECTED ) == 0x00 );
 | 
			
		||||
 | 
			
		||||
		/* Configure the hardware as per the negotiated link. */
 | 
			
		||||
		if( ( ulPHYStatus & PHY_LINK_FULLDUPLX ) == PHY_LINK_FULLDUPLX )
 | 
			
		||||
		{
 | 
			
		||||
			IP_ENET_SetDuplex( LPC_ETHERNET, pdTRUE );
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			IP_ENET_SetDuplex( LPC_ETHERNET, pdFALSE );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( ( ulPHYStatus & PHY_LINK_SPEED100 ) == PHY_LINK_SPEED100 )
 | 
			
		||||
		{
 | 
			
		||||
			IP_ENET_SetSpeed( LPC_ETHERNET, pdTRUE );
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			IP_ENET_SetSpeed( LPC_ETHERNET, pdFALSE );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Set descriptors to their initial state. */
 | 
			
		||||
		prvResetRxDescriptors();
 | 
			
		||||
		prvResetTxDescriptors();
 | 
			
		||||
 | 
			
		||||
		/* Enable RX and TX. */
 | 
			
		||||
		Chip_ENET_TXEnable( LPC_ETHERNET );
 | 
			
		||||
		Chip_ENET_RXEnable( LPC_ETHERNET );
 | 
			
		||||
 | 
			
		||||
		/* Enable the interrupt and set its priority as configured.  THIS
 | 
			
		||||
		DRIVER REQUIRES configMAC_INTERRUPT_PRIORITY TO BE DEFINED, PREFERABLY
 | 
			
		||||
		IN FreeRTOSConfig.h. */
 | 
			
		||||
		NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
 | 
			
		||||
		NVIC_EnableIRQ( ETHERNET_IRQn );
 | 
			
		||||
 | 
			
		||||
		/* Enable interrupts. */
 | 
			
		||||
		LPC_ETHERNET->DMA_INT_EN =  DMA_IE_NIE | DMA_IE_RIE;
 | 
			
		||||
 | 
			
		||||
		xReturn = pdPASS;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
portBASE_TYPE xEMACIsTxDescriptorAvailable( void )
 | 
			
		||||
{
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
 | 
			
		||||
	if( ( xTxDescriptors[ xTxDescriptorIndex ].CTRLSTAT & RDES_OWN ) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdPASS;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vEMACAssignBufferToDescriptor( uint8_t * pucBuffer )
 | 
			
		||||
{
 | 
			
		||||
	/* The old packet is now finished with and can be freed. */
 | 
			
		||||
	vEthernetBufferRelease( ( void * ) xTxDescriptors[ xTxDescriptorIndex ].B1ADD );
 | 
			
		||||
 | 
			
		||||
	/* Assign the new packet to the descriptor. */
 | 
			
		||||
	xTxDescriptors[ xTxDescriptorIndex ].B1ADD = ( uint32_t ) pucBuffer;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vEMACStartNextTransmission( uint32_t ulLength )
 | 
			
		||||
{
 | 
			
		||||
	xTxDescriptors[ xTxDescriptorIndex ].BSIZE = ulLength;
 | 
			
		||||
	xTxDescriptors[ xTxDescriptorIndex ].CTRLSTAT |= RDES_OWN;
 | 
			
		||||
 | 
			
		||||
	/* Wake Up the DMA if it's in Suspended Mode. */
 | 
			
		||||
	LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
 | 
			
		||||
	xTxDescriptorIndex++;
 | 
			
		||||
 | 
			
		||||
	if( xTxDescriptorIndex == configNUM_TX_ETHERNET_DMA_DESCRIPTORS )
 | 
			
		||||
	{
 | 
			
		||||
		xTxDescriptorIndex = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static uint32_t prvReceivedDataLength( void )
 | 
			
		||||
{
 | 
			
		||||
unsigned short RxLen = 0;
 | 
			
		||||
 | 
			
		||||
	RxLen = ( xRXDescriptors[ xRxDescriptorIndex ].STATUS >> 16 ) & 0x03FFF;
 | 
			
		||||
	return RxLen;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vEMACReturnRxDescriptor( void )
 | 
			
		||||
{
 | 
			
		||||
	xRXDescriptors[ xRxDescriptorIndex ].STATUS = RDES_OWN;
 | 
			
		||||
	xRxDescriptorIndex++;
 | 
			
		||||
 | 
			
		||||
	if( xRxDescriptorIndex == configNUM_RX_ETHERNET_DMA_DESCRIPTORS )
 | 
			
		||||
	{
 | 
			
		||||
		xRxDescriptorIndex = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
portBASE_TYPE xEMACRxDataAvailable( void )
 | 
			
		||||
{
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
 | 
			
		||||
	if( ( xRXDescriptors[ xRxDescriptorIndex ].STATUS & RDES_OWN ) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdPASS;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vEMACSwapEmptyBufferForRxedData( xNetworkBufferDescriptor_t *pxNetworkBuffer )
 | 
			
		||||
{
 | 
			
		||||
uint8_t *pucTemp;
 | 
			
		||||
 | 
			
		||||
	/* Swap the buffer in the network buffer with the buffer used by the DMA.
 | 
			
		||||
	This allows the data to be passed out without having to perform any copies. */
 | 
			
		||||
	pucTemp = ( uint8_t * ) xRXDescriptors[ xRxDescriptorIndex ].B1ADD;
 | 
			
		||||
	xRXDescriptors[ xRxDescriptorIndex ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;
 | 
			
		||||
	pxNetworkBuffer->pucEthernetBuffer = pucTemp;
 | 
			
		||||
 | 
			
		||||
	/* Only supports frames coming in single buffers.  If this frame is split
 | 
			
		||||
	across multiple buffers then reject it (and if the frame is needed increase
 | 
			
		||||
	the ipconfigNETWORK_MTU setting). */
 | 
			
		||||
	if( ( xRXDescriptors[ xRxDescriptorIndex ].STATUS & emacEXPECTED_RX_STATUS_MASK ) != emacEXPECTED_RX_STATUS_MASK )
 | 
			
		||||
	{
 | 
			
		||||
		pxNetworkBuffer->xDataLength = 0;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		pxNetworkBuffer->xDataLength = ( size_t ) prvReceivedDataLength() - ( ipETHERNET_CRC_BYTES - 1U );;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvResetRxDescriptors( void )
 | 
			
		||||
{
 | 
			
		||||
uint32_t x;
 | 
			
		||||
size_t xBufferSize = ipTOTAL_ETHERNET_FRAME_SIZE;
 | 
			
		||||
 | 
			
		||||
	for( x = 0; x < configNUM_RX_ETHERNET_DMA_DESCRIPTORS; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		/* Obtain the buffer first, as the size of the buffer might be changed
 | 
			
		||||
		within the pucEthernetBufferGet() call. */
 | 
			
		||||
		xRXDescriptors[ x ].B1ADD  = ( uint32_t ) pucEthernetBufferGet( &xBufferSize );
 | 
			
		||||
		xRXDescriptors[ x ].STATUS = RDES_OWN;
 | 
			
		||||
		xRXDescriptors[ x ].CTRL  = xBufferSize;
 | 
			
		||||
		xRXDescriptors[ x ].B2ADD = ( uint32_t ) &xRXDescriptors[ x + 1 ];
 | 
			
		||||
		
 | 
			
		||||
		configASSERT( ( ( ( uint32_t ) xRXDescriptors[x].B1ADD ) & 0x07 ) == 0 );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Last Descriptor */
 | 
			
		||||
	xRXDescriptors[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS - 1 ].CTRL |= RDES_ENH_RER;
 | 
			
		||||
 | 
			
		||||
	xRxDescriptorIndex = 0;
 | 
			
		||||
 | 
			
		||||
	/* Set Starting address of RX Descriptor list */
 | 
			
		||||
	LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xRXDescriptors;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvResetTxDescriptors( void )
 | 
			
		||||
{
 | 
			
		||||
/* Initialize Transmit Descriptor and Status array. */
 | 
			
		||||
uint32_t x;
 | 
			
		||||
 | 
			
		||||
	for( x = 0; x < configNUM_TX_ETHERNET_DMA_DESCRIPTORS; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		xTxDescriptors[ x ].CTRLSTAT = TDES_ENH_FS | TDES_ENH_LS;
 | 
			
		||||
		xTxDescriptors[ x ].BSIZE  = 0;
 | 
			
		||||
		xTxDescriptors[ x ].B2ADD = ( uint32_t ) &xTxDescriptors[ x + 1 ];
 | 
			
		||||
 | 
			
		||||
		/* Packet is assigned when a Tx is initiated. */
 | 
			
		||||
		xTxDescriptors[ x ].B1ADD   = ( uint32_t )NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Last Descriptor? */
 | 
			
		||||
	xTxDescriptors[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS-1 ].CTRLSTAT |= TDES_ENH_TER;
 | 
			
		||||
 | 
			
		||||
	/* Set Starting address of TX Descriptor list */
 | 
			
		||||
	LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xTxDescriptors;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void ETH_IRQHandler( void )
 | 
			
		||||
{
 | 
			
		||||
uint32_t ulInterruptCause;
 | 
			
		||||
extern xSemaphoreHandle xEMACRxEventSemaphore;
 | 
			
		||||
 | 
			
		||||
	configASSERT( xEMACRxEventSemaphore );
 | 
			
		||||
 | 
			
		||||
	ulInterruptCause = LPC_ETHERNET->DMA_STAT ;
 | 
			
		||||
 | 
			
		||||
	/* Clear the interrupt. */
 | 
			
		||||
	LPC_ETHERNET->DMA_STAT |= ( DMA_ST_NIS | DMA_ST_RI );
 | 
			
		||||
 | 
			
		||||
	/* 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 & DMA_ST_FBI ) != 0U )
 | 
			
		||||
	{
 | 
			
		||||
		LPC_ETHERNET->DMA_STAT |= DMA_ST_FBI;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Unblock the deferred interrupt handler task if the event was an Rx. */
 | 
			
		||||
	if( ( ulInterruptCause & DMA_IE_RIE ) != 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 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is part of the FreeRTOS+UDP distribution.  The FreeRTOS+UDP license
 | 
			
		||||
 * terms are different to the FreeRTOS license terms.
 | 
			
		||||
 *
 | 
			
		||||
 * FreeRTOS+UDP uses a dual license model that allows the software to be used
 | 
			
		||||
 * under a standard GPL open source license, or a commercial license.  The
 | 
			
		||||
 * standard GPL license (unlike the modified GPL license under which FreeRTOS
 | 
			
		||||
 * itself is distributed) requires that all software statically linked with
 | 
			
		||||
 * FreeRTOS+UDP is also distributed under the same GPL V2 license terms.
 | 
			
		||||
 * Details of both license options follow:
 | 
			
		||||
 *
 | 
			
		||||
 * - Open source licensing -
 | 
			
		||||
 * FreeRTOS+UDP is a free download and may be used, modified, evaluated and
 | 
			
		||||
 * distributed without charge provided the user adheres to version two of the
 | 
			
		||||
 * GNU General Public License (GPL) and does not remove the copyright notice or
 | 
			
		||||
 * this text.  The GPL V2 text is available on the gnu.org web site, and on the
 | 
			
		||||
 * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
 | 
			
		||||
 *
 | 
			
		||||
 * - Commercial licensing -
 | 
			
		||||
 * Businesses and individuals that for commercial or other reasons cannot comply
 | 
			
		||||
 * with the terms of the GPL V2 license must obtain a commercial license before
 | 
			
		||||
 * incorporating FreeRTOS+UDP into proprietary software for distribution in any
 | 
			
		||||
 * form.  Commercial licenses can be purchased from http://shop.freertos.org/udp
 | 
			
		||||
 * and do not require any source files to be changed.
 | 
			
		||||
 *
 | 
			
		||||
 * FreeRTOS+UDP is distributed in the hope that it will be useful.  You cannot
 | 
			
		||||
 * use FreeRTOS+UDP unless you agree that you use the software 'as is'.
 | 
			
		||||
 * FreeRTOS+UDP 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/udp
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LPC18xx_43xx_EMAC_H
 | 
			
		||||
#define LPC18xx_43xx_EMAC_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialise the MAC and PHY.
 | 
			
		||||
 */
 | 
			
		||||
portBASE_TYPE xEMACInit( uint8_t ucMACAddress[ 6 ] );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return pdTRUE if there is a FreeRTOS Tx descriptor.  Return pdFALSE if all
 | 
			
		||||
 * Tx descriptors are already in use.
 | 
			
		||||
 */
 | 
			
		||||
portBASE_TYPE xEMACIsTxDescriptorAvailable( void );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Assign a buffer to a Tx descriptor so it is ready to be transmitted, but
 | 
			
		||||
 * don't start the transmission yet.
 | 
			
		||||
 */
 | 
			
		||||
void vEMACAssignBufferToDescriptor( uint8_t * pucBuffer );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Start transmitting the buffer pointed to by the next Tx descriptor.  The
 | 
			
		||||
 * buffer must have first been allocated to the Tx descriptor using a call to
 | 
			
		||||
 * vEMACAssignBufferToDescriptor().
 | 
			
		||||
 */
 | 
			
		||||
void vEMACStartNextTransmission( uint32_t ulLength );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The data pointed to by the Rx descriptor has been consumed, and the Rx
 | 
			
		||||
 * descriptor can be returned to the control of the DMS.
 | 
			
		||||
 */
 | 
			
		||||
void vEMACReturnRxDescriptor( void );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns pdTRUE if the next Rx descriptor contains received data.  Returns
 | 
			
		||||
 * pdFLASE fi the next Rx descriptor is still under the control of the DMA.
 | 
			
		||||
 */
 | 
			
		||||
portBASE_TYPE xEMACRxDataAvailable( void );
 | 
			
		||||
void vEMACSwapEmptyBufferForRxedData( xNetworkBufferDescriptor_t *pxNetworkBuffer );
 | 
			
		||||
 | 
			
		||||
#endif /* LPC18xx_43xx_EMAC_H */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,610 +0,0 @@
 | 
			
		|||
/**********************************************************************
 | 
			
		||||
* Copyright(C) 2011, NXP Semiconductor
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
* Heavily modified by Real Time Engineers ltd.
 | 
			
		||||
***********************************************************************
 | 
			
		||||
* Software that is described herein is for illustrative purposes only
 | 
			
		||||
* which provides customers with programming information regarding the
 | 
			
		||||
* products. This software is supplied "AS IS" without any warranties.
 | 
			
		||||
* NXP Semiconductors assumes no responsibility or liability for the
 | 
			
		||||
* use of the software, conveys no license or title under any patent,
 | 
			
		||||
* copyright, or mask work right to the product. NXP Semiconductors
 | 
			
		||||
* reserves the right to make changes in the software without
 | 
			
		||||
* notification. NXP Semiconductors also make no representation or
 | 
			
		||||
* warranty that such application will be suitable for the specified
 | 
			
		||||
* use without further testing or modification.
 | 
			
		||||
**********************************************************************/
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
#include "task.h"
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS+UDP includes. */
 | 
			
		||||
#include "FreeRTOS_UDP_IP.h"
 | 
			
		||||
#include "FreeRTOS_IP_Private.h"
 | 
			
		||||
#include "NetworkBufferManagement.h"
 | 
			
		||||
 | 
			
		||||
/* Library includes. */
 | 
			
		||||
#include "lpc18xx_emac.h"
 | 
			
		||||
#include "lpc18xx_rgu.h"
 | 
			
		||||
#include "lpc18xx_scu.h"
 | 
			
		||||
#include "lpc18xx_gpio.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define emacTIMEOUT_DELAY	( 2 )
 | 
			
		||||
#define emacNEGOTIATE_DELAY	( 10 / portTICK_RATE_MS )
 | 
			
		||||
 | 
			
		||||
#define emacEXPECTED_RX_STATUS_MASK	( RX_FIRST_SEGM | RX_LAST_SEGM )
 | 
			
		||||
 | 
			
		||||
/* Rx descriptors and data array. */
 | 
			
		||||
static volatile RX_Desc Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
static unsigned int RxDescIndex = 0;
 | 
			
		||||
 | 
			
		||||
/** Rx Status data array - Must be 8-Byte aligned */
 | 
			
		||||
#if defined ( __CC_ARM   )
 | 
			
		||||
	static __align(8) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
#elif defined ( __ICCARM__ )
 | 
			
		||||
	#pragma data_alignment=8
 | 
			
		||||
	static RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
#elif defined   (  __GNUC__  )
 | 
			
		||||
	static volatile __attribute__ ((aligned (8))) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Tx descriptors and status array. */
 | 
			
		||||
static volatile TX_Desc Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
static volatile TX_Stat Tx_Stat[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];
 | 
			
		||||
static unsigned int TxDescIndex = 0;
 | 
			
		||||
 | 
			
		||||
/* Private Functions ---------------------------------------------------------- */
 | 
			
		||||
static void rx_descr_init( void );
 | 
			
		||||
static void tx_descr_init( void );
 | 
			
		||||
static int32_t write_PHY( uint32_t PhyReg, uint16_t Value );
 | 
			
		||||
static int32_t read_PHY( uint32_t PhyReg );
 | 
			
		||||
static void setEmacAddr( uint8_t abStationAddr[] );
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief		Initializes the EMAC peripheral according to the specified
 | 
			
		||||
 *               parameters in the EMAC_ConfigStruct.
 | 
			
		||||
 * @param[in]	EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
 | 
			
		||||
 *                    that contains the configuration information for the
 | 
			
		||||
 *                    specified EMAC peripheral.
 | 
			
		||||
 * @return		None
 | 
			
		||||
 *
 | 
			
		||||
 * Note: This function will initialize EMAC module according to procedure below:
 | 
			
		||||
 *  - Remove the soft reset condition from the MAC
 | 
			
		||||
 *  - Configure the PHY via the MIIM interface of the MAC
 | 
			
		||||
 *  - Select RMII mode
 | 
			
		||||
 *  - Configure the transmit and receive DMA engines, including the descriptor arrays
 | 
			
		||||
 *  - Configure the host registers (MAC1,MAC2 etc.) in the MAC
 | 
			
		||||
 *  - Enable the receive and transmit data paths
 | 
			
		||||
 *  In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
 | 
			
		||||
 *  all remain interrupts are disabled
 | 
			
		||||
 *  (Ref. from LPC17xx UM)
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
portBASE_TYPE EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
 | 
			
		||||
{
 | 
			
		||||
int32_t id1, id2, regv, phy = 0;
 | 
			
		||||
int32_t phy_linkstatus_reg, phy_linkstatus_mask;
 | 
			
		||||
uint32_t x;
 | 
			
		||||
const uint32_t ulMaxAttempts = 250UL;
 | 
			
		||||
portBASE_TYPE xReturn = pdPASS;
 | 
			
		||||
 | 
			
		||||
	/* Enable Ethernet Pins (NGX LPC1830 Xplorer. */
 | 
			
		||||
	scu_pinmux(0x2 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);
 | 
			
		||||
	scu_pinmux(0x1 ,17 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0x1 ,18 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0x1 ,20 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0x1 ,19 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC0);
 | 
			
		||||
	scu_pinmux(0x0 ,1 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC6);
 | 
			
		||||
	scu_pinmux(0x1 ,15 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0x0 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC2);
 | 
			
		||||
	scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0xC ,9 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);
 | 
			
		||||
	scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);
 | 
			
		||||
 | 
			
		||||
	/* Ethernet RESET Pins */
 | 
			
		||||
	scu_pinmux(0x1 ,0 , MD_PUP, FUNC0);
 | 
			
		||||
	GPIO_SetDir(0,(1<<4), 1);
 | 
			
		||||
	GPIO_SetValue(0,(1<<4));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	#if MII				  /*   Select MII interface       */				 // check MUXING for new Eagle...
 | 
			
		||||
	  scu_pinmux(0xC ,6 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_RXD2: PC_6 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0xC ,7 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_RXD3: PC_7 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0xC ,0 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_RXLK: PC_0 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0xC ,2 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_TXD2: PC_2 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0xC ,3 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_TXD3: PC_3 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0xC ,5 , (MD_PLN | MD_EZI | MD_ZI), FUNC3); 	// ENET_TX_ER:  PC_5 -> FUNC3
 | 
			
		||||
	  scu_pinmux(0x0 ,1 , (MD_PLN | MD_EZI | MD_ZI), FUNC2); 	// ENET_COL:  P0_1 -> FUNC2
 | 
			
		||||
	#else				   /*   Select RMII interface     */
 | 
			
		||||
	  LPC_CREG->CREG6 |= RMII_SELECT;
 | 
			
		||||
	#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	RGU_SoftReset( RGU_SIG_ETHERNET );
 | 
			
		||||
 | 
			
		||||
	/* Wait for reset. */
 | 
			
		||||
	while( !( LPC_RGU->RESET_ACTIVE_STATUS0 & ( 1 << ETHERNET_RST ) ) )
 | 
			
		||||
	{
 | 
			
		||||
		vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Reset all GMAC Subsystem internal registers and logic. */
 | 
			
		||||
	LPC_ETHERNET->DMA_BUS_MODE |= DMA_SOFT_RESET;
 | 
			
		||||
 | 
			
		||||
	/* Wait for software reset completion. */
 | 
			
		||||
	while( LPC_ETHERNET->DMA_BUS_MODE & DMA_SOFT_RESET )
 | 
			
		||||
	{
 | 
			
		||||
		vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Put the PHY in reset mode */
 | 
			
		||||
	write_PHY( PHY_REG_BMCR, PHY_BMCR_RESET );
 | 
			
		||||
 | 
			
		||||
	/* Wait for hardware reset to end. */
 | 
			
		||||
	for( x = 0; x < ulMaxAttempts; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		regv = read_PHY (PHY_REG_BMCR);
 | 
			
		||||
		if( !( regv & PHY_BMCR_RESET ) )
 | 
			
		||||
		{
 | 
			
		||||
			/* Reset complete */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( x == ulMaxAttempts )
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check if this is a DP83848C PHY. */
 | 
			
		||||
	id1 = read_PHY( PHY_REG_IDR1 );
 | 
			
		||||
	id2 = read_PHY( PHY_REG_IDR2 );
 | 
			
		||||
	if( ( ( id1 << 16 ) | ( id2 & 0xFFF0 ) ) == DP83848C_ID )
 | 
			
		||||
	{
 | 
			
		||||
		phy = DP83848C_ID;
 | 
			
		||||
	}
 | 
			
		||||
	else if( ( ( id1 << 16 ) | id2 ) == LAN8720_ID )
 | 
			
		||||
	{
 | 
			
		||||
		phy = LAN8720_ID;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( phy != 0 )
 | 
			
		||||
	{
 | 
			
		||||
		/* Use autonegotiation about the link speed. */
 | 
			
		||||
		write_PHY( PHY_REG_BMCR, PHY_AUTO_NEG );
 | 
			
		||||
 | 
			
		||||
		/* Wait to complete Auto_Negotiation. */
 | 
			
		||||
		for( x = 0; x < ulMaxAttempts; x++ )
 | 
			
		||||
		{
 | 
			
		||||
			regv = read_PHY( PHY_REG_BMSR );
 | 
			
		||||
 | 
			
		||||
			if( ( regv & PHY_AUTO_NEG_DONE ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				/* Auto negotiation Complete. */
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				vTaskDelay( emacNEGOTIATE_DELAY );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( x == ulMaxAttempts )
 | 
			
		||||
		{
 | 
			
		||||
			xReturn = pdFAIL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if( xReturn == pdPASS )
 | 
			
		||||
	{
 | 
			
		||||
		/* Default to DP83848C. */
 | 
			
		||||
		phy_linkstatus_reg = PHY_REG_STS;
 | 
			
		||||
		phy_linkstatus_mask = 0x0001;
 | 
			
		||||
 | 
			
		||||
		if( phy == LAN8720_ID )
 | 
			
		||||
		{
 | 
			
		||||
			phy_linkstatus_reg = PHY_REG_BMSR;
 | 
			
		||||
			phy_linkstatus_mask = 0x0004;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Check the link status. */
 | 
			
		||||
		for( x = 0; x < ulMaxAttempts; x++ )
 | 
			
		||||
		{
 | 
			
		||||
			regv = read_PHY( phy_linkstatus_reg );
 | 
			
		||||
 | 
			
		||||
			if( ( regv & phy_linkstatus_mask ) != 0 )
 | 
			
		||||
			{
 | 
			
		||||
				/* Link is on. */
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				vTaskDelay( emacNEGOTIATE_DELAY );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( x == ulMaxAttempts )
 | 
			
		||||
		{
 | 
			
		||||
			xReturn = pdFAIL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		regv = read_PHY( PHY_REG_SPCON );
 | 
			
		||||
		regv &= PHY_REG_HCDSPEED_MASK;
 | 
			
		||||
 | 
			
		||||
		/* Configure 100MBit/10MBit mode and Full/Half Duplex mode. */
 | 
			
		||||
		switch( regv )
 | 
			
		||||
		{
 | 
			
		||||
			case PHY_REG_HCDSPEED_10MB_FULLD:
 | 
			
		||||
				LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case PHY_REG_HCDSPEED_100MB_HALFD:
 | 
			
		||||
				LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case PHY_REG_HCDSPEED_100MB_FULLD:
 | 
			
		||||
				LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;
 | 
			
		||||
				LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Set the Ethernet MAC Address registers */
 | 
			
		||||
		setEmacAddr( EMAC_ConfigStruct->pbEMAC_Addr );
 | 
			
		||||
 | 
			
		||||
		/* Initialize Descriptor Lists    */
 | 
			
		||||
		rx_descr_init();
 | 
			
		||||
		tx_descr_init();
 | 
			
		||||
 | 
			
		||||
		/* Configure Filter
 | 
			
		||||
		LPC_ETHERNET->MAC_FRAME_FILTER is left at its default value.
 | 
			
		||||
		MAC_PROMISCUOUS and MAC_RECEIVEALL can be set if required. */
 | 
			
		||||
 | 
			
		||||
		/* Enable Receiver and Transmitter   */
 | 
			
		||||
		LPC_ETHERNET->MAC_CONFIG |= (MAC_TX_ENABLE | MAC_RX_ENABLE);
 | 
			
		||||
 | 
			
		||||
		/* Enable interrupts    */
 | 
			
		||||
		LPC_ETHERNET->DMA_INT_EN =  DMA_INT_NOR_SUM | DMA_INT_RECEIVE ;
 | 
			
		||||
 | 
			
		||||
		/* Start Transmission & Receive processes   */
 | 
			
		||||
		LPC_ETHERNET->DMA_OP_MODE |= (DMA_SS_TRANSMIT | DMA_SS_RECEIVE );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
portBASE_TYPE EMAC_CheckTransmitIndex( void )
 | 
			
		||||
{
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
 | 
			
		||||
	if( ( Tx_Desc[ TxDescIndex ].Status & OWN_BIT ) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdPASS;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief 		EMAC_SetNextPacketToSend
 | 
			
		||||
 * @param[in] 	pucBuffer
 | 
			
		||||
 * @return 		None
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
void EMAC_SetNextPacketToSend( uint8_t * pucBuffer )
 | 
			
		||||
{
 | 
			
		||||
	/* The old packet is now finished with and can be freed. */
 | 
			
		||||
	vEthernetBufferRelease( ( void * ) Tx_Desc[ TxDescIndex ].Packet );
 | 
			
		||||
 | 
			
		||||
	/* Assign the new packet to the descriptor. */
 | 
			
		||||
	Tx_Desc[ TxDescIndex ].Packet = ( uint32_t ) pucBuffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EMAC_StartTransmitNextBuffer( uint32_t ulLength )
 | 
			
		||||
{
 | 
			
		||||
	Tx_Desc[ TxDescIndex ].Ctrl = ulLength;
 | 
			
		||||
	Tx_Desc[ TxDescIndex ].Status |= OWN_BIT;
 | 
			
		||||
 | 
			
		||||
	/* Wake Up the DMA if it's in Suspended Mode. */
 | 
			
		||||
	LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
 | 
			
		||||
	TxDescIndex++;
 | 
			
		||||
 | 
			
		||||
	if( TxDescIndex == configNUM_TX_ETHERNET_DMA_DESCRIPTORS )
 | 
			
		||||
	{
 | 
			
		||||
		TxDescIndex = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief		Get size of current Received data in received buffer (due to
 | 
			
		||||
 * 				RxConsumeIndex)
 | 
			
		||||
 * @param[in]	None
 | 
			
		||||
 * @return		Size of received data
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
uint32_t EMAC_GetReceiveDataSize(void)
 | 
			
		||||
{
 | 
			
		||||
unsigned short RxLen = 0;
 | 
			
		||||
 | 
			
		||||
	RxLen = ( Rx_Desc[ RxDescIndex ].Status >> 16 ) & 0x03FFF;
 | 
			
		||||
	return RxLen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief		Increase the RxConsumeIndex (after reading the Receive buffer
 | 
			
		||||
 * 				to release the Receive buffer) and wrap-around the index if
 | 
			
		||||
 * 				it reaches the maximum Receive Number
 | 
			
		||||
 * @param[in]	None
 | 
			
		||||
 * @return		None
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
void EMAC_UpdateRxConsumeIndex( void )
 | 
			
		||||
{
 | 
			
		||||
	Rx_Desc[ RxDescIndex ].Status = OWN_BIT;
 | 
			
		||||
	RxDescIndex++;
 | 
			
		||||
 | 
			
		||||
	if( RxDescIndex == configNUM_RX_ETHERNET_DMA_DESCRIPTORS )
 | 
			
		||||
	{
 | 
			
		||||
		RxDescIndex = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief		Check whether if the current RxConsumeIndex is not equal to the
 | 
			
		||||
 * 				current RxProduceIndex.
 | 
			
		||||
 * @param[in]	None
 | 
			
		||||
 * @return		TRUE if they're not equal, otherwise return FALSE
 | 
			
		||||
 *
 | 
			
		||||
 * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
 | 
			
		||||
 * it means there're available data has been received. They should be read
 | 
			
		||||
 * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
portBASE_TYPE EMAC_CheckReceiveIndex(void)
 | 
			
		||||
{
 | 
			
		||||
portBASE_TYPE xReturn;
 | 
			
		||||
 | 
			
		||||
	if( ( Rx_Desc[ RxDescIndex ].Status & OWN_BIT ) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdPASS;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		xReturn = pdFAIL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return xReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EMAC_NextPacketToRead( xNetworkBufferDescriptor_t *pxNetworkBuffer )
 | 
			
		||||
{
 | 
			
		||||
uint8_t *pucTemp;
 | 
			
		||||
 | 
			
		||||
	/* Swap the buffer in the network buffer with the buffer used by the DMA.
 | 
			
		||||
	This allows the data to be passed out without having to perform any copies. */
 | 
			
		||||
	pucTemp = ( uint8_t * ) Rx_Desc[ RxDescIndex ].Packet;
 | 
			
		||||
	Rx_Desc[ RxDescIndex ].Packet = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;
 | 
			
		||||
	pxNetworkBuffer->pucEthernetBuffer = pucTemp;
 | 
			
		||||
 | 
			
		||||
	/* Only supports frames coming in single buffers.  If this frame is split
 | 
			
		||||
	across multiple buffers then reject it (and if the frame is needed increase
 | 
			
		||||
	the ipconfigNETWORK_MTU setting). */
 | 
			
		||||
	if( ( Rx_Desc[ RxDescIndex ].Status & emacEXPECTED_RX_STATUS_MASK ) != emacEXPECTED_RX_STATUS_MASK )
 | 
			
		||||
	{
 | 
			
		||||
		pxNetworkBuffer->xDataLength = 0;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		pxNetworkBuffer->xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( ipETHERNET_CRC_BYTES - 1U );;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief 		Initializes RX Descriptor
 | 
			
		||||
 * @param[in] 	None
 | 
			
		||||
 * @return 		None
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
static void rx_descr_init( void )
 | 
			
		||||
{
 | 
			
		||||
uint32_t x;
 | 
			
		||||
size_t xBufferSize = ipTOTAL_ETHERNET_FRAME_SIZE;
 | 
			
		||||
 | 
			
		||||
	for( x = 0; x < configNUM_RX_ETHERNET_DMA_DESCRIPTORS; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		/* Obtain the buffer first, as the size of the buffer might be changed
 | 
			
		||||
		within the pucEthernetBufferGet() call. */
 | 
			
		||||
		Rx_Desc[ x ].Packet  = ( uint32_t ) pucEthernetBufferGet( &xBufferSize );
 | 
			
		||||
		Rx_Desc[ x ].Status = OWN_BIT;
 | 
			
		||||
		Rx_Desc[ x ].Ctrl  = xBufferSize;
 | 
			
		||||
		Rx_Desc[ x ].NextDescripter = ( uint32_t ) &Rx_Desc[ x + 1 ];
 | 
			
		||||
		
 | 
			
		||||
		configASSERT( ( ( ( uint32_t ) Rx_Desc[x].Packet ) & 0x07 ) == 0 );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Last Descriptor */
 | 
			
		||||
	Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS - 1 ].Ctrl |= RX_END_RING;
 | 
			
		||||
 | 
			
		||||
	RxDescIndex = 0;
 | 
			
		||||
 | 
			
		||||
	/* Set Starting address of RX Descriptor list */
 | 
			
		||||
	LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) Rx_Desc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief 		Initializes TX Descriptor
 | 
			
		||||
 * @param[in] 	None
 | 
			
		||||
 * @return 		None
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
static void tx_descr_init( void )
 | 
			
		||||
{
 | 
			
		||||
/* Initialize Transmit Descriptor and Status array. */
 | 
			
		||||
uint32_t x;
 | 
			
		||||
 | 
			
		||||
	for( x = 0; x < configNUM_TX_ETHERNET_DMA_DESCRIPTORS; x++ )
 | 
			
		||||
	{
 | 
			
		||||
		Tx_Desc[ x ].Status = TX_LAST_SEGM | TX_FIRST_SEGM;
 | 
			
		||||
		Tx_Desc[ x ].Ctrl  = 0;
 | 
			
		||||
		Tx_Desc[ x ].NextDescripter = ( uint32_t ) &Tx_Desc[ x + 1 ];
 | 
			
		||||
 | 
			
		||||
		/* Packet is assigned when a Tx is initiated. */
 | 
			
		||||
		Tx_Desc[ x ].Packet   = ( uint32_t )NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Last Descriptor? */
 | 
			
		||||
	Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS-1 ].Status |= TX_END_RING;
 | 
			
		||||
 | 
			
		||||
	/* Set Starting address of TX Descriptor list */
 | 
			
		||||
	LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) Tx_Desc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief 		Write value to PHY device
 | 
			
		||||
 * @param[in] 	PhyReg: PHY Register address
 | 
			
		||||
 * @param[in] 	Value:  Value to write
 | 
			
		||||
 * @return 		0 - if success
 | 
			
		||||
 * 				1 - if fail
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
 | 
			
		||||
{
 | 
			
		||||
uint32_t x;
 | 
			
		||||
const uint32_t ulMaxAttempts = 250UL;
 | 
			
		||||
int32_t lReturn = pdPASS;
 | 
			
		||||
 | 
			
		||||
	/* Write a data 'Value' to PHY register 'PhyReg'. */
 | 
			
		||||
	x = 0;
 | 
			
		||||
	while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )
 | 
			
		||||
	{
 | 
			
		||||
		x++;
 | 
			
		||||
 | 
			
		||||
		if( x >= ulMaxAttempts )
 | 
			
		||||
		{
 | 
			
		||||
			/* Time out. */
 | 
			
		||||
			lReturn = pdFAIL;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* GMII is busy. */
 | 
			
		||||
			vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( lReturn == pdPASS )
 | 
			
		||||
	{
 | 
			
		||||
		LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_WRITE;
 | 
			
		||||
		LPC_ETHERNET->MAC_MII_DATA = Value;
 | 
			
		||||
 | 
			
		||||
		/* Start PHY Write Cycle. */
 | 
			
		||||
		LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;
 | 
			
		||||
 | 
			
		||||
		/* Wait untl operation completed. */
 | 
			
		||||
		for( x = 0; x < ulMaxAttempts; x++ )
 | 
			
		||||
		{
 | 
			
		||||
			if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if( x == ulMaxAttempts )
 | 
			
		||||
		{
 | 
			
		||||
			/* Timeout. */
 | 
			
		||||
			lReturn = pdFAIL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief 		Read value from PHY device
 | 
			
		||||
 * @param[in] 	PhyReg: PHY Register address
 | 
			
		||||
 * @return 		0 - if success
 | 
			
		||||
 * 				1 - if fail
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
static int32_t read_PHY( uint32_t PhyReg )
 | 
			
		||||
{
 | 
			
		||||
int32_t lValue = 0;
 | 
			
		||||
uint32_t x;
 | 
			
		||||
const uint32_t ulMaxAttempts = 250UL;
 | 
			
		||||
 | 
			
		||||
	/* Write a data 'Value' to PHY register 'PhyReg'. */
 | 
			
		||||
	x = 0;
 | 
			
		||||
	while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )
 | 
			
		||||
	{
 | 
			
		||||
		x++;
 | 
			
		||||
 | 
			
		||||
		if( x >= ulMaxAttempts )
 | 
			
		||||
		{
 | 
			
		||||
			/* Time out. */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* GMII is busy. */
 | 
			
		||||
			vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( x < ulMaxAttempts )
 | 
			
		||||
	{
 | 
			
		||||
		/* Read a PHY register 'PhyReg'. */
 | 
			
		||||
		LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_READ;
 | 
			
		||||
 | 
			
		||||
		/* Start PHY Read Cycle. */
 | 
			
		||||
		LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;
 | 
			
		||||
 | 
			
		||||
		/* Wait until operation completed */
 | 
			
		||||
		for( x = 0; x < ulMaxAttempts; x++ )
 | 
			
		||||
		{
 | 
			
		||||
			if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				vTaskDelay( emacTIMEOUT_DELAY );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		configASSERT( x != ulMaxAttempts );
 | 
			
		||||
		lValue = LPC_ETHERNET->MAC_MII_DATA;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************************************************************//**
 | 
			
		||||
 * @brief		Set Station MAC address for EMAC module
 | 
			
		||||
 * @param[in]	abStationAddr Pointer to Station address that contains 6-bytes
 | 
			
		||||
 * 				of MAC address (should be in order from MAC Address 1 to MAC Address 6)
 | 
			
		||||
 * @return		None
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
static void setEmacAddr( uint8_t abStationAddr[] )
 | 
			
		||||
{
 | 
			
		||||
	/* Set the Ethernet MAC Address registers */
 | 
			
		||||
	LPC_ETHERNET->MAC_ADDR0_HIGH = (( uint32_t ) abStationAddr[ 5 ] << 8 ) | ( uint32_t )abStationAddr[ 4 ];
 | 
			
		||||
	LPC_ETHERNET->MAC_ADDR0_LOW =	(( uint32_t )abStationAddr[ 3 ] << 24) | (( uint32_t )abStationAddr[ 2 ] << 16) | (( uint32_t )abStationAddr[ 1 ] << 8 ) | ( uint32_t )abStationAddr[ 0 ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,238 +0,0 @@
 | 
			
		|||
/***********************************************************************//**
 | 
			
		||||
 * @file		lpc17xx_emac.h
 | 
			
		||||
 * @brief		Contains all macro definitions and function prototypes
 | 
			
		||||
 * 				support for Ethernet MAC firmware library on LPC17xx
 | 
			
		||||
 * @version		2.0
 | 
			
		||||
 * @date		21. May. 2010
 | 
			
		||||
 * @author		NXP MCU SW Application Team
 | 
			
		||||
 **************************************************************************
 | 
			
		||||
 * Software that is described herein is for illustrative purposes only
 | 
			
		||||
 * which provides customers with programming information regarding the
 | 
			
		||||
 * products. This software is supplied "AS IS" without any warranties.
 | 
			
		||||
 * NXP Semiconductors assumes no responsibility or liability for the
 | 
			
		||||
 * use of the software, conveys no license or title under any patent,
 | 
			
		||||
 * copyright, or mask work right to the product. NXP Semiconductors
 | 
			
		||||
 * reserves the right to make changes in the software without
 | 
			
		||||
 * notification. NXP Semiconductors also make no representation or
 | 
			
		||||
 * warranty that such application will be suitable for the specified
 | 
			
		||||
 * use without further testing or modification.
 | 
			
		||||
 **************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* Peripheral group ----------------------------------------------------------- */
 | 
			
		||||
/** @defgroup EMAC EMAC
 | 
			
		||||
 * @ingroup LPC1700CMSIS_FwLib_Drivers
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LPC18XX_EMAC_H_
 | 
			
		||||
#define LPC18XX_EMAC_H_
 | 
			
		||||
 | 
			
		||||
/* Includes ------------------------------------------------------------------- */
 | 
			
		||||
#include "LPC18xx.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "lpc_types.h"
 | 
			
		||||
 | 
			
		||||
/* Configuration */
 | 
			
		||||
 | 
			
		||||
/* Interface Selection */
 | 
			
		||||
#define MII				0		// =0 RMII  -  =1 MII
 | 
			
		||||
 | 
			
		||||
/* End of Configuration   */
 | 
			
		||||
 | 
			
		||||
/*  Descriptors Fields bits       */
 | 
			
		||||
#define OWN_BIT				(1U<<31)	/*  Own bit in RDES0 & TDES0              */
 | 
			
		||||
#define RX_END_RING			(1<<15)		/*  Receive End of Ring bit in RDES1      */
 | 
			
		||||
#define RX_NXTDESC_FLAG		(1<<14)		/*  Second Address Chained bit in RDES1   */
 | 
			
		||||
#define TX_LAST_SEGM		(1<<29)		/*  Last Segment bit in TDES0             */
 | 
			
		||||
#define RX_LAST_SEGM		(1<<9)
 | 
			
		||||
#define TX_FIRST_SEGM		(1<<28)		/*  First Segment bit in TDES0            */
 | 
			
		||||
#define RX_FIRST_SEGM		(1<<8)		/*  First Segment bit in TDES0            */
 | 
			
		||||
#define TX_END_RING			(1<<21)		/*  Transmit End of Ring bit in TDES0     */
 | 
			
		||||
#define TX_NXTDESC_FLAG		(1<<20)		/*  Second Address Chained bit in TDES0   */
 | 
			
		||||
 | 
			
		||||
/* EMAC Memory Buffer configuration for 16K Ethernet RAM */
 | 
			
		||||
#define EMAC_ETH_MAX_FLEN 		ipETHERNET_FRAME_SIZE_TO_USE
 | 
			
		||||
 | 
			
		||||
/* NOTE: EMAC_NUM_RX_FRAG is not used by the example FreeRTOS drivers - use
 | 
			
		||||
configNUM_RX_ETHERNET_DMA_DESCRIPTORS. */
 | 
			
		||||
#define EMAC_NUM_RX_FRAG         6           /**< Num.of RX Fragments */
 | 
			
		||||
 | 
			
		||||
/* NOTE: EMAC_NUM_TX_FRAG is not used by the example FreeRTOS drivers - use
 | 
			
		||||
configNUM_TX_ETHERNET_DMA_DESCRIPTORS. */
 | 
			
		||||
#define EMAC_NUM_TX_FRAG         2           /**< Num.of TX Fragments */
 | 
			
		||||
 | 
			
		||||
/* EMAC Control and Status bits   */
 | 
			
		||||
#define MAC_RX_ENABLE	 (1<<2)			/*  Receiver Enable in MAC_CONFIG reg      */
 | 
			
		||||
#define MAC_TX_ENABLE	 (1<<3)			/*  Transmitter Enable in MAC_CONFIG reg   */
 | 
			
		||||
#define MAC_PADCRC_STRIP (1<<7)			/*  Automatic Pad-CRC Stripping in MAC_CONFIG reg   */
 | 
			
		||||
#define MAC_DUPMODE		 (1<<11)		/*  Duplex Mode in  MAC_CONFIG reg         */
 | 
			
		||||
#define MAC_100MPS		 (1<<14)		/*  Speed is 100Mbps in MAC_CONFIG reg     */
 | 
			
		||||
#define MAC_PROMISCUOUS  (1U<<0)		/*  Promiscuous Mode bit in MAC_FRAME_FILTER reg    */
 | 
			
		||||
#define MAC_DIS_BROAD    (1U<<5)		/*  Disable Broadcast Frames bit in	MAC_FRAME_FILTER reg    */
 | 
			
		||||
#define MAC_RECEIVEALL   (1U<<31)       /*  Receive All bit in MAC_FRAME_FILTER reg    */
 | 
			
		||||
#define DMA_SOFT_RESET	  0x01          /*  Software Reset bit in DMA_BUS_MODE reg */
 | 
			
		||||
#define DMA_SS_RECEIVE   (1<<1)         /*  Start/Stop Receive bit in DMA_OP_MODE reg  */
 | 
			
		||||
#define DMA_SS_TRANSMIT  (1<<13)        /*  Start/Stop Transmission bit in DMA_OP_MODE reg  */
 | 
			
		||||
#define DMA_INT_TRANSMIT (1<<0)         /*  Transmit Interrupt Enable bit in DMA_INT_EN reg */
 | 
			
		||||
#define DMA_INT_OVERFLOW (1<<4)         /*  Overflow Interrupt Enable bit in DMA_INT_EN reg */
 | 
			
		||||
#define DMA_INT_UNDERFLW (1<<5)         /*  Underflow Interrupt Enable bit in DMA_INT_EN reg */
 | 
			
		||||
#define DMA_INT_RECEIVE  (1<<6)         /*  Receive Interrupt Enable bit in DMA_INT_EN reg */
 | 
			
		||||
#define DMA_INT_ABN_SUM  (1<<15)        /*  Abnormal Interrupt Summary Enable bit in DMA_INT_EN reg */
 | 
			
		||||
#define DMA_INT_NOR_SUM  (1<<16)        /*  Normal Interrupt Summary Enable bit in DMA_INT_EN reg */
 | 
			
		||||
 | 
			
		||||
/* MII Management Command Register */
 | 
			
		||||
#define GMII_READ           (0<<1)		/* GMII Read PHY                     */
 | 
			
		||||
#define GMII_WRITE          (1<<1)      /* GMII Write PHY                    */
 | 
			
		||||
#define GMII_BUSY           0x00000001  /* GMII is Busy / Start Read/Write   */
 | 
			
		||||
#define MII_WR_TOUT         0x00050000  /* MII Write timeout count           */
 | 
			
		||||
#define MII_RD_TOUT         0x00050000  /* MII Read timeout count            */
 | 
			
		||||
 | 
			
		||||
/* MII Management Address Register */
 | 
			
		||||
#define MADR_PHY_ADR        0x00001F00  /* PHY Address Mask                  */
 | 
			
		||||
 | 
			
		||||
/* LAN8720 PHY Registers */
 | 
			
		||||
#define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
 | 
			
		||||
#define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
 | 
			
		||||
#define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
 | 
			
		||||
#define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
 | 
			
		||||
#define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
 | 
			
		||||
#define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
 | 
			
		||||
#define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
 | 
			
		||||
#define PHY_REG_ANNPTR      0x07        /* Auto-Neg. Next Page TX            */
 | 
			
		||||
 | 
			
		||||
/* LAN8720 PHY Speed identify */
 | 
			
		||||
#define PHY_REG_SPCON    				0x1f   /* Speed indication Register     */
 | 
			
		||||
#define PHY_REG_HCDSPEED_MASK    		0x1c   /* Speed indication Register mask*/
 | 
			
		||||
#define PHY_REG_HCDSPEED_10MB_HALFD    	0x04   /* Speed is 10Mbps HALF-duplex   */
 | 
			
		||||
#define PHY_REG_HCDSPEED_10MB_FULLD    	0x14   /* Speed is 10Mbps FULL-duplex   */
 | 
			
		||||
#define PHY_REG_HCDSPEED_100MB_HALFD    0x08   /* Speed is 100Mbps HALF-duplex  */
 | 
			
		||||
#define PHY_REG_HCDSPEED_100MB_FULLD    0x18   /* Speed is 100Mbps FULL-duplex  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* PHY Extended Registers */
 | 
			
		||||
#define PHY_REG_STS         0x10        /* Status Register                   */
 | 
			
		||||
#define PHY_REG_MICR        0x11        /* MII Interrupt Control Register    */
 | 
			
		||||
#define PHY_REG_MISR        0x12        /* MII Interrupt Status Register     */
 | 
			
		||||
#define PHY_REG_FCSCR       0x14        /* False Carrier Sense Counter       */
 | 
			
		||||
#define PHY_REG_RECR        0x15        /* Receive Error Counter             */
 | 
			
		||||
#define PHY_REG_PCSR        0x16        /* PCS Sublayer Config. and Status   */
 | 
			
		||||
#define PHY_REG_RBR         0x17        /* RMII and Bypass Register          */
 | 
			
		||||
#define PHY_REG_LEDCR       0x18        /* LED Direct Control Register       */
 | 
			
		||||
#define PHY_REG_PHYCR       0x19        /* PHY Control Register              */
 | 
			
		||||
#define PHY_REG_10BTSCR     0x1A        /* 10Base-T Status/Control Register  */
 | 
			
		||||
#define PHY_REG_CDCTRL1     0x1B        /* CD Test Control and BIST Extens.  */
 | 
			
		||||
#define PHY_REG_EDCR        0x1D        /* Energy Detect Control Register    */
 | 
			
		||||
 | 
			
		||||
/* PHY Control and Status bits  */
 | 
			
		||||
#define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
 | 
			
		||||
#define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
 | 
			
		||||
#define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
 | 
			
		||||
#define PHY_HALFD_10M       0x0000      /* Half Duplex 10MBit                */
 | 
			
		||||
#define PHY_AUTO_NEG        0x1000      /* Select Auto Negotiation           */
 | 
			
		||||
#define PHY_AUTO_NEG_DONE   0x0020		/* AutoNegotiation Complete in BMSR PHY reg  */
 | 
			
		||||
#define PHY_BMCR_RESET		0x8000		/* Reset bit at BMCR PHY reg         */
 | 
			
		||||
#define LINK_VALID_STS		0x0001		/* Link Valid Status at REG_STS PHY reg	 */
 | 
			
		||||
#define FULL_DUP_STS		0x0004		/* Full Duplex Status at REG_STS PHY reg */
 | 
			
		||||
#define SPEED_10M_STS		0x0002		/* 10Mbps Status at REG_STS PHY reg */
 | 
			
		||||
 | 
			
		||||
#define DP83848C_DEF_ADR    0x01        /* Default PHY device address        */
 | 
			
		||||
#define DP83848C_ID         0x20005C90  /* PHY Identifier (without Rev. info */
 | 
			
		||||
#define LAN8720_ID			0x0007C0F1  /* PHY Identifier for SMSC PHY       */
 | 
			
		||||
 | 
			
		||||
/*  Misc    */
 | 
			
		||||
#define ETHERNET_RST		22			/* 	Reset Output for EMAC at RGU     */
 | 
			
		||||
#define RMII_SELECT			0x04		/*  Select RMII in EMACCFG           */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief EMAC configuration structure definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t	Mode;						/**< Supported EMAC PHY device speed, should be one of the following:
 | 
			
		||||
											- EMAC_MODE_AUTO
 | 
			
		||||
											- EMAC_MODE_10M_FULL
 | 
			
		||||
											- EMAC_MODE_10M_HALF
 | 
			
		||||
											- EMAC_MODE_100M_FULL
 | 
			
		||||
											- EMAC_MODE_100M_HALF
 | 
			
		||||
											*/
 | 
			
		||||
	uint8_t 	*pbEMAC_Addr;				/**< Pointer to EMAC Station address that contains 6-bytes
 | 
			
		||||
											of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5])
 | 
			
		||||
											*/
 | 
			
		||||
} EMAC_CFG_Type;
 | 
			
		||||
 | 
			
		||||
/* Descriptor and status formats ---------------------------------------------- */
 | 
			
		||||
/**
 | 
			
		||||
 * @brief RX Descriptor structure type definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t Status;		/**< Receive Status  Descriptor */
 | 
			
		||||
	uint32_t Ctrl;			/**< Receive Control Descriptor */
 | 
			
		||||
	uint32_t Packet;		/**< Receive Packet Descriptor */
 | 
			
		||||
	uint32_t NextDescripter;/**< Receive Next Descriptor Address */
 | 
			
		||||
} RX_Desc;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief RX Status structure type definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t Info;		/**< Receive Information Status */
 | 
			
		||||
	uint32_t HashCRC;	/**< Receive Hash CRC Status */
 | 
			
		||||
} RX_Stat;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief TX Descriptor structure type definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t Status;		/**< Transmit Status  Descriptor */
 | 
			
		||||
	uint32_t Ctrl;		/**< Transmit Control Descriptor */
 | 
			
		||||
	uint32_t Packet;	/**< Transmit Packet Descriptor */
 | 
			
		||||
	uint32_t NextDescripter;	/**< Transmit Next Descriptor Address */
 | 
			
		||||
} TX_Desc;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief TX Status structure type definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
   uint32_t Info;		/**< Transmit Information Status */
 | 
			
		||||
} TX_Stat;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief TX Data Buffer structure definition
 | 
			
		||||
 */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	uint32_t ulDataLen;			/**< Data length */
 | 
			
		||||
	uint32_t *pbDataBuf;		/**< A word-align data pointer to data buffer */
 | 
			
		||||
} EMAC_PACKETBUF_Type;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  Prototypes               */
 | 
			
		||||
portBASE_TYPE EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct);
 | 
			
		||||
int32_t EMAC_UpdatePHYStatus(void);
 | 
			
		||||
uint32_t EMAC_GetReceiveDataSize(void);
 | 
			
		||||
void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
 | 
			
		||||
void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
 | 
			
		||||
void EMAC_NextPacketToRead( xNetworkBufferDescriptor_t *pxNetworkBuffer );
 | 
			
		||||
void EMAC_UpdateRxConsumeIndex(void);
 | 
			
		||||
portBASE_TYPE EMAC_CheckReceiveIndex(void);
 | 
			
		||||
portBASE_TYPE EMAC_CheckTransmitIndex(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* LPC18XX_EMAC_H_ */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @}
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* --------------------------------- End Of File ------------------------------ */
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue