Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dp83848.c Source File

dp83848.c

Go to the documentation of this file.
00001 /**
00002  * @file dp83848.c
00003  * @brief DP83848 Ethernet PHY transceiver
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "drivers/dp83848.h"
00035 #include "debug.h"
00036 
00037 
00038 /**
00039  * @brief DP83848 Ethernet PHY driver
00040  **/
00041 
00042 const PhyDriver dp83848PhyDriver =
00043 {
00044    dp83848Init,
00045    dp83848Tick,
00046    dp83848EnableIrq,
00047    dp83848DisableIrq,
00048    dp83848EventHandler,
00049 };
00050 
00051 
00052 /**
00053  * @brief DP83848 PHY transceiver initialization
00054  * @param[in] interface Underlying network interface
00055  * @return Error code
00056  **/
00057 
00058 error_t dp83848Init(NetInterface *interface)
00059 {
00060    //Debug message
00061    TRACE_INFO("Initializing DP83848...\r\n");
00062 
00063    //Initialize external interrupt line driver
00064    if(interface->extIntDriver != NULL)
00065       interface->extIntDriver->init();
00066 
00067    //Reset PHY transceiver
00068    dp83848WritePhyReg(interface, DP83848_PHY_REG_BMCR, BMCR_RESET);
00069    //Wait for the reset to complete
00070    while(dp83848ReadPhyReg(interface, DP83848_PHY_REG_BMCR) & BMCR_RESET);
00071 
00072    //Dump PHY registers for debugging purpose
00073    dp83848DumpPhyReg(interface);
00074 
00075    //Configure PWR_DOWN/INT pin as an interrupt output
00076    dp83848WritePhyReg(interface, DP83848_PHY_REG_MICR, MICR_INTEN | MICR_INT_OE);
00077    //The PHY will generate interrupts when link status changes are detected
00078    dp83848WritePhyReg(interface, DP83848_PHY_REG_MISR, MISR_LINK_INT_EN);
00079 
00080    //Force the TCP/IP stack to poll the link state at startup
00081    interface->phyEvent = TRUE;
00082    //Notify the TCP/IP stack of the event
00083    osSetEvent(&netEvent);
00084 
00085    //Successful initialization
00086    return NO_ERROR;
00087 }
00088 
00089 
00090 /**
00091  * @brief DP83848 timer handler
00092  * @param[in] interface Underlying network interface
00093  **/
00094 
00095 void dp83848Tick(NetInterface *interface)
00096 {
00097    uint16_t value;
00098    bool_t linkState;
00099 
00100    //No external interrupt line driver?
00101    if(interface->extIntDriver == NULL)
00102    {
00103       //Read basic status register
00104       value = dp83848ReadPhyReg(interface, DP83848_PHY_REG_BMSR);
00105       //Retrieve current link state
00106       linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE;
00107 
00108       //Link up event?
00109       if(linkState && !interface->linkState)
00110       {
00111          //Set event flag
00112          interface->phyEvent = TRUE;
00113          //Notify the TCP/IP stack of the event
00114          osSetEvent(&netEvent);
00115       }
00116       //Link down event?
00117       else if(!linkState && interface->linkState)
00118       {
00119          //Set event flag
00120          interface->phyEvent = TRUE;
00121          //Notify the TCP/IP stack of the event
00122          osSetEvent(&netEvent);
00123       }
00124    }
00125 }
00126 
00127 
00128 /**
00129  * @brief Enable interrupts
00130  * @param[in] interface Underlying network interface
00131  **/
00132 
00133 void dp83848EnableIrq(NetInterface *interface)
00134 {
00135    //Enable PHY transceiver interrupts
00136    if(interface->extIntDriver != NULL)
00137       interface->extIntDriver->enableIrq();
00138 }
00139 
00140 
00141 /**
00142  * @brief Disable interrupts
00143  * @param[in] interface Underlying network interface
00144  **/
00145 
00146 void dp83848DisableIrq(NetInterface *interface)
00147 {
00148    //Disable PHY transceiver interrupts
00149    if(interface->extIntDriver != NULL)
00150       interface->extIntDriver->disableIrq();
00151 }
00152 
00153 
00154 /**
00155  * @brief DP83848 event handler
00156  * @param[in] interface Underlying network interface
00157  **/
00158 
00159 void dp83848EventHandler(NetInterface *interface)
00160 {
00161    uint16_t status;
00162 
00163    //Read status register to acknowledge the interrupt
00164    status = dp83848ReadPhyReg(interface, DP83848_PHY_REG_MISR);
00165 
00166    //Link status change?
00167    if(status & MISR_LINK_INT)
00168    {
00169       //Read PHY status register
00170       status = dp83848ReadPhyReg(interface, DP83848_PHY_REG_PHYSTS);
00171 
00172       //Link is up?
00173       if(status & PHYSTS_LINK_STATUS)
00174       {
00175          //Check current speed
00176          if(status & PHYSTS_SPEED_STATUS)
00177             interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
00178          else
00179             interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
00180 
00181          //Check duplex mode
00182          if(status & PHYSTS_DUPLEX_STATUS)
00183             interface->duplexMode = NIC_FULL_DUPLEX_MODE;
00184          else
00185             interface->duplexMode = NIC_HALF_DUPLEX_MODE;
00186 
00187          //Update link state
00188          interface->linkState = TRUE;
00189 
00190          //Adjust MAC configuration parameters for proper operation
00191          interface->nicDriver->updateMacConfig(interface);
00192       }
00193       else
00194       {
00195          //Update link state
00196          interface->linkState = FALSE;
00197       }
00198 
00199       //Process link state change event
00200       nicNotifyLinkChange(interface);
00201    }
00202 }
00203 
00204 
00205 /**
00206  * @brief Write PHY register
00207  * @param[in] interface Underlying network interface
00208  * @param[in] address PHY register address
00209  * @param[in] data Register value
00210  **/
00211 
00212 void dp83848WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
00213 {
00214    uint8_t phyAddr;
00215 
00216    //Get the address of the PHY transceiver
00217    if(interface->phyAddr < 32)
00218       phyAddr = interface->phyAddr;
00219    else
00220       phyAddr = DP83848_PHY_ADDR;
00221 
00222    //Write the specified PHY register
00223    interface->nicDriver->writePhyReg(phyAddr, address, data);
00224 }
00225 
00226 
00227 /**
00228  * @brief Read PHY register
00229  * @param[in] interface Underlying network interface
00230  * @param[in] address PHY register address
00231  * @return Register value
00232  **/
00233 
00234 uint16_t dp83848ReadPhyReg(NetInterface *interface, uint8_t address)
00235 {
00236    uint8_t phyAddr;
00237 
00238    //Get the address of the PHY transceiver
00239    if(interface->phyAddr < 32)
00240       phyAddr = interface->phyAddr;
00241    else
00242       phyAddr = DP83848_PHY_ADDR;
00243 
00244    //Read the specified PHY register
00245    return interface->nicDriver->readPhyReg(phyAddr, address);
00246 }
00247 
00248 
00249 /**
00250  * @brief Dump PHY registers for debugging purpose
00251  * @param[in] interface Underlying network interface
00252  **/
00253 
00254 void dp83848DumpPhyReg(NetInterface *interface)
00255 {
00256    uint8_t i;
00257 
00258    //Loop through PHY registers
00259    for(i = 0; i < 32; i++)
00260    {
00261       //Display current PHY register
00262       TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, dp83848ReadPhyReg(interface, i));
00263    }
00264 
00265    //Terminate with a line feed
00266    TRACE_DEBUG("\r\n");
00267 }
00268