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
60 #include "NyLPC_config.h"
\r
61 #if NyLPC_MCU==NyLPC_MCU_LPC17xx
\r
64 /* Kernel includes. */
\r
65 #include "../NyLPC_cEthernetMM.h"
\r
66 #include "EtherDev_DP83848C_protected.h"
\r
67 #include "LPC17xx.h"
\r
68 #include "NyLPC_os.h"
\r
71 #define DP83848C_ID 0x20005C90 /* PHY Identifier */
\r
73 /* DP83848C PHY Registers */
\r
74 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
\r
75 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
\r
76 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
\r
77 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
\r
78 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
\r
79 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
\r
80 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
\r
81 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
\r
83 /* PHY Extended Registers */
\r
84 #define PHY_REG_STS 0x10 /* Status Register */
\r
85 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
\r
86 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
\r
87 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
\r
88 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
\r
89 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
\r
90 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
\r
91 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
\r
92 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
\r
93 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
\r
94 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
\r
95 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
\r
97 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
\r
98 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
\r
99 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
\r
100 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
\r
101 #define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
\r
102 #define PHY_AUTO_NEG_COMPLETE 0x0020 /* Auto negotiation have finished. */
\r
103 //#define ETHDEV_PHY_DEF_ADR 0x0100 /* Default PHY device address */
\r
106 #ifndef configEMAC_INTERRUPT_PRIORITY
\r
107 #define configEMAC_INTERRUPT_PRIORITY 5
\r
110 /* Time to wait between each inspection of the link status. */
\r
111 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
\r
113 /* Short delay used in several places during the initialisation process. */
\r
114 #define emacSHORT_DELAY_MS 10
\r
116 /* Hardware specific bit definitions. */
\r
117 #define emacPINSEL2_VALUE ( 0x50150105 )
\r
121 /*-----------------------------------------------------------*/
\r
123 /* Setup the IO and peripherals required for Ethernet communication.*/
\r
124 static void prvSetupEMACHardware( void );
\r
125 /* Control the auto negotiate process.*/
\r
126 static void prvConfigurePHY( void );
\r
128 * Wait for a link to be established, then setup the PHY according to the link
\r
131 static NyLPC_TBool prvSetupLinkStatus( void );
\r
137 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);
\r
138 static void stop(void);
\r
139 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);
\r
140 static void releaseTxBuf(void* i_buf);
\r
141 /*-----------------------------------------------------------*/
\r
142 #define ETH_TX_BUF_BASE (void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG)
\r
145 const static struct TiEthernetDevice _interface=
\r
150 EthDev_LPC17xx_getRxEthFrame,
\r
151 EthDev_LPC17xx_nextRxEthFrame,
\r
154 EthDev_LPC17xx_sendTxEthFrame,
\r
155 EthDev_LPC17xx_processTx
\r
158 static void* _event_param;
\r
159 static NyLPC_TiEthernetDevice_onEvent _event_handler;
\r
162 static void emacIsrHandler(unsigned long i_status);
\r
165 * EthernetDeviceのファクトリー関数
\r
168 NyLPC_TBool EthDev_DP83848C_getInterface(
\r
169 const struct TiEthernetDevice** o_dev)
\r
171 unsigned long ulID1, ulID2;
\r
172 NyLPC_TBool lReturn = NyLPC_TBool_TRUE;
\r
173 //Reset MCU Interface. and wait for reset.
\r
174 prvSetupEMACHardware();
\r
175 //Check peripheral name
\r
176 ulID1 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR1, &lReturn );
\r
177 ulID2 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR2, &lReturn );
\r
178 if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) != DP83848C_ID)
\r
180 return NyLPC_TBool_FALSE;
\r
182 *o_dev=&_interface;
\r
183 LPC_EMAC->TxProduceIndex = 0;
\r
184 LPC_EMAC->RxConsumeIndex = 0;
\r
185 return NyLPC_TBool_TRUE;
\r
189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)
\r
191 _event_handler=i_handler;
\r
192 _event_param=i_param;
\r
193 NyLPC_cIsr_setEnetISR(emacIsrHandler);
\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
200 NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);
\r
202 /* Initialize Tx and Rx DMA Descriptors */
\r
203 EthDev_LPC17xx_prevRxDescriptor();
\r
204 EthDev_LPC17xx_prevTxDescriptor();
\r
206 /* Setup the PHY. */
\r
209 //wait for Link up...
\r
210 while(!prvSetupLinkStatus())
\r
212 NyLPC_cThread_sleep(100);
\r
215 /* Receive Broadcast and Perfect Match Packets */
\r
216 LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN | RFC_MCAST_EN;
\r
219 NyLPC_cIsr_enterCritical();
\r
221 /* Reset all interrupts */
\r
222 LPC_EMAC->IntClear = 0xffff;
\r
223 LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE );
\r
225 /* Enable receive and transmit mode of MAC Ethernet core */
\r
226 LPC_EMAC->Command |= ( CR_RX_EN | CR_TX_EN );
\r
227 LPC_EMAC->MAC1 |= MAC1_REC_EN;
\r
229 /* Set the interrupt priority to the max permissible to cause some
\r
230 interrupt nesting. */
\r
231 NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
\r
233 /* Enable the interrupt. */
\r
234 NVIC_EnableIRQ( ENET_IRQn );
\r
236 NyLPC_cIsr_exitCritical();
\r
238 return NyLPC_TBool_TRUE;
\r
241 static void stop(void)
\r
243 NyLPC_cIsr_enterCritical();
\r
245 LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable;
\r
246 NVIC_DisableIRQ( ENET_IRQn );
\r
248 NyLPC_cIsr_exitCritical();
\r
249 LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
\r
250 LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
\r
252 NyLPC_cIsr_setEnetISR(NULL);
\r
254 NyLPC_cEthernetMM_finalize();
\r
258 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
\r
260 return NyLPC_cEthernetMM_alloc(i_hint,o_size);
\r
262 static void releaseTxBuf(void* i_buf)
\r
264 NyLPC_cEthernetMM_release(i_buf);
\r
269 /********************************************************************************
\r
270 * Private functions
\r
271 *******************************************************************************/
\r
273 /*-----------------------------------------------------------*/
\r
275 /*-----------------------------------------------------------*/
\r
277 static void prvSetupEMACHardware( void )
\r
281 NyLPC_TBool lDummy;
\r
283 /* Power Up the EMAC controller. */
\r
284 LPC_SC->PCONP |= 0x40000000;
\r
285 NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
\r
287 /* Enable P1 Ethernet Pins. */
\r
288 LPC_PINCON->PINSEL2 = emacPINSEL2_VALUE;
\r
289 LPC_PINCON->PINSEL3 = ( LPC_PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;
\r
291 /* Reset all EMAC internal modules. */
\r
292 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
\r
293 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES| CR_PASS_RUNT_FRM;
\r
294 /* A short delay after reset. */
\r
295 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
297 /* Initialize MAC control registers. */
\r
298 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
\r
299 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
\r
300 LPC_EMAC->MAXF = ETH_MAX_FLEN;
\r
301 LPC_EMAC->CLRT = CLRT_DEF;
\r
302 LPC_EMAC->IPGR = IPGR_DEF;
\r
304 /*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */ // I don't think so!
\r
305 /* Enable Reduced MII interface. */
\r
306 LPC_EMAC->MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
\r
307 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
308 LPC_EMAC->MCFG = MCFG_CLK_DIV20;
\r
310 /* Enable Reduced MII interface. */
\r
311 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
\r
313 /* Reset Reduced MII Logic. */
\r
314 LPC_EMAC->SUPP = SUPP_RES_RMII | SUPP_SPEED;
\r
315 NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
\r
316 LPC_EMAC->SUPP = SUPP_SPEED;
\r
318 /* Put the PHY in reset mode */
\r
319 EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
\r
320 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5);
\r
322 /* Wait for hardware reset to end. */
\r
323 for( x = 0; x < 100; x++ )
\r
325 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
\r
326 us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMCR, &lDummy );
\r
327 if( !( us & MCFG_RES_MII ) )
\r
329 /* Reset complete */
\r
334 /*------------------------------------------------
\r
335 * Private function depend on device.
\r
337 ------------------------------------------------*/
\r
342 #define emacLINK_ESTABLISHED ( 0x0001 )
\r
343 #define emacFULL_DUPLEX_ENABLED ( 0x0004 )
\r
344 #define emac10BASE_T_MODE ( 0x0002 )
\r
347 static void prvConfigurePHY( void )
\r
351 NyLPC_TBool lDummy;
\r
353 /* Auto negotiate the configuration. */
\r
354 if( EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )
\r
356 NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
\r
358 for( x = 0; x < 10; x++ )
\r
360 us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMSR, &lDummy );
\r
362 if( us & PHY_AUTO_NEG_COMPLETE )
\r
367 NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
\r
372 static NyLPC_TBool prvSetupLinkStatus( void )
\r
374 NyLPC_TBool lReturn = NyLPC_TBool_FALSE;
\r
376 unsigned short usLinkStatus;
\r
378 /* Wait with timeout for the link to be established. */
\r
379 for( x = 0; x < 10; x++ )
\r
381 usLinkStatus = EthDev_LPC17xx_prvReadPHY( PHY_REG_STS, &lReturn );
\r
382 if( usLinkStatus & emacLINK_ESTABLISHED )
\r
384 /* Link is established. */
\r
385 lReturn = NyLPC_TBool_TRUE;
\r
389 NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
\r
392 if( lReturn == NyLPC_TBool_TRUE )
\r
394 /* Configure Full/Half Duplex mode. */
\r
395 if( usLinkStatus & emacFULL_DUPLEX_ENABLED )
\r
397 /* Full duplex is enabled. */
\r
398 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
\r
399 LPC_EMAC->Command |= CR_FULL_DUP;
\r
400 LPC_EMAC->IPGT = IPGT_FULL_DUP;
\r
404 /* Half duplex mode. */
\r
405 LPC_EMAC->IPGT = IPGT_HALF_DUP;
\r
408 /* Configure 100MBit/10MBit mode. */
\r
409 if( usLinkStatus & emac10BASE_T_MODE )
\r
412 LPC_EMAC->SUPP = 0;
\r
416 /* 100MBit mode. */
\r
417 LPC_EMAC->SUPP = SUPP_SPEED;
\r
427 static void emacIsrHandler(unsigned long i_status)
\r
429 if( i_status & INT_RX_DONE )
\r
431 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);
\r
433 if( i_status & INT_TX_DONE )
\r
435 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);
\r