2 FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
54 /* Originally adapted from file written by Andreas Dannenberg. Supplied with permission. */
\r
56 * Modified for MiMic by R.Iizuka. 2011.08.27
\r
57 * http://nyatla.jp/mimic
\r
61 /* Kernel includes. */
\r
62 #include "EtherDev_DP83848C_protected.h"
\r
63 #include "LPC17xx.h"
\r
64 #include "NyLPC_os.h"
\r
67 #define DP83848C_ID 0x20005C90 /* PHY Identifier */
\r
69 /* DP83848C PHY Registers */
\r
70 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
\r
71 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
\r
72 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
\r
73 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
\r
74 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
\r
75 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
\r
76 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
\r
77 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
\r
79 /* PHY Extended Registers */
\r
80 #define PHY_REG_STS 0x10 /* Status Register */
\r
81 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
\r
82 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
\r
83 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
\r
84 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
\r
85 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
\r
86 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
\r
87 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
\r
88 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
\r
89 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
\r
90 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
\r
91 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
\r
93 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
\r
94 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
\r
95 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
\r
96 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
\r
97 #define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
\r
98 #define PHY_AUTO_NEG_COMPLETE 0x0020 /* Auto negotiation have finished. */
\r
99 #define ETHDEV_PHY_DEF_ADR 0x0100 /* Default PHY device address */
\r
102 #ifndef configEMAC_INTERRUPT_PRIORITY
\r
103 #define configEMAC_INTERRUPT_PRIORITY 5
\r
106 /* Time to wait between each inspection of the link status. */
\r
107 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
\r
109 /* Short delay used in several places during the initialisation process. */
\r
110 #define emacSHORT_DELAY_MS 10
\r
112 /* Hardware specific bit definitions. */
\r
113 #define emacPINSEL2_VALUE ( 0x50150105 )
\r
115 /* If no buffers are available, then wait this long before looking again.... */
\r
116 #define emacBUFFER_WAIT_DELAY_MS 3
\r
117 #define emacBUFFER_WAIT_EMPTY_MS 10
\r
119 /* ...and don't look more than this many times. */
\r
120 #define emacBUFFER_WAIT_ATTEMPTS ( 30 )
\r
122 /* Index to the Tx descriptor that is always used first for every Tx. The second
\r
123 descriptor is then used to re-send in order to speed up the uIP Tx process. */
\r
124 #define emacTX_DESC_INDEX ( 0 )
\r
126 /*-----------------------------------------------------------*/
\r
128 /* Setup the IO and peripherals required for Ethernet communication.*/
\r
129 static void prvSetupEMACHardware( void );
\r
130 /* Control the auto negotiate process.*/
\r
131 static void prvConfigurePHY( void );
\r
133 * Wait for a link to be established, then setup the PHY according to the link
\r
136 static NyLPC_TBool prvSetupLinkStatus( void );
\r
138 * Send lValue to the lPhyReg within the PHY.
\r
140 static NyLPC_TBool prvWritePHY( long lPhyReg, long lValue );
\r
142 * Read a value from ucPhyReg within the PHY. *plStatus will be set to
\r
143 * pdFALSE if there is an error.
\r
145 static unsigned short prvReadPHY( unsigned int ucPhyReg, long *plStatus );
\r
149 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr);
\r
150 static void stop(void);
\r
152 /*-----------------------------------------------------------*/
\r
156 const static struct TiEthernetDevice _interface=
\r
161 EthDev_LPC17xx_getRxEthFrame,
\r
162 EthDev_LPC17xx_nextRxEthFrame,
\r
163 EthDev_LPC17xx_allocTxBuf,
\r
164 EthDev_LPC17xx_releaseTxBuf,
\r
165 EthDev_LPC17xx_sendTxEthFrame,
\r
166 EthDev_LPC17xx_processTx};
\r
168 * EthernetDeviceのファクトリー関数
\r
171 NyLPC_TBool EthDev_DP83848C_getInterface(
\r
172 const struct TiEthernetDevice** o_dev)
\r
174 unsigned long ulID1, ulID2;
\r
175 NyLPC_TBool lReturn = NyLPC_TBool_TRUE;
\r
176 //Reset MCU Interface. and wait for reset.
\r
177 prvSetupEMACHardware();
\r
178 //Check peripheral name
\r
179 ulID1 = prvReadPHY( PHY_REG_IDR1, &lReturn );
\r
180 ulID2 = prvReadPHY( PHY_REG_IDR2, &lReturn );
\r
181 if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) != DP83848C_ID)
\r
183 return NyLPC_TBool_FALSE;
\r
185 *o_dev=&_interface;
\r
186 LPC_EMAC->TxProduceIndex = 0;
\r
187 LPC_EMAC->RxConsumeIndex = 0;
\r
188 return NyLPC_TBool_TRUE;
\r
192 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr)
\r
194 /* Set the Ethernet MAC Address registers */
\r
195 LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];
\r
196 LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];
\r
197 LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];
\r
199 /* Initialize Tx and Rx DMA Descriptors */
\r
200 EthDev_LPC17xx_prevRxDescriptor();
\r
201 EthDev_LPC17xx_prevTxDescriptor();
\r
204 /* Setup the PHY. */
\r
207 //wait for Link up...
\r
208 while(!prvSetupLinkStatus())
\r
210 NyLPC_cThread_sleep(100);
\r
213 /* Receive Broadcast and Perfect Match Packets */
\r
214 LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN | RFC_MCAST_EN;
\r
217 NyLPC_cIsr_enterCritical();
\r
219 /* Reset all interrupts */
\r
220 LPC_EMAC->IntClear = 0xffff;
\r
221 LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE );
\r
223 /* Enable receive and transmit mode of MAC Ethernet core */
\r
224 LPC_EMAC->Command |= ( CR_RX_EN | CR_TX_EN );
\r
225 LPC_EMAC->MAC1 |= MAC1_REC_EN;
\r
227 /* Set the interrupt priority to the max permissible to cause some
\r
228 interrupt nesting. */
\r
229 NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
\r
231 /* Enable the interrupt. */
\r
232 NVIC_EnableIRQ( ENET_IRQn );
\r
234 NyLPC_cIsr_exitCritical();
\r
236 return NyLPC_TBool_TRUE;
\r
239 static void stop(void)
\r
241 NyLPC_cIsr_enterCritical();
\r
243 LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable;
\r
244 NVIC_DisableIRQ( ENET_IRQn );
\r
246 NyLPC_cIsr_exitCritical();
\r
247 LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
\r
248 LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
\r
255 /********************************************************************************
\r
256 * Private functions
\r
257 *******************************************************************************/
\r
259 /*-----------------------------------------------------------*/
\r
261 /*-----------------------------------------------------------*/
\r
263 static void prvSetupEMACHardware( void )
\r
267 NyLPC_TBool lDummy;
\r
269 /* Power Up the EMAC controller. */
\r
270 LPC_SC->PCONP |= 0x40000000;
\r
271 NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
\r
273 /* Enable P1 Ethernet Pins. */
\r
274 LPC_PINCON->PINSEL2 = emacPINSEL2_VALUE;
\r
275 LPC_PINCON->PINSEL3 = ( LPC_PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;
\r
277 /* Reset all EMAC internal modules. */
\r
278 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
\r
279 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES| CR_PASS_RUNT_FRM;
\r
280 /* A short delay after reset. */
\r
281 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
283 /* Initialize MAC control registers. */
\r
284 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
\r
285 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
\r
286 LPC_EMAC->MAXF = ETH_MAX_FLEN;
\r
287 LPC_EMAC->CLRT = CLRT_DEF;
\r
288 LPC_EMAC->IPGR = IPGR_DEF;
\r
290 /*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */ // I don't think so!
\r
291 /* Enable Reduced MII interface. */
\r
292 LPC_EMAC->MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
\r
293 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
294 LPC_EMAC->MCFG = MCFG_CLK_DIV20;
\r
296 /* Enable Reduced MII interface. */
\r
297 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
\r
299 /* Reset Reduced MII Logic. */
\r
300 LPC_EMAC->SUPP = SUPP_RES_RMII | SUPP_SPEED;
\r
301 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
302 LPC_EMAC->SUPP = SUPP_SPEED;
\r
304 /* Put the PHY in reset mode */
\r
305 prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
\r
306 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5);
\r
308 /* Wait for hardware reset to end. */
\r
309 for( x = 0; x < 100; x++ )
\r
311 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
\r
312 us = prvReadPHY( PHY_REG_BMCR, &lDummy );
\r
313 if( !( us & MCFG_RES_MII ) )
\r
315 /* Reset complete */
\r
320 /*-----------------------------------------------------------*/
\r
323 /*-----------------------------------------------------------*/
\r
325 static NyLPC_TBool prvWritePHY( long lPhyReg, long lValue )
\r
327 const long lMaxTime = 10;
\r
330 LPC_EMAC->MCMD = 0;
\r
331 LPC_EMAC->MADR = ETHDEV_PHY_DEF_ADR | lPhyReg;
\r
332 LPC_EMAC->MWTD = lValue;
\r
334 for( x = 0; x < lMaxTime; x++ )
\r
336 if( ( LPC_EMAC->MIND & MIND_BUSY ) == 0 )
\r
338 /* Operation has finished. */
\r
342 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
347 return NyLPC_TBool_TRUE;
\r
351 return NyLPC_TBool_FALSE;
\r
354 /*-----------------------------------------------------------*/
\r
356 static unsigned short prvReadPHY( unsigned int ucPhyReg, NyLPC_TBool* plStatus )
\r
359 const long lMaxTime = 10;
\r
361 LPC_EMAC->MCMD = 1;
\r
362 LPC_EMAC->MADR = ETHDEV_PHY_DEF_ADR | ucPhyReg;
\r
363 LPC_EMAC->MCMD = MCMD_READ;
\r
365 for( x = 0; x < lMaxTime; x++ )
\r
367 /* Operation has finished. */
\r
368 if( ( LPC_EMAC->MIND & MIND_BUSY ) == 0 )
\r
372 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
375 LPC_EMAC->MCMD = 0;
\r
377 if( x >= lMaxTime )
\r
379 *plStatus = NyLPC_TBool_FALSE;
\r
382 return( LPC_EMAC->MRDD );
\r
384 /*------------------------------------------------
\r
385 * Private function depend on device.
\r
387 ------------------------------------------------*/
\r
392 #define emacLINK_ESTABLISHED ( 0x0001 )
\r
393 #define emacFULL_DUPLEX_ENABLED ( 0x0004 )
\r
394 #define emac10BASE_T_MODE ( 0x0002 )
\r
397 static void prvConfigurePHY( void )
\r
401 NyLPC_TBool lDummy;
\r
403 /* Auto negotiate the configuration. */
\r
404 if( prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )
\r
406 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
\r
408 for( x = 0; x < 10; x++ )
\r
410 us = prvReadPHY( PHY_REG_BMSR, &lDummy );
\r
412 if( us & PHY_AUTO_NEG_COMPLETE )
\r
417 NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
\r
422 static NyLPC_TBool prvSetupLinkStatus( void )
\r
424 NyLPC_TBool lReturn = NyLPC_TBool_FALSE;
\r
426 unsigned short usLinkStatus;
\r
428 /* Wait with timeout for the link to be established. */
\r
429 for( x = 0; x < 10; x++ )
\r
431 usLinkStatus = prvReadPHY( PHY_REG_STS, &lReturn );
\r
432 if( usLinkStatus & emacLINK_ESTABLISHED )
\r
434 /* Link is established. */
\r
435 lReturn = NyLPC_TBool_TRUE;
\r
439 NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
\r
442 if( lReturn == NyLPC_TBool_TRUE )
\r
444 /* Configure Full/Half Duplex mode. */
\r
445 if( usLinkStatus & emacFULL_DUPLEX_ENABLED )
\r
447 /* Full duplex is enabled. */
\r
448 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
\r
449 LPC_EMAC->Command |= CR_FULL_DUP;
\r
450 LPC_EMAC->IPGT = IPGT_FULL_DUP;
\r
454 /* Half duplex mode. */
\r
455 LPC_EMAC->IPGT = IPGT_HALF_DUP;
\r
458 /* Configure 100MBit/10MBit mode. */
\r
459 if( usLinkStatus & emac10BASE_T_MODE )
\r
462 LPC_EMAC->SUPP = 0;
\r
466 /* 100MBit mode. */
\r
467 LPC_EMAC->SUPP = SUPP_SPEED;
\r