Update the FreeRTOS+UDP LPC18xx MAC driver to use the LPCOpen drivers.

This commit is contained in:
Richard Barry 2013-06-03 20:27:46 +00:00
parent 54c62d429f
commit f9d0a153b4
5 changed files with 446 additions and 911 deletions

View file

@ -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();
}
}
}

View file

@ -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 );
}

View file

@ -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 */

View file

@ -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 ];
}

View file

@ -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 ------------------------------ */