OSDN Git Service

update libMiMic
[mimic/MiMicSDK.git] / lib / src / driver / ethernet / lpc17xx / EtherDev_DP83848C.c
1 /*\r
2     FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3 \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\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
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \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
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 /* Originally adapted from file written by Andreas Dannenberg.  Supplied with permission. */\r
55 /*\r
56  * Modified for MiMic by R.Iizuka. 2011.08.27\r
57  * http://nyatla.jp/mimic\r
58  */\r
59 \r
60 #include "NyLPC_config.h"\r
61 #if NyLPC_MCU==NyLPC_MCU_LPC17xx\r
62 \r
63 \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
69 \r
70 \r
71 #define DP83848C_ID         0x20005C90  /* PHY Identifier                    */\r
72 \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
82 \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
96 \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
104 \r
105 \r
106 #ifndef configEMAC_INTERRUPT_PRIORITY\r
107     #define configEMAC_INTERRUPT_PRIORITY       5\r
108 #endif\r
109 \r
110 /* Time to wait between each inspection of the link status. */\r
111 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500\r
112 \r
113 /* Short delay used in several places during the initialisation process. */\r
114 #define emacSHORT_DELAY_MS                 10\r
115 \r
116 /* Hardware specific bit definitions. */\r
117 #define emacPINSEL2_VALUE           ( 0x50150105 )\r
118 \r
119 \r
120 \r
121 /*-----------------------------------------------------------*/\r
122 \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
127 /*\r
128  * Wait for a link to be established, then setup the PHY according to the link\r
129  * parameters.\r
130  */\r
131 static NyLPC_TBool prvSetupLinkStatus( void );\r
132 \r
133 \r
134 \r
135 \r
136 \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
143 \r
144 \r
145 const static struct TiEthernetDevice _interface=\r
146 {\r
147     "DP83848C",\r
148     start,\r
149     stop,\r
150     EthDev_LPC17xx_getRxEthFrame,\r
151     EthDev_LPC17xx_nextRxEthFrame,\r
152     allocTxBuf,\r
153     releaseTxBuf,\r
154     EthDev_LPC17xx_sendTxEthFrame,\r
155     EthDev_LPC17xx_processTx\r
156 };\r
157 \r
158 static void* _event_param;\r
159 static NyLPC_TiEthernetDevice_onEvent _event_handler;\r
160 \r
161 /** EMAC ISRハンドラ*/\r
162 static void emacIsrHandler(unsigned long i_status);\r
163 \r
164 /*\r
165  * EthernetDeviceのファクトリー関数\r
166  */\r
167 \r
168 NyLPC_TBool EthDev_DP83848C_getInterface(\r
169     const struct TiEthernetDevice** o_dev)\r
170 {\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
179     {\r
180         return NyLPC_TBool_FALSE;\r
181     }\r
182     *o_dev=&_interface;\r
183         LPC_EMAC->TxProduceIndex = 0;\r
184         LPC_EMAC->RxConsumeIndex = 0;\r
185     return NyLPC_TBool_TRUE;\r
186 }\r
187 \r
188 \r
189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)\r
190 {\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
198 \r
199         //TXメモリマネージャの準備\r
200         NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);\r
201 \r
202         /* Initialize Tx and Rx DMA Descriptors */\r
203     EthDev_LPC17xx_prevRxDescriptor();\r
204     EthDev_LPC17xx_prevTxDescriptor();\r
205 \r
206     /* Setup the PHY. */\r
207     prvConfigurePHY();\r
208 \r
209     //wait for Link up...\r
210     while(!prvSetupLinkStatus())\r
211     {\r
212         NyLPC_cThread_sleep(100);\r
213     }\r
214 \r
215     /* Receive Broadcast and Perfect Match Packets */\r
216     LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN | RFC_MCAST_EN;\r
217 \r
218     //Ethernetの割込み開始設定\r
219     NyLPC_cIsr_enterCritical();\r
220     {\r
221         /* Reset all interrupts */\r
222         LPC_EMAC->IntClear = 0xffff;\r
223         LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE );\r
224 \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
228 \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
232 \r
233         /* Enable the interrupt. */\r
234         NVIC_EnableIRQ( ENET_IRQn );\r
235     }\r
236     NyLPC_cIsr_exitCritical();\r
237 \r
238     return NyLPC_TBool_TRUE;\r
239 \r
240 }\r
241 static void stop(void)\r
242 {\r
243     NyLPC_cIsr_enterCritical();\r
244     {\r
245         LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable;\r
246         NVIC_DisableIRQ( ENET_IRQn );\r
247     }\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
251         //ISR割り込み解除\r
252         NyLPC_cIsr_setEnetISR(NULL);\r
253         //TXメモリマネージャの終了\r
254         NyLPC_cEthernetMM_finalize();\r
255     return;\r
256 }\r
257 \r
258 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)\r
259 {\r
260         return NyLPC_cEthernetMM_alloc(i_hint,o_size);\r
261 }\r
262 static void releaseTxBuf(void* i_buf)\r
263 {\r
264         NyLPC_cEthernetMM_release(i_buf);\r
265 }\r
266 \r
267 \r
268 \r
269 /********************************************************************************\r
270  * Private functions\r
271  *******************************************************************************/\r
272 \r
273 /*-----------------------------------------------------------*/\r
274 \r
275 /*-----------------------------------------------------------*/\r
276 \r
277 static void prvSetupEMACHardware( void )\r
278 {\r
279     unsigned short us;\r
280     long x;\r
281     NyLPC_TBool lDummy;\r
282 \r
283     /* Power Up the EMAC controller. */\r
284     LPC_SC->PCONP |= 0x40000000;\r
285     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);\r
286 \r
287     /* Enable P1 Ethernet Pins. */\r
288     LPC_PINCON->PINSEL2 = emacPINSEL2_VALUE;\r
289     LPC_PINCON->PINSEL3 = ( LPC_PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;\r
290 \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
296 \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
303 \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
309 \r
310     /* Enable Reduced MII interface. */\r
311     LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;\r
312 \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
317 \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
321 \r
322     /* Wait for hardware reset to end. */\r
323     for( x = 0; x < 100; x++ )\r
324     {\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
328         {\r
329             /* Reset complete */\r
330             break;\r
331         }\r
332     }\r
333 }\r
334 /*------------------------------------------------\r
335  * Private function depend on device.\r
336  * デバイス依存部分\r
337  ------------------------------------------------*/\r
338 \r
339 \r
340 /*for mbed\r
341  */\r
342 #define emacLINK_ESTABLISHED        ( 0x0001 )\r
343 #define emacFULL_DUPLEX_ENABLED     ( 0x0004 )\r
344 #define emac10BASE_T_MODE           ( 0x0002 )\r
345 \r
346 \r
347 static void prvConfigurePHY( void )\r
348 {\r
349     unsigned short us;\r
350     long x;\r
351     NyLPC_TBool lDummy;\r
352 \r
353     /* Auto negotiate the configuration. */\r
354     if( EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )\r
355     {\r
356         NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );\r
357 \r
358         for( x = 0; x < 10; x++ )\r
359         {\r
360             us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMSR, &lDummy );\r
361 \r
362             if( us & PHY_AUTO_NEG_COMPLETE )\r
363             {\r
364                 break;\r
365             }\r
366 \r
367             NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);\r
368         }\r
369     }\r
370 }\r
371 \r
372 static NyLPC_TBool prvSetupLinkStatus( void )\r
373 {\r
374     NyLPC_TBool lReturn = NyLPC_TBool_FALSE;\r
375     long x;\r
376     unsigned short usLinkStatus;\r
377 \r
378     /* Wait with timeout for the link to be established. */\r
379     for( x = 0; x < 10; x++ )\r
380     {\r
381         usLinkStatus = EthDev_LPC17xx_prvReadPHY( PHY_REG_STS, &lReturn );\r
382         if( usLinkStatus & emacLINK_ESTABLISHED )\r
383         {\r
384             /* Link is established. */\r
385             lReturn = NyLPC_TBool_TRUE;\r
386             break;\r
387         }\r
388 \r
389         NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);\r
390     }\r
391 \r
392     if( lReturn == NyLPC_TBool_TRUE )\r
393     {\r
394         /* Configure Full/Half Duplex mode. */\r
395         if( usLinkStatus & emacFULL_DUPLEX_ENABLED )\r
396         {\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
401         }\r
402         else\r
403         {\r
404             /* Half duplex mode. */\r
405             LPC_EMAC->IPGT = IPGT_HALF_DUP;\r
406         }\r
407 \r
408         /* Configure 100MBit/10MBit mode. */\r
409         if( usLinkStatus & emac10BASE_T_MODE )\r
410         {\r
411             /* 10MBit mode. */\r
412             LPC_EMAC->SUPP = 0;\r
413         }\r
414         else\r
415         {\r
416             /* 100MBit mode. */\r
417             LPC_EMAC->SUPP = SUPP_SPEED;\r
418         }\r
419     }\r
420 \r
421     return lReturn;\r
422 }\r
423 \r
424 /**\r
425  * EMACからのハンドラ\r
426  */\r
427 static void emacIsrHandler(unsigned long i_status)\r
428 {\r
429         if( i_status & INT_RX_DONE )\r
430         {\r
431                 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);\r
432         }\r
433         if( i_status & INT_TX_DONE )\r
434         {\r
435                 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);\r
436         }\r
437 }\r
438 \r
439 #endif\r