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_DP83848C.c Source File

EtherDev_DP83848C.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 #include "NyLPC_config.h"
00061 #if NyLPC_MCU==NyLPC_MCU_LPC17xx
00062 
00063 
00064 /* Kernel includes. */
00065 #include "../NyLPC_cEthernetMM.h"
00066 #include "EtherDev_DP83848C_protected.h"
00067 #include "LPC17xx.h"
00068 #include "NyLPC_os.h"
00069 
00070 
00071 #define DP83848C_ID         0x20005C90  /* PHY Identifier                    */
00072 
00073 /* DP83848C PHY Registers */
00074 #define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
00075 #define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
00076 #define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
00077 #define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
00078 #define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
00079 #define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
00080 #define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
00081 #define PHY_REG_ANNPTR      0x07        /* Auto-Neg. Next Page TX            */
00082 
00083 /* PHY Extended Registers */
00084 #define PHY_REG_STS         0x10        /* Status Register                   */
00085 #define PHY_REG_MICR        0x11        /* MII Interrupt Control Register    */
00086 #define PHY_REG_MISR        0x12        /* MII Interrupt Status Register     */
00087 #define PHY_REG_FCSCR       0x14        /* False Carrier Sense Counter       */
00088 #define PHY_REG_RECR        0x15        /* Receive Error Counter             */
00089 #define PHY_REG_PCSR        0x16        /* PCS Sublayer Config. and Status   */
00090 #define PHY_REG_RBR         0x17        /* RMII and Bypass Register          */
00091 #define PHY_REG_LEDCR       0x18        /* LED Direct Control Register       */
00092 #define PHY_REG_PHYCR       0x19        /* PHY Control Register              */
00093 #define PHY_REG_10BTSCR     0x1A        /* 10Base-T Status/Control Register  */
00094 #define PHY_REG_CDCTRL1     0x1B        /* CD Test Control and BIST Extens.  */
00095 #define PHY_REG_EDCR        0x1D        /* Energy Detect Control Register    */
00096 
00097 #define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
00098 #define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
00099 #define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
00100 #define PHY_HALFD_10M       0x0000      /* Half Duplex 10MBit                */
00101 #define PHY_AUTO_NEG        0x3000      /* Select Auto Negotiation           */
00102 #define PHY_AUTO_NEG_COMPLETE 0x0020    /* Auto negotiation have finished.   */
00103 //#define ETHDEV_PHY_DEF_ADR    0x0100      /* Default PHY device address        */
00104 
00105 
00106 #ifndef configEMAC_INTERRUPT_PRIORITY
00107     #define configEMAC_INTERRUPT_PRIORITY       5
00108 #endif
00109 
00110 /* Time to wait between each inspection of the link status. */
00111 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
00112 
00113 /* Short delay used in several places during the initialisation process. */
00114 #define emacSHORT_DELAY_MS                 10
00115 
00116 /* Hardware specific bit definitions. */
00117 #define emacPINSEL2_VALUE           ( 0x50150105 )
00118 
00119 
00120 
00121 /*-----------------------------------------------------------*/
00122 
00123 /* Setup the IO and peripherals required for Ethernet communication.*/
00124 static void prvSetupEMACHardware( void );
00125 /* Control the auto negotiate process.*/
00126 static void prvConfigurePHY( void );
00127 /*
00128  * Wait for a link to be established, then setup the PHY according to the link
00129  * parameters.
00130  */
00131 static NyLPC_TBool prvSetupLinkStatus( void );
00132 
00133 
00134 
00135 
00136 
00137 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);
00138 static void stop(void);
00139 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);
00140 static void releaseTxBuf(void* i_buf);
00141 /*-----------------------------------------------------------*/
00142 #define ETH_TX_BUF_BASE (void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG)
00143 
00144 
00145 const static struct TiEthernetDevice _interface=
00146 {
00147     "DP83848C",
00148     start,
00149     stop,
00150     EthDev_LPC17xx_getRxEthFrame,
00151     EthDev_LPC17xx_nextRxEthFrame,
00152     allocTxBuf,
00153     releaseTxBuf,
00154     EthDev_LPC17xx_sendTxEthFrame,
00155     EthDev_LPC17xx_processTx
00156 };
00157 
00158 static void* _event_param;
00159 static NyLPC_TiEthernetDevice_onEvent _event_handler;
00160 
00161 /** EMAC ISRハンドラ*/
00162 static void emacIsrHandler(unsigned long i_status);
00163 
00164 /*
00165  * EthernetDeviceのファクトリー関数
00166  */
00167 
00168 NyLPC_TBool EthDev_DP83848C_getInterface(
00169     const struct TiEthernetDevice** o_dev)
00170 {
00171     unsigned long ulID1, ulID2;
00172     NyLPC_TBool lReturn = NyLPC_TBool_TRUE;
00173     //Reset MCU Interface. and wait for reset.
00174     prvSetupEMACHardware();
00175     //Check peripheral name
00176     ulID1 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR1, &lReturn );
00177     ulID2 = EthDev_LPC17xx_prvReadPHY( PHY_REG_IDR2, &lReturn );
00178     if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFF0UL ) ) != DP83848C_ID)
00179     {
00180         return NyLPC_TBool_FALSE;
00181     }
00182     *o_dev=&_interface;
00183     LPC_EMAC->TxProduceIndex = 0;
00184     LPC_EMAC->RxConsumeIndex = 0;
00185     return NyLPC_TBool_TRUE;
00186 }
00187 
00188 
00189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)
00190 {
00191     _event_handler=i_handler;
00192     _event_param=i_param;
00193     NyLPC_cIsr_setEnetISR(emacIsrHandler);
00194     /* Set the Ethernet MAC Address registers */
00195     LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];
00196     LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];
00197     LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];
00198 
00199     //TXメモリマネージャの準備
00200     NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);
00201 
00202     /* Initialize Tx and Rx DMA Descriptors */
00203     EthDev_LPC17xx_prevRxDescriptor();
00204     EthDev_LPC17xx_prevTxDescriptor();
00205 
00206     /* Setup the PHY. */
00207     prvConfigurePHY();
00208 
00209     //wait for Link up...
00210     while(!prvSetupLinkStatus())
00211     {
00212         NyLPC_cThread_sleep(100);
00213     }
00214 
00215     /* Receive Broadcast and Perfect Match Packets */
00216     LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN | RFC_MCAST_EN;
00217 
00218     //Ethernetの割込み開始設定
00219     NyLPC_cIsr_enterCritical();
00220     {
00221         /* Reset all interrupts */
00222         LPC_EMAC->IntClear = 0xffff;
00223         LPC_EMAC->IntEnable = ( INT_RX_DONE | INT_TX_DONE );
00224 
00225         /* Enable receive and transmit mode of MAC Ethernet core */
00226         LPC_EMAC->Command |= ( CR_RX_EN | CR_TX_EN );
00227         LPC_EMAC->MAC1 |= MAC1_REC_EN;
00228 
00229         /* Set the interrupt priority to the max permissible to cause some
00230         interrupt nesting. */
00231         NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
00232 
00233         /* Enable the interrupt. */
00234         NVIC_EnableIRQ( ENET_IRQn );
00235     }
00236     NyLPC_cIsr_exitCritical();
00237 
00238     return NyLPC_TBool_TRUE;
00239 
00240 }
00241 static void stop(void)
00242 {
00243     NyLPC_cIsr_enterCritical();
00244     {
00245         LPC_EMAC->IntEnable = (~(INT_RX_DONE|INT_TX_DONE))&LPC_EMAC->IntEnable;
00246         NVIC_DisableIRQ( ENET_IRQn );
00247     }
00248     NyLPC_cIsr_exitCritical();
00249     LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
00250     LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
00251     //ISR割り込み解除
00252     NyLPC_cIsr_setEnetISR(NULL);
00253     //TXメモリマネージャの終了
00254     NyLPC_cEthernetMM_finalize();
00255     return;
00256 }
00257 
00258 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
00259 {
00260     return NyLPC_cEthernetMM_alloc(i_hint,o_size);
00261 }
00262 static void releaseTxBuf(void* i_buf)
00263 {
00264     NyLPC_cEthernetMM_release(i_buf);
00265 }
00266 
00267 
00268 
00269 /********************************************************************************
00270  * Private functions
00271  *******************************************************************************/
00272 
00273 /*-----------------------------------------------------------*/
00274 
00275 /*-----------------------------------------------------------*/
00276 
00277 static void prvSetupEMACHardware( void )
00278 {
00279     unsigned short us;
00280     long x;
00281     NyLPC_TBool lDummy;
00282 
00283     /* Power Up the EMAC controller. */
00284     LPC_SC->PCONP |= 0x40000000;
00285     NyLPC_cThread_sleep( emacSHORT_DELAY_MS);
00286 
00287     /* Enable P1 Ethernet Pins. */
00288     LPC_PINCON->PINSEL2 = emacPINSEL2_VALUE;
00289     LPC_PINCON->PINSEL3 = ( LPC_PINCON->PINSEL3 & ~0x0000000F ) | 0x00000005;
00290 
00291     /* Reset all EMAC internal modules. */
00292     LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
00293     LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES| CR_PASS_RUNT_FRM;
00294     /* A short delay after reset. */
00295     NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
00296 
00297     /* Initialize MAC control registers. */
00298     LPC_EMAC->MAC1 = MAC1_PASS_ALL;
00299     LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
00300     LPC_EMAC->MAXF = ETH_MAX_FLEN;
00301     LPC_EMAC->CLRT = CLRT_DEF;
00302     LPC_EMAC->IPGR = IPGR_DEF;
00303 
00304     /*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */ // I don't think so!
00305     /* Enable Reduced MII interface. */
00306     LPC_EMAC->MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
00307     NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
00308     LPC_EMAC->MCFG = MCFG_CLK_DIV20;
00309 
00310     /* Enable Reduced MII interface. */
00311     LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
00312 
00313     /* Reset Reduced MII Logic. */
00314     LPC_EMAC->SUPP = SUPP_RES_RMII | SUPP_SPEED;
00315     NyLPC_cThread_sleep( emacSHORT_DELAY_MS );
00316     LPC_EMAC->SUPP = SUPP_SPEED;
00317 
00318     /* Put the PHY in reset mode */
00319     EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, MCFG_RES_MII );
00320     NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5);
00321 
00322     /* Wait for hardware reset to end. */
00323     for( x = 0; x < 100; x++ )
00324     {
00325         NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
00326         us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMCR, &lDummy );
00327         if( !( us & MCFG_RES_MII ) )
00328         {
00329             /* Reset complete */
00330             break;
00331         }
00332     }
00333 }
00334 /*------------------------------------------------
00335  * Private function depend on device.
00336  * デバイス依存部分
00337  ------------------------------------------------*/
00338 
00339 
00340 /*for mbed
00341  */
00342 #define emacLINK_ESTABLISHED        ( 0x0001 )
00343 #define emacFULL_DUPLEX_ENABLED     ( 0x0004 )
00344 #define emac10BASE_T_MODE           ( 0x0002 )
00345 
00346 
00347 static void prvConfigurePHY( void )
00348 {
00349     unsigned short us;
00350     long x;
00351     NyLPC_TBool lDummy;
00352 
00353     /* Auto negotiate the configuration. */
00354     if( EthDev_LPC17xx_prvWritePHY( PHY_REG_BMCR, PHY_AUTO_NEG ) )
00355     {
00356         NyLPC_cThread_sleep( emacSHORT_DELAY_MS * 5 );
00357 
00358         for( x = 0; x < 10; x++ )
00359         {
00360             us = EthDev_LPC17xx_prvReadPHY( PHY_REG_BMSR, &lDummy );
00361 
00362             if( us & PHY_AUTO_NEG_COMPLETE )
00363             {
00364                 break;
00365             }
00366 
00367             NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
00368         }
00369     }
00370 }
00371 
00372 static NyLPC_TBool prvSetupLinkStatus( void )
00373 {
00374     NyLPC_TBool lReturn = NyLPC_TBool_FALSE;
00375     long x;
00376     unsigned short usLinkStatus;
00377 
00378     /* Wait with timeout for the link to be established. */
00379     for( x = 0; x < 10; x++ )
00380     {
00381         usLinkStatus = EthDev_LPC17xx_prvReadPHY( PHY_REG_STS, &lReturn );
00382         if( usLinkStatus & emacLINK_ESTABLISHED )
00383         {
00384             /* Link is established. */
00385             lReturn = NyLPC_TBool_TRUE;
00386             break;
00387         }
00388 
00389         NyLPC_cThread_sleep( emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
00390     }
00391 
00392     if( lReturn == NyLPC_TBool_TRUE )
00393     {
00394         /* Configure Full/Half Duplex mode. */
00395         if( usLinkStatus & emacFULL_DUPLEX_ENABLED )
00396         {
00397             /* Full duplex is enabled. */
00398             LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
00399             LPC_EMAC->Command |= CR_FULL_DUP;
00400             LPC_EMAC->IPGT = IPGT_FULL_DUP;
00401         }
00402         else
00403         {
00404             /* Half duplex mode. */
00405             LPC_EMAC->IPGT = IPGT_HALF_DUP;
00406         }
00407 
00408         /* Configure 100MBit/10MBit mode. */
00409         if( usLinkStatus & emac10BASE_T_MODE )
00410         {
00411             /* 10MBit mode. */
00412             LPC_EMAC->SUPP = 0;
00413         }
00414         else
00415         {
00416             /* 100MBit mode. */
00417             LPC_EMAC->SUPP = SUPP_SPEED;
00418         }
00419     }
00420 
00421     return lReturn;
00422 }
00423 
00424 /**
00425  * EMACからのハンドラ
00426  */
00427 static void emacIsrHandler(unsigned long i_status)
00428 {
00429     if( i_status & INT_RX_DONE )
00430     {
00431         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);
00432     }
00433     if( i_status & INT_TX_DONE )
00434     {
00435         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);
00436     }
00437 }
00438 
00439 #endif