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. */
( 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. */
}
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. */
( 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,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,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 ------------------------------ */