-/******************************************************************\r
- ***** *****\r
- ***** Ver.: 1.0 *****\r
- ***** Date: 07/05/2001 *****\r
- ***** Auth: Andreas Dannenberg *****\r
- ***** HTWK Leipzig *****\r
- ***** university of applied sciences *****\r
- ***** Germany *****\r
- ***** Func: ethernet packet-driver for use with LAN- *****\r
- ***** controller CS8900 from Crystal/Cirrus Logic *****\r
- ***** *****\r
- ***** Keil: Module modified for use with Philips *****\r
- ***** LPC2378 EMAC Ethernet controller *****\r
- ***** *****\r
- ******************************************************************/\r
-\r
-/* Adapted from file originally written by Andreas Dannenberg. Supplied with permission. */\r
+/*\r
+ FreeRTOS.org V5.3.1 - Copyright (C) 2003-2009 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify it\r
+ under the terms of the GNU General Public License (version 2) as published\r
+ by the Free Software Foundation and modified by the FreeRTOS exception.\r
+ **NOTE** The exception to the GPL is included to allow you to distribute a\r
+ combined work that includes FreeRTOS.org without being obliged to provide\r
+ the source code for any proprietary components. Alternative commercial\r
+ license and support terms are also available upon request. See the\r
+ licensing section of http://www.FreeRTOS.org for full details.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\r
+ more details.\r
+\r
+ You should have received a copy of the GNU General Public License along\r
+ with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59\r
+ Temple Place, Suite 330, Boston, MA 02111-1307 USA.\r
+\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ * This is a concise, step by step, 'hands on' guide that describes both *\r
+ * general multitasking concepts and FreeRTOS specifics. It presents and *\r
+ * explains numerous examples that are written using the FreeRTOS API. *\r
+ * Full source code for all the examples is provided in an accompanying *\r
+ * .zip file. *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ 1 tab == 4 spaces!\r
+\r
+ Please ensure to read the configuration and relevant port sections of the\r
+ online documentation.\r
+\r
+ http://www.FreeRTOS.org - Documentation, latest information, license and\r
+ contact details.\r
+\r
+ http://www.SafeRTOS.com - A version that is certified for use in safety\r
+ critical systems.\r
+\r
+ http://www.OpenRTOS.com - Commercial support, development, porting,\r
+ licensing and training services.\r
+*/\r
+\r
+/* Originally adapted from file written by Andreas Dannenberg. Supplied with permission. */\r
+\r
+/* Kernel includes. */\r
#include "FreeRTOS.h"\r
-#include "semphr.h"\r
#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware specific includes. */\r
#include "LPC17xx_defs.h"\r
#include "EthDev_LPC17xx.h"\r
\r
-#define emacPINSEL2_VALUE 0x50150105\r
-\r
+/* Time to wait between each inspection of the link status. */\r
#define emacWAIT_FOR_LINK_TO_ESTABLISH ( 500 / portTICK_RATE_MS )\r
+\r
+/* Short delay used in several places during the initialisation process. */\r
#define emacSHORT_DELAY ( 2 )\r
\r
+/* Hardware specific bit definitions. */\r
#define emacLINK_ESTABLISHED ( 0x0001 )\r
#define emacFULL_DUPLEX_ENABLED ( 0x0004 )\r
#define emac10BASE_T_MODE ( 0x0002 )\r
+#define emacPINSEL2_VALUE 0x50150105\r
\r
/* If no buffers are available, then wait this long before looking again.... */\r
#define emacBUFFER_WAIT_DELAY ( 3 / portTICK_RATE_MS )\r
/* ...and don't look more than this many times. */\r
#define emacBUFFER_WAIT_ATTEMPTS ( 30 )\r
\r
+/* Index to the Tx descriptor that is always used first for every Tx. The second\r
+descriptor is then used to re-send in order to speed up the uIP Tx process. */\r
#define emacTX_DESC_INDEX ( 0 )\r
\r
-/* The semaphore used to wake the uIP task when data arives. */\r
-extern xSemaphoreHandle xEMACSemaphore;\r
-\r
-static unsigned short *rptr;\r
-static unsigned short *tptr;\r
+/*-----------------------------------------------------------*/\r
\r
+/*\r
+ * Configure both the Rx and Tx descriptors during the init process.\r
+ */\r
static void prvInitDescriptors( void );\r
+\r
+/*\r
+ * Setup the IO and peripherals required for Ethernet communication.\r
+ */\r
static void prvSetupEMACHardware( void );\r
+\r
+/*\r
+ * Control the auto negotiate process.\r
+ */\r
static void prvConfigurePHY( void );\r
+\r
+/*\r
+ * Wait for a link to be established, then setup the PHY according to the link\r
+ * parameters.\r
+ */\r
static long prvSetupLinkStatus( void );\r
+\r
+/*\r
+ * Search the pool of buffers to find one that is free. If a buffer is found\r
+ * mark it as in use before returning its address.\r
+ */\r
static unsigned char *prvGetNextBuffer( void );\r
+\r
+/*\r
+ * Return an allocated buffer to the pool of free buffers.\r
+ */\r
static void prvReturnBuffer( unsigned char *pucBuffer );\r
\r
-/* Each ucBufferInUse index corresponds to a position in the same index in the\r
-ucMACBuffers array. If the index contains a 1 then the buffer within\r
-ucMACBuffers is in use, if it contains a 0 then the buffer is free. */\r
+/*\r
+ * Send lValue to the lPhyReg within the PHY.\r
+ */\r
+static long prvWritePHY( long lPhyReg, long lValue );\r
+\r
+/*\r
+ * Read a value from ucPhyReg within the PHY. *plStatus will be set to\r
+ * pdFALSE if there is an error.\r
+ */\r
+static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The semaphore used to wake the uIP task when data arrives. */\r
+extern xSemaphoreHandle xEMACSemaphore;\r
+\r
+/* Each ucBufferInUse index corresponds to a position in the pool of buffers.\r
+If the index contains a 1 then the buffer within pool is in use, if it\r
+contains a 0 then the buffer is free. */\r
static unsigned char ucBufferInUse[ ETH_NUM_BUFFERS ] = { pdFALSE };\r
\r
/* The uip_buffer is not a fixed array, but instead gets pointed to the buffers\r
\r
/*-----------------------------------------------------------*/\r
\r
-int write_PHY( long lPhyReg, long lValue )\r
+long lEMACInit( void )\r
{\r
-const long lMaxTime = 10;\r
-long x;\r
+long lReturn = pdPASS;\r
+volatile unsigned long regv, tout;\r
+unsigned long ulID1, ulID2;\r
\r
- MAC_MADR = DP83848C_DEF_ADR | lPhyReg;\r
- MAC_MWTD = lValue;\r
+ /* Reset peripherals, configure port pins and registers. */\r
+ prvSetupEMACHardware();\r
\r
- x = 0;\r
- for( x = 0; x < lMaxTime; x++ )\r
+ /* Check the PHY part number is as expected. */\r
+ ulID1 = prvReadPHY( PHY_REG_IDR1, &lReturn );\r
+ ulID2 = prvReadPHY( PHY_REG_IDR2, &lReturn );\r
+ if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) == DP83848C_ID )\r
{\r
- if( ( MAC_MIND & MIND_BUSY ) == 0 )\r
- {\r
- /* Operation has finished. */\r
- break;\r
- }\r
+ /* Set the Ethernet MAC Address registers */\r
+ MAC_SA0 = ( configMAC_ADDR0 << 8 ) | configMAC_ADDR1;\r
+ MAC_SA1 = ( configMAC_ADDR2 << 8 ) | configMAC_ADDR3;\r
+ MAC_SA2 = ( configMAC_ADDR4 << 8 ) | configMAC_ADDR5;\r
\r
- vTaskDelay( emacSHORT_DELAY );\r
- }\r
+ /* Initialize Tx and Rx DMA Descriptors */\r
+ prvInitDescriptors();\r
\r
- if( x < lMaxTime )\r
- {\r
- return pdPASS;\r
+ /* Receive broadcast and perfect match packets */\r
+ MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;\r
+\r
+ /* Setup the PHY. */\r
+ prvConfigurePHY();\r
}\r
else\r
{\r
- return pdFAIL;\r
+ lReturn = pdFAIL;\r
}\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-unsigned short read_PHY( unsigned char ucPhyReg, long *plStatus )\r
-{\r
-long x;\r
-const long lMaxTime = 10;\r
\r
- MAC_MADR = DP83848C_DEF_ADR | ucPhyReg;\r
- MAC_MCMD = MCMD_READ;\r
-\r
- for( x = 0; x < lMaxTime; x++ )\r
+ /* Check the link status. */\r
+ if( lReturn == pdPASS )\r
{\r
- /* Operation has finished. */\r
- if( ( MAC_MIND & MIND_BUSY ) == 0 )\r
- {\r
- break;\r
- }\r
-\r
- vTaskDelay( emacSHORT_DELAY );\r
+ lReturn = prvSetupLinkStatus();\r
}\r
\r
- MAC_MCMD = 0;\r
-\r
- if( x >= lMaxTime )\r
+ if( lReturn == pdPASS )\r
{\r
- *plStatus = pdFAIL;\r
+ /* Initialise uip_buf to ensure it points somewhere valid. */\r
+ uip_buf = prvGetNextBuffer();\r
+\r
+ /* Reset all interrupts */\r
+ MAC_INTCLEAR = ( INT_RX_OVERRUN | INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP );\r
+\r
+ /* Enable receive and transmit mode of MAC Ethernet core */\r
+ MAC_COMMAND |= ( CR_RX_EN | CR_TX_EN );\r
+ MAC_MAC1 |= MAC1_REC_EN;\r
}\r
\r
- return( MAC_MRDD );\r
+ return lReturn;\r
}\r
/*-----------------------------------------------------------*/\r
\r
MAC_SUPP = 0;\r
\r
/* Put the PHY in reset mode */\r
- write_PHY( PHY_REG_BMCR, MCFG_RES_MII );\r
- write_PHY( PHY_REG_BMCR, MCFG_RES_MII );\r
+ prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );\r
+ prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );\r
\r
/* Wait for hardware reset to end. */\r
for( x = 0; x < 100; x++ )\r
{\r
vTaskDelay( emacSHORT_DELAY * 5 );\r
- us = read_PHY( PHY_REG_BMCR, &lDummy );\r
+ us = prvReadPHY( PHY_REG_BMCR, &lDummy );\r
if( !( us & MCFG_RES_MII ) )\r
{\r
/* Reset complete */\r
long x, lDummy;\r
\r
/* Auto negotiate the configuration. */\r
- if( write_PHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )\r
+ if( prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )\r
{\r
vTaskDelay( emacSHORT_DELAY * 5 );\r
\r
for( x = 0; x < 10; x++ )\r
{\r
- us = read_PHY( PHY_REG_BMSR, &lDummy );\r
+ us = prvReadPHY( PHY_REG_BMSR, &lDummy );\r
\r
if( us & PHY_AUTO_NEG_COMPLETE )\r
{\r
long lReturn = pdFAIL, x;\r
unsigned short usLinkStatus;\r
\r
+ /* Wait with timeout for the link to be established. */\r
for( x = 0; x < 10; x++ )\r
{\r
- usLinkStatus = read_PHY( PHY_REG_STS, &lReturn );\r
+ usLinkStatus = prvReadPHY( PHY_REG_STS, &lReturn );\r
if( usLinkStatus & emacLINK_ESTABLISHED )\r
{\r
/* Link is established. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
-long Init_EMAC( void )\r
-{\r
-long lReturn = pdPASS;\r
-volatile unsigned long regv, tout;\r
-unsigned long ulID1, ulID2;\r
-\r
- /* Reset peripherals, configure port pins and registers. */\r
- prvSetupEMACHardware();\r
-\r
- /* Check if connected to a DP83848C PHY. */\r
- ulID1 = read_PHY( PHY_REG_IDR1, &lReturn );\r
- ulID2 = read_PHY( PHY_REG_IDR2, &lReturn );\r
- if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) == DP83848C_ID )\r
- {\r
- /* Set the Ethernet MAC Address registers */\r
- MAC_SA0 = ( configMAC_ADDR0 << 8 ) | configMAC_ADDR1;\r
- MAC_SA1 = ( configMAC_ADDR2 << 8 ) | configMAC_ADDR3;\r
- MAC_SA2 = ( configMAC_ADDR4 << 8 ) | configMAC_ADDR5;\r
-\r
- /* Initialize Tx and Rx DMA Descriptors */\r
- prvInitDescriptors();\r
-\r
- /* Receive Broadcast and Perfect Match Packets */\r
- MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;\r
-\r
- /* Setup the PHY. */\r
- prvConfigurePHY();\r
- }\r
- else\r
- {\r
- lReturn = pdFAIL;\r
- }\r
-\r
- /* Check the link status. */\r
- if( lReturn == pdPASS )\r
- {\r
- lReturn = prvSetupLinkStatus();\r
- }\r
-\r
- if( lReturn == pdPASS )\r
- {\r
- /* Initialise uip_buf to ensure it points somewhere valid. */\r
- uip_buf = prvGetNextBuffer();\r
-\r
- /* Reset all interrupts */\r
- MAC_INTCLEAR = ( INT_RX_OVERRUN | INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP );\r
-\r
- /* Enable receive and transmit mode of MAC Ethernet core */\r
- MAC_COMMAND |= ( CR_RX_EN | CR_TX_EN );\r
- MAC_MAC1 |= MAC1_REC_EN;\r
- }\r
-\r
- return lReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
static void prvReturnBuffer( unsigned char *pucBuffer )\r
{\r
unsigned long ul;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static long prvWritePHY( long lPhyReg, long lValue )\r
+{\r
+const long lMaxTime = 10;\r
+long x;\r
+\r
+ MAC_MADR = DP83848C_DEF_ADR | lPhyReg;\r
+ MAC_MWTD = lValue;\r
+\r
+ x = 0;\r
+ for( x = 0; x < lMaxTime; x++ )\r
+ {\r
+ if( ( MAC_MIND & MIND_BUSY ) == 0 )\r
+ {\r
+ /* Operation has finished. */\r
+ break;\r
+ }\r
+\r
+ vTaskDelay( emacSHORT_DELAY );\r
+ }\r
+\r
+ if( x < lMaxTime )\r
+ {\r
+ return pdPASS;\r
+ }\r
+ else\r
+ {\r
+ return pdFAIL;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static unsigned short prvReadPHY( unsigned char ucPhyReg, long *plStatus )\r
+{\r
+long x;\r
+const long lMaxTime = 10;\r
+\r
+ MAC_MADR = DP83848C_DEF_ADR | ucPhyReg;\r
+ MAC_MCMD = MCMD_READ;\r
+\r
+ for( x = 0; x < lMaxTime; x++ )\r
+ {\r
+ /* Operation has finished. */\r
+ if( ( MAC_MIND & MIND_BUSY ) == 0 )\r
+ {\r
+ break;\r
+ }\r
\r
-static char c[ 256 ] = { 0 };\r
-static int i = 0;\r
+ vTaskDelay( emacSHORT_DELAY );\r
+ }\r
\r
+ MAC_MCMD = 0;\r
+\r
+ if( x >= lMaxTime )\r
+ {\r
+ *plStatus = pdFAIL;\r
+ }\r
+\r
+ return( MAC_MRDD );\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
void vEMAC_ISR( void )\r
{\r
{\r
if( usSendLen > 0 )\r
{\r
-if( i < 255 )\r
- c[ i++ ] = 1;\r
/* Send the data again, using the second descriptor. As there are\r
only two descriptors the index is set back to 0. */\r
TX_DESC_PACKET( ( emacTX_DESC_INDEX + 1 ) ) = TX_DESC_PACKET( emacTX_DESC_INDEX );\r
}\r
else\r
{\r
-if( i < 255 )\r
- c[ i++ ] = 1;\r
-\r
/* The Tx buffer is no longer required. */\r
prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) );\r
TX_DESC_PACKET( emacTX_DESC_INDEX ) = NULL;\r