This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EtherDev_LAN8720.c Source File

EtherDev_LAN8720.c

00001 /*
00002     FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.
00003     
00004 
00005     ***************************************************************************
00006      *                                                                       *
00007      *    FreeRTOS tutorial books are available in pdf and paperback.        *
00008      *    Complete, revised, and edited pdf reference manuals are also       *
00009      *    available.                                                         *
00010      *                                                                       *
00011      *    Purchasing FreeRTOS documentation will not only help you, by       *
00012      *    ensuring you get running as quickly as possible and with an        *
00013      *    in-depth knowledge of how to use FreeRTOS, it will also help       *
00014      *    the FreeRTOS project to continue with its mission of providing     *
00015      *    professional grade, cross platform, de facto standard solutions    *
00016      *    for microcontrollers - completely free of charge!                  *
00017      *                                                                       *
00018      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *
00019      *                                                                       *
00020      *    Thank you for using FreeRTOS, and thank you for your support!      *
00021      *                                                                       *
00022     ***************************************************************************
00023 
00024 
00025     This file is part of the FreeRTOS distribution.
00026 
00027     FreeRTOS is free software; you can redistribute it and/or modify it under
00028     the terms of the GNU General Public License (version 2) as published by the
00029     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
00030     >>>NOTE<<< The modification to the GPL is included to allow you to
00031     distribute a combined work that includes FreeRTOS without being obliged to
00032     provide the source code for proprietary components outside of the FreeRTOS
00033     kernel.  FreeRTOS is distributed in the hope that it will be useful, but
00034     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00035     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00036     more details. You should have received a copy of the GNU General Public
00037     License and the FreeRTOS license exception along with FreeRTOS; if not it
00038     can be viewed here: http://www.freertos.org/a00114.html and also obtained
00039     by writing to Richard Barry, contact details for whom are available on the
00040     FreeRTOS WEB site.
00041 
00042     1 tab == 4 spaces!
00043 
00044     http://www.FreeRTOS.org - Documentation, latest information, license and
00045     contact details.
00046 
00047     http://www.SafeRTOS.com - A version that is certified for use in safety
00048     critical systems.
00049 
00050     http://www.OpenRTOS.com - Commercial support, development, porting,
00051     licensing and training services.
00052 */
00053 
00054 /* Originally adapted from file written by Andreas Dannenberg.  Supplied with permission. */
00055 /*
00056  * Modified for MiMic by R.Iizuka. 2011.08.27
00057  * http://nyatla.jp/mimic
00058  */
00059 
00060 
00061 #include "NyLPC_config.h"
00062 #if NyLPC_MCU==NyLPC_MCU_LPC17xx
00063 #include "EtherDev_LAN8720_protected.h"
00064 #include "../NyLPC_cEthernetMM.h"
00065 #include "LPC17xx.h"
00066 #include "NyLPC_os.h"
00067 
00068 #define LAN8720_ID          0x0007C0F0  /* PHY Identifier                    */
00069 
00070 /* LAN8720 PHY Registers */
00071 #define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
00072 #define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
00073 #define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
00074 #define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
00075 #define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
00076 #define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
00077 #define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
00078 
00079 /* PHY Extended Registers */
00080 #define PHY_REG_MODE_CTRL       17
00081 #define PHY_REG_SPECIAL_MODE    18
00082 #define PHY_REG_SYMBOL_ERR_CNT  26
00083 #define PHY_REG_SPECIAL_CTRL    27
00084 #define PHY_REG_INT_SOURCE      29
00085 #define PHY_REG_INT_MASK        30
00086 #define PHY_REG_PHY_CTRL        31
00087 
00088 #define PHY_AUTO_NEG            0x3000  /* Select Auto Negotiation           */
00089 #define PHY_AUTO_NEG_COMPLETE   0x1000  /* Auto negotiation have finished.   */
00090 
00091 #define PHY_SPEED_FDUPLX        0x0010  /* Full Duplex   */
00092 #define PHY_SPEED_100           0x0008  /* 100Mbit   */
00093 
00094 
00095 #ifndef configEMAC_INTERRUPT_PRIORITY
00096     #define configEMAC_INTERRUPT_PRIORITY       5
00097 #endif
00098 
00099 /* Time to wait between each inspection of the link status. */
00100 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
00101 
00102 /* Short delay used in several places during the initialisation process. */
00103 #define emacSHORT_DELAY_MS 10
00104 
00105 /* Hardware specific bit definitions. */
00106 #define emacPINSEL2_VALUE           ( 0x50150105 )
00107 
00108 
00109 /*-----------------------------------------------------------*/
00110 
00111 /* Setup the IO and peripherals required for Ethernet communication.*/
00112 static void prvSetupEMACHardware( void );
00113 /* Control the auto negotiate process.*/
00114 static void prvConfigurePHY( void );
00115 /*
00116  * Wait for a link to be established, then setup the PHY according to the link
00117  * parameters.
00118  */
00119 static long prvSetupLinkStatus( void );
00120 
00121 
00122 
00123 
00124 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);
00125 static void stop(void);
00126 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);
00127 static void releaseTxBuf(void* i_buf);
00128 
00129 /** EMAC ISRハンドラ*/
00130 static void emacIsrHandler(unsigned long i_status);
00131 
00132 /*-----------------------------------------------------------*/
00133 
00134 
00135 const static struct TiEthernetDevice _interface=
00136 {
00137     "LAN8720",
00138     start,
00139     stop,
00140     EthDev_LPC17xx_getRxEthFrame,
00141     EthDev_LPC17xx_nextRxEthFrame,
00142     allocTxBuf,
00143     releaseTxBuf,
00144     EthDev_LPC17xx_sendTxEthFrame,
00145     EthDev_LPC17xx_processTx
00146 };
00147 static void* _event_param;
00148 static NyLPC_TiEthernetDevice_onEvent _event_handler;
00149 
00150 /*
00151  * EthernetDeviceのファクトリー関数。インターフェイスを生成できればtrue
00152  *
00153  */
00154 NyLPC_TBool EthDev_LAN8720_getInterface(
00155     const struct TiEthernetDevice** o_dev)
00156 {
00157     unsigned long ulID1, ulID2;
00158     NyLPC_TBool ret=NyLPC_TBool_TRUE;
00159     //Reset MCU Interface. and wait for reset.
00160     prvSetupEMACHardware();
00161     //Check peripheral name
00162     ulID1 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR1, &ret );
00163     ulID2 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR2, &ret );
00164     if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) != LAN8720_ID)
00165     {
00166         return NyLPC_TBool_FALSE;
00167     }
00168     *o_dev=&_interface;
00169     LPC_EMAC->TxProduceIndex = 0;
00170     LPC_EMAC->RxConsumeIndex = 0;
00171     return NyLPC_TBool_TRUE;
00172 }
00173 
00174 
00175 
00176 /***********************************************************************
00177  * RXバッファ関連の定義
00178  ***********************************************************************/
00179 #define ETH_TX_BUF_BASE (void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG)
00180 
00181 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)
00182 {
00183     //ISRw割り込み設定
00184     NyLPC_cIsr_setEnetISR(emacIsrHandler);
00185     _event_handler=i_handler;
00186     _event_param=i_param;
00187     /* Set the Ethernet MAC Address registers */
00188     LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];
00189     LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];
00190     LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];
00191 
00192     //TXメモリマネージャの準備
00193     NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);
00194     /* Initialize Tx and Rx DMA Descriptors */
00195     EthDev_LPC17xx_prevRxDescriptor();
00196     EthDev_LPC17xx_prevTxDescriptor();
00197 
00198     /* Setup the PHY. */
00199     prvConfigurePHY();
00200 
00201     //wait for Link up...
00202     while(!prvSetupLinkStatus())
00203     {
00204         NyLPC_cThread_sleep(100);
00205     }
00206 
00207     /* Receive Broadcast and Perfect Match Packets */
00208     LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN | RFC_MCAST_EN;
00209 
00210     //Ethernetの割込み開始設定
00211     NyLPC_cIsr_enterCritical();
00212     {
00213         /* Reset all interrupts */
00214         LPC_EMAC->IntClear = 0xffff;
00215         LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE );
00216         /* Enable receive and transmit mode of MAC Ethernet core */
00217         LPC_EMAC->Command |= ( CR_RX_EN | CR_TX_EN );
00218         LPC_EMAC->MAC1 |= MAC1_REC_EN;
00219 
00220         /* Set the interrupt priority to the max permissible to cause some
00221         interrupt nesting. */
00222         NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
00223 
00224         /* Enable the interrupt. */
00225         NVIC_EnableIRQ( ENET_IRQn );
00226     }
00227     NyLPC_cIsr_exitCritical();
00228 
00229     return NyLPC_TBool_TRUE;
00230 }
00231 static void stop(void)
00232 {
00233     NyLPC_cIsr_enterCritical();
00234     {
00235         LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable;
00236         NVIC_DisableIRQ( ENET_IRQn );
00237     }
00238     NyLPC_cIsr_exitCritical();
00239     LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
00240     LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
00241     //ISR割り込み解除
00242     NyLPC_cIsr_setEnetISR(NULL);
00243     //TXメモリマネージャの終了
00244     NyLPC_cEthernetMM_finalize();
00245 }
00246 
00247 
00248 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
00249 {
00250     return NyLPC_cEthernetMM_alloc(i_hint,o_size);
00251 }
00252 static void releaseTxBuf(void* i_buf)
00253 {
00254     NyLPC_cEthernetMM_release(i_buf);
00255 }
00256 
00257 
00258 
00259 /********************************************************************************
00260  * Private functions
00261  *******************************************************************************/
00262 
00263 /*-----------------------------------------------------------*/
00264 
00265 /*-----------------------------------------------------------*/
00266 
00267 static void prvSetupEMACHardware( void )
00268 {
00269     unsigned short us;
00270     long x;
00271     NyLPC_TBool lDummy;
00272 
00273     /* Power Up the EMAC controller. */
00274     LPC_SC->PCONP |= 0x40000000;
00275     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
00276 
00277     /* Enable P1 Ethernet Pins. */
00278     LPC_PINCON->PINSEL2 = emacPINSEL2_VALUE;
00279     LPC_PINCON->PINSEL3 = ( LPC_PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;
00280 
00281     /* Reset all EMAC internal modules. */
00282     LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
00283     LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES| CR_PASS_RUNT_FRM;
00284     /* A short delay after reset. */
00285     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
00286 
00287     /* Initialize MAC control registers. */
00288     LPC_EMAC->MAC1 = MAC1_PASS_ALL;
00289     LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
00290     LPC_EMAC->MAXF = ETH_MAX_FLEN;
00291     LPC_EMAC->CLRT = CLRT_DEF;
00292     LPC_EMAC->IPGR = IPGR_DEF;
00293 
00294     /*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */ // I don't think so!
00295     /* Enable Reduced MII interface. */
00296     LPC_EMAC->MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
00297     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
00298     LPC_EMAC->MCFG = MCFG_CLK_DIV20;
00299 
00300     /* Enable Reduced MII interface. */
00301     LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
00302 
00303     /* Reset Reduced MII Logic. */
00304     LPC_EMAC->SUPP = SUPP_RES_RMII | SUPP_SPEED;
00305     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
00306     LPC_EMAC->SUPP = SUPP_SPEED;
00307 
00308     /* Put the PHY in reset mode */
00309     EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
00310     NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5);
00311 
00312     /* Wait for hardware reset to end. */
00313     for( x = 0; x < 100; x++ )
00314     {
00315         NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
00316         us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMCR, &lDummy );
00317         if( !( us & MCFG_RES_MII ) )
00318         {
00319             /* Reset complete */
00320             break;
00321         }
00322     }
00323 }
00324 
00325 
00326 /**
00327  * Private function depend on configulation.
00328  * デバイス依存部分
00329  */
00330 
00331 
00332 /* for LPC1769
00333  */
00334 static void prvConfigurePHY( void )
00335 {
00336     unsigned short us;
00337     long x;
00338     NyLPC_TBool lDummy;
00339     /* Auto negotiate the configuration. */
00340     if( EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )
00341     {
00342         NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
00343 
00344         for( x = 0; x < 10; x++ )
00345         {
00346             us = EthDev_LPC17xx_prvReadPHY( PHY_REG_PHY_CTRL, &lDummy );
00347             if( us & PHY_AUTO_NEG_COMPLETE )
00348             {
00349                 break;
00350             }
00351             NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
00352         }
00353     }
00354 }
00355 
00356 static long prvSetupLinkStatus( void )
00357 {
00358     long x;
00359     unsigned short usLinkStatus;
00360     NyLPC_TBool lReturn=NyLPC_TBool_TRUE;
00361 
00362     /* Wait with timeout for the link to be established. */
00363     for( x = 0; x < 10; x++ )
00364     {
00365         usLinkStatus = EthDev_LPC17xx_prvReadPHY (PHY_REG_PHY_CTRL, &lReturn );
00366         if( usLinkStatus & PHY_AUTO_NEG_COMPLETE )
00367         {
00368             /* Link is established. */
00369             lReturn = NyLPC_TBool_TRUE;
00370             break;
00371         }
00372         NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
00373     }
00374 
00375     if( lReturn == NyLPC_TBool_TRUE )
00376     {
00377         /* Configure Full/Half Duplex mode. */
00378         if (usLinkStatus & PHY_SPEED_FDUPLX )
00379         {
00380             /* Full duplex is enabled. */
00381             LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
00382             LPC_EMAC->Command |= CR_FULL_DUP;
00383             LPC_EMAC->IPGT = IPGT_FULL_DUP;
00384         }
00385         else
00386         {
00387             /* Half duplex mode. */
00388             LPC_EMAC->IPGT = IPGT_HALF_DUP;
00389         }
00390 
00391         /* Configure 100MBit/10MBit mode. */
00392         if( !(usLinkStatus & PHY_SPEED_100) )
00393         {
00394             /* 10MBit mode. */
00395             LPC_EMAC->SUPP = 0;
00396         }
00397         else
00398         {
00399             /* 100MBit mode. */
00400             LPC_EMAC->SUPP = SUPP_SPEED;
00401         }
00402     }
00403     return lReturn;
00404 }
00405 //--------------------------------------------------------------------------------
00406 // ISR
00407 //--------------------------------------------------------------------------------
00408 
00409 /**
00410  * EMACからのハンドラ
00411  */
00412 static void emacIsrHandler(unsigned long i_status)
00413 {
00414     if( i_status & INT_RX_DONE )
00415     {
00416         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);
00417     }
00418     if( i_status & INT_TX_DONE )
00419     {
00420         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);
00421     }
00422 }
00423 
00424 #endif
00425 
00426