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.
ar8031.c
00001 /** 00002 * @file ar8031.c 00003 * @brief AR8031 Gigabit 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/ar8031.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief AR8031 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver ar8031PhyDriver = 00043 { 00044 ar8031Init, 00045 ar8031Tick, 00046 ar8031EnableIrq, 00047 ar8031DisableIrq, 00048 ar8031EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief AR8031 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t ar8031Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing AR8031...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver 00068 ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Chip configuration register 00073 ar8031WritePhyReg(interface, AR8031_PHY_REG_CHIP_CONFIG, 00074 CHIP_CONFIG_BT_BX_REG_SEL | CHIP_CONFIG_PRIORITY_SEL); 00075 00076 //Basic mode control register 00077 ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR, 00078 BMCR_SPEED_SEL_LSB | BMCR_AN_EN | BMCR_DUPLEX_MODE); 00079 00080 //Auto-negotiation advertisement register 00081 ar8031WritePhyReg(interface, AR8031_PHY_REG_ANAR, 00082 ANAR_XNP_ABLE | ANAR_ASYMMETRIC_PAUSE | ANAR_PAUSE | ANAR_100BTX_FD | 00083 ANAR_100BTX_HD | ANAR_10BT_FD | ANAR_10BT_HD | ANAR_SELECTOR0); 00084 00085 //1000 BASE-T control register 00086 ar8031WritePhyReg(interface, AR8031_PHY_REG_1000BT_CTRL, 00087 _1000BT_CTRL_1000BT_FD); 00088 00089 //Function control register 00090 ar8031WritePhyReg(interface, AR8031_PHY_REG_FUNCTION_CTRL, 00091 FUNCTION_ASSERT_CRS_ON_TX | FUNCTION_MDI_CROSSOVER_MODE1 | 00092 FUNCTION_MDI_CROSSOVER_MODE0 | FUNCTION_POLARITY_REVERSAL); 00093 00094 //Dump PHY registers for debugging purpose 00095 ar8031DumpPhyReg(interface); 00096 00097 //The PHY will generate interrupts when link status changes are detected 00098 ar8031WritePhyReg(interface, AR8031_PHY_REG_INT_EN, 00099 INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS); 00100 00101 //Force the TCP/IP stack to poll the link state at startup 00102 interface->phyEvent = TRUE; 00103 //Notify the TCP/IP stack of the event 00104 osSetEvent(&netEvent); 00105 00106 //Successful initialization 00107 return NO_ERROR; 00108 } 00109 00110 00111 /** 00112 * @brief AR8031 timer handler 00113 * @param[in] interface Underlying network interface 00114 **/ 00115 00116 void ar8031Tick(NetInterface *interface) 00117 { 00118 uint16_t value; 00119 bool_t linkState; 00120 00121 //No external interrupt line driver? 00122 if(interface->extIntDriver == NULL) 00123 { 00124 //Read basic status register 00125 value = ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMSR); 00126 //Retrieve current link state 00127 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE; 00128 00129 //Link up event? 00130 if(linkState && !interface->linkState) 00131 { 00132 //Set event flag 00133 interface->phyEvent = TRUE; 00134 //Notify the TCP/IP stack of the event 00135 osSetEvent(&netEvent); 00136 } 00137 //Link down event? 00138 else if(!linkState && interface->linkState) 00139 { 00140 //Set event flag 00141 interface->phyEvent = TRUE; 00142 //Notify the TCP/IP stack of the event 00143 osSetEvent(&netEvent); 00144 } 00145 } 00146 } 00147 00148 00149 /** 00150 * @brief Enable interrupts 00151 * @param[in] interface Underlying network interface 00152 **/ 00153 00154 void ar8031EnableIrq(NetInterface *interface) 00155 { 00156 //Enable PHY transceiver interrupts 00157 if(interface->extIntDriver != NULL) 00158 interface->extIntDriver->enableIrq(); 00159 } 00160 00161 00162 /** 00163 * @brief Disable interrupts 00164 * @param[in] interface Underlying network interface 00165 **/ 00166 00167 void ar8031DisableIrq(NetInterface *interface) 00168 { 00169 //Disable PHY transceiver interrupts 00170 if(interface->extIntDriver != NULL) 00171 interface->extIntDriver->disableIrq(); 00172 } 00173 00174 00175 /** 00176 * @brief AR8031 event handler 00177 * @param[in] interface Underlying network interface 00178 **/ 00179 00180 void ar8031EventHandler(NetInterface *interface) 00181 { 00182 uint16_t status; 00183 00184 //Read status register to acknowledge the interrupt 00185 status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_INT_STATUS); 00186 00187 //Link status change? 00188 if(status & (INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS)) 00189 { 00190 //Read PHY status register 00191 status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_PHY_STATUS); 00192 00193 //Link is up? 00194 if(status & PHY_STATUS_LINK) 00195 { 00196 //Check current speed 00197 switch(status & PHY_STATUS_SPEED_MASK) 00198 { 00199 //10BASE-T 00200 case PHY_STATUS_SPEED_10: 00201 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00202 break; 00203 //100BASE-TX 00204 case PHY_STATUS_SPEED_100: 00205 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00206 break; 00207 //1000BASE-T 00208 case PHY_STATUS_SPEED_1000: 00209 interface->linkSpeed = NIC_LINK_SPEED_1GBPS; 00210 break; 00211 //Unknown speed 00212 default: 00213 //Debug message 00214 TRACE_WARNING("Invalid speed\r\n"); 00215 break; 00216 } 00217 00218 //Check current duplex mode 00219 if(status & PHY_STATUS_DUPLEX) 00220 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00221 else 00222 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00223 00224 //Update link state 00225 interface->linkState = TRUE; 00226 00227 //Adjust MAC configuration parameters for proper operation 00228 interface->nicDriver->updateMacConfig(interface); 00229 } 00230 else 00231 { 00232 //Update link state 00233 interface->linkState = FALSE; 00234 } 00235 00236 //Process link state change event 00237 nicNotifyLinkChange(interface); 00238 } 00239 } 00240 00241 00242 /** 00243 * @brief Write PHY register 00244 * @param[in] interface Underlying network interface 00245 * @param[in] address PHY register address 00246 * @param[in] data Register value 00247 **/ 00248 00249 void ar8031WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00250 { 00251 uint8_t phyAddr; 00252 00253 //Get the address of the PHY transceiver 00254 if(interface->phyAddr < 32) 00255 phyAddr = interface->phyAddr; 00256 else 00257 phyAddr = AR8031_PHY_ADDR; 00258 00259 //Write the specified PHY register 00260 interface->nicDriver->writePhyReg(phyAddr, address, data); 00261 } 00262 00263 00264 /** 00265 * @brief Read PHY register 00266 * @param[in] interface Underlying network interface 00267 * @param[in] address PHY register address 00268 * @return Register value 00269 **/ 00270 00271 uint16_t ar8031ReadPhyReg(NetInterface *interface, uint8_t address) 00272 { 00273 uint8_t phyAddr; 00274 00275 //Get the address of the PHY transceiver 00276 if(interface->phyAddr < 32) 00277 phyAddr = interface->phyAddr; 00278 else 00279 phyAddr = AR8031_PHY_ADDR; 00280 00281 //Read the specified PHY register 00282 return interface->nicDriver->readPhyReg(phyAddr, address); 00283 } 00284 00285 00286 /** 00287 * @brief Dump PHY registers for debugging purpose 00288 * @param[in] interface Underlying network interface 00289 **/ 00290 00291 void ar8031DumpPhyReg(NetInterface *interface) 00292 { 00293 uint8_t i; 00294 00295 //Loop through PHY registers 00296 for(i = 0; i < 32; i++) 00297 { 00298 //Display current PHY register 00299 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, ar8031ReadPhyReg(interface, i)); 00300 } 00301 00302 //Terminate with a line feed 00303 TRACE_DEBUG("\r\n"); 00304 } 00305
Generated on Tue Jul 12 2022 17:10:12 by
1.7.2