Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dp83848.c
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
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2