Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ar8031.c
Sergunb 0:8918a71cdbe9 3 * @brief AR8031 Gigabit Ethernet PHY transceiver
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL NIC_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include "core/net.h"
Sergunb 0:8918a71cdbe9 34 #include "drivers/ar8031.h"
Sergunb 0:8918a71cdbe9 35 #include "debug.h"
Sergunb 0:8918a71cdbe9 36
Sergunb 0:8918a71cdbe9 37
Sergunb 0:8918a71cdbe9 38 /**
Sergunb 0:8918a71cdbe9 39 * @brief AR8031 Ethernet PHY driver
Sergunb 0:8918a71cdbe9 40 **/
Sergunb 0:8918a71cdbe9 41
Sergunb 0:8918a71cdbe9 42 const PhyDriver ar8031PhyDriver =
Sergunb 0:8918a71cdbe9 43 {
Sergunb 0:8918a71cdbe9 44 ar8031Init,
Sergunb 0:8918a71cdbe9 45 ar8031Tick,
Sergunb 0:8918a71cdbe9 46 ar8031EnableIrq,
Sergunb 0:8918a71cdbe9 47 ar8031DisableIrq,
Sergunb 0:8918a71cdbe9 48 ar8031EventHandler,
Sergunb 0:8918a71cdbe9 49 };
Sergunb 0:8918a71cdbe9 50
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 /**
Sergunb 0:8918a71cdbe9 53 * @brief AR8031 PHY transceiver initialization
Sergunb 0:8918a71cdbe9 54 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 55 * @return Error code
Sergunb 0:8918a71cdbe9 56 **/
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58 error_t ar8031Init(NetInterface *interface)
Sergunb 0:8918a71cdbe9 59 {
Sergunb 0:8918a71cdbe9 60 //Debug message
Sergunb 0:8918a71cdbe9 61 TRACE_INFO("Initializing AR8031...\r\n");
Sergunb 0:8918a71cdbe9 62
Sergunb 0:8918a71cdbe9 63 //Initialize external interrupt line driver
Sergunb 0:8918a71cdbe9 64 if(interface->extIntDriver != NULL)
Sergunb 0:8918a71cdbe9 65 interface->extIntDriver->init();
Sergunb 0:8918a71cdbe9 66
Sergunb 0:8918a71cdbe9 67 //Reset PHY transceiver
Sergunb 0:8918a71cdbe9 68 ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR, BMCR_RESET);
Sergunb 0:8918a71cdbe9 69 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 70 while(ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMCR) & BMCR_RESET);
Sergunb 0:8918a71cdbe9 71
Sergunb 0:8918a71cdbe9 72 //Chip configuration register
Sergunb 0:8918a71cdbe9 73 ar8031WritePhyReg(interface, AR8031_PHY_REG_CHIP_CONFIG,
Sergunb 0:8918a71cdbe9 74 CHIP_CONFIG_BT_BX_REG_SEL | CHIP_CONFIG_PRIORITY_SEL);
Sergunb 0:8918a71cdbe9 75
Sergunb 0:8918a71cdbe9 76 //Basic mode control register
Sergunb 0:8918a71cdbe9 77 ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR,
Sergunb 0:8918a71cdbe9 78 BMCR_SPEED_SEL_LSB | BMCR_AN_EN | BMCR_DUPLEX_MODE);
Sergunb 0:8918a71cdbe9 79
Sergunb 0:8918a71cdbe9 80 //Auto-negotiation advertisement register
Sergunb 0:8918a71cdbe9 81 ar8031WritePhyReg(interface, AR8031_PHY_REG_ANAR,
Sergunb 0:8918a71cdbe9 82 ANAR_XNP_ABLE | ANAR_ASYMMETRIC_PAUSE | ANAR_PAUSE | ANAR_100BTX_FD |
Sergunb 0:8918a71cdbe9 83 ANAR_100BTX_HD | ANAR_10BT_FD | ANAR_10BT_HD | ANAR_SELECTOR0);
Sergunb 0:8918a71cdbe9 84
Sergunb 0:8918a71cdbe9 85 //1000 BASE-T control register
Sergunb 0:8918a71cdbe9 86 ar8031WritePhyReg(interface, AR8031_PHY_REG_1000BT_CTRL,
Sergunb 0:8918a71cdbe9 87 _1000BT_CTRL_1000BT_FD);
Sergunb 0:8918a71cdbe9 88
Sergunb 0:8918a71cdbe9 89 //Function control register
Sergunb 0:8918a71cdbe9 90 ar8031WritePhyReg(interface, AR8031_PHY_REG_FUNCTION_CTRL,
Sergunb 0:8918a71cdbe9 91 FUNCTION_ASSERT_CRS_ON_TX | FUNCTION_MDI_CROSSOVER_MODE1 |
Sergunb 0:8918a71cdbe9 92 FUNCTION_MDI_CROSSOVER_MODE0 | FUNCTION_POLARITY_REVERSAL);
Sergunb 0:8918a71cdbe9 93
Sergunb 0:8918a71cdbe9 94 //Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 95 ar8031DumpPhyReg(interface);
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 //The PHY will generate interrupts when link status changes are detected
Sergunb 0:8918a71cdbe9 98 ar8031WritePhyReg(interface, AR8031_PHY_REG_INT_EN,
Sergunb 0:8918a71cdbe9 99 INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS);
Sergunb 0:8918a71cdbe9 100
Sergunb 0:8918a71cdbe9 101 //Force the TCP/IP stack to poll the link state at startup
Sergunb 0:8918a71cdbe9 102 interface->phyEvent = TRUE;
Sergunb 0:8918a71cdbe9 103 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 104 osSetEvent(&netEvent);
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //Successful initialization
Sergunb 0:8918a71cdbe9 107 return NO_ERROR;
Sergunb 0:8918a71cdbe9 108 }
Sergunb 0:8918a71cdbe9 109
Sergunb 0:8918a71cdbe9 110
Sergunb 0:8918a71cdbe9 111 /**
Sergunb 0:8918a71cdbe9 112 * @brief AR8031 timer handler
Sergunb 0:8918a71cdbe9 113 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 114 **/
Sergunb 0:8918a71cdbe9 115
Sergunb 0:8918a71cdbe9 116 void ar8031Tick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 117 {
Sergunb 0:8918a71cdbe9 118 uint16_t value;
Sergunb 0:8918a71cdbe9 119 bool_t linkState;
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121 //No external interrupt line driver?
Sergunb 0:8918a71cdbe9 122 if(interface->extIntDriver == NULL)
Sergunb 0:8918a71cdbe9 123 {
Sergunb 0:8918a71cdbe9 124 //Read basic status register
Sergunb 0:8918a71cdbe9 125 value = ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMSR);
Sergunb 0:8918a71cdbe9 126 //Retrieve current link state
Sergunb 0:8918a71cdbe9 127 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE;
Sergunb 0:8918a71cdbe9 128
Sergunb 0:8918a71cdbe9 129 //Link up event?
Sergunb 0:8918a71cdbe9 130 if(linkState && !interface->linkState)
Sergunb 0:8918a71cdbe9 131 {
Sergunb 0:8918a71cdbe9 132 //Set event flag
Sergunb 0:8918a71cdbe9 133 interface->phyEvent = TRUE;
Sergunb 0:8918a71cdbe9 134 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 135 osSetEvent(&netEvent);
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137 //Link down event?
Sergunb 0:8918a71cdbe9 138 else if(!linkState && interface->linkState)
Sergunb 0:8918a71cdbe9 139 {
Sergunb 0:8918a71cdbe9 140 //Set event flag
Sergunb 0:8918a71cdbe9 141 interface->phyEvent = TRUE;
Sergunb 0:8918a71cdbe9 142 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 143 osSetEvent(&netEvent);
Sergunb 0:8918a71cdbe9 144 }
Sergunb 0:8918a71cdbe9 145 }
Sergunb 0:8918a71cdbe9 146 }
Sergunb 0:8918a71cdbe9 147
Sergunb 0:8918a71cdbe9 148
Sergunb 0:8918a71cdbe9 149 /**
Sergunb 0:8918a71cdbe9 150 * @brief Enable interrupts
Sergunb 0:8918a71cdbe9 151 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 152 **/
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 void ar8031EnableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 155 {
Sergunb 0:8918a71cdbe9 156 //Enable PHY transceiver interrupts
Sergunb 0:8918a71cdbe9 157 if(interface->extIntDriver != NULL)
Sergunb 0:8918a71cdbe9 158 interface->extIntDriver->enableIrq();
Sergunb 0:8918a71cdbe9 159 }
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161
Sergunb 0:8918a71cdbe9 162 /**
Sergunb 0:8918a71cdbe9 163 * @brief Disable interrupts
Sergunb 0:8918a71cdbe9 164 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 165 **/
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167 void ar8031DisableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 168 {
Sergunb 0:8918a71cdbe9 169 //Disable PHY transceiver interrupts
Sergunb 0:8918a71cdbe9 170 if(interface->extIntDriver != NULL)
Sergunb 0:8918a71cdbe9 171 interface->extIntDriver->disableIrq();
Sergunb 0:8918a71cdbe9 172 }
Sergunb 0:8918a71cdbe9 173
Sergunb 0:8918a71cdbe9 174
Sergunb 0:8918a71cdbe9 175 /**
Sergunb 0:8918a71cdbe9 176 * @brief AR8031 event handler
Sergunb 0:8918a71cdbe9 177 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 178 **/
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180 void ar8031EventHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 uint16_t status;
Sergunb 0:8918a71cdbe9 183
Sergunb 0:8918a71cdbe9 184 //Read status register to acknowledge the interrupt
Sergunb 0:8918a71cdbe9 185 status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_INT_STATUS);
Sergunb 0:8918a71cdbe9 186
Sergunb 0:8918a71cdbe9 187 //Link status change?
Sergunb 0:8918a71cdbe9 188 if(status & (INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS))
Sergunb 0:8918a71cdbe9 189 {
Sergunb 0:8918a71cdbe9 190 //Read PHY status register
Sergunb 0:8918a71cdbe9 191 status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_PHY_STATUS);
Sergunb 0:8918a71cdbe9 192
Sergunb 0:8918a71cdbe9 193 //Link is up?
Sergunb 0:8918a71cdbe9 194 if(status & PHY_STATUS_LINK)
Sergunb 0:8918a71cdbe9 195 {
Sergunb 0:8918a71cdbe9 196 //Check current speed
Sergunb 0:8918a71cdbe9 197 switch(status & PHY_STATUS_SPEED_MASK)
Sergunb 0:8918a71cdbe9 198 {
Sergunb 0:8918a71cdbe9 199 //10BASE-T
Sergunb 0:8918a71cdbe9 200 case PHY_STATUS_SPEED_10:
Sergunb 0:8918a71cdbe9 201 interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
Sergunb 0:8918a71cdbe9 202 break;
Sergunb 0:8918a71cdbe9 203 //100BASE-TX
Sergunb 0:8918a71cdbe9 204 case PHY_STATUS_SPEED_100:
Sergunb 0:8918a71cdbe9 205 interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
Sergunb 0:8918a71cdbe9 206 break;
Sergunb 0:8918a71cdbe9 207 //1000BASE-T
Sergunb 0:8918a71cdbe9 208 case PHY_STATUS_SPEED_1000:
Sergunb 0:8918a71cdbe9 209 interface->linkSpeed = NIC_LINK_SPEED_1GBPS;
Sergunb 0:8918a71cdbe9 210 break;
Sergunb 0:8918a71cdbe9 211 //Unknown speed
Sergunb 0:8918a71cdbe9 212 default:
Sergunb 0:8918a71cdbe9 213 //Debug message
Sergunb 0:8918a71cdbe9 214 TRACE_WARNING("Invalid speed\r\n");
Sergunb 0:8918a71cdbe9 215 break;
Sergunb 0:8918a71cdbe9 216 }
Sergunb 0:8918a71cdbe9 217
Sergunb 0:8918a71cdbe9 218 //Check current duplex mode
Sergunb 0:8918a71cdbe9 219 if(status & PHY_STATUS_DUPLEX)
Sergunb 0:8918a71cdbe9 220 interface->duplexMode = NIC_FULL_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 221 else
Sergunb 0:8918a71cdbe9 222 interface->duplexMode = NIC_HALF_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 223
Sergunb 0:8918a71cdbe9 224 //Update link state
Sergunb 0:8918a71cdbe9 225 interface->linkState = TRUE;
Sergunb 0:8918a71cdbe9 226
Sergunb 0:8918a71cdbe9 227 //Adjust MAC configuration parameters for proper operation
Sergunb 0:8918a71cdbe9 228 interface->nicDriver->updateMacConfig(interface);
Sergunb 0:8918a71cdbe9 229 }
Sergunb 0:8918a71cdbe9 230 else
Sergunb 0:8918a71cdbe9 231 {
Sergunb 0:8918a71cdbe9 232 //Update link state
Sergunb 0:8918a71cdbe9 233 interface->linkState = FALSE;
Sergunb 0:8918a71cdbe9 234 }
Sergunb 0:8918a71cdbe9 235
Sergunb 0:8918a71cdbe9 236 //Process link state change event
Sergunb 0:8918a71cdbe9 237 nicNotifyLinkChange(interface);
Sergunb 0:8918a71cdbe9 238 }
Sergunb 0:8918a71cdbe9 239 }
Sergunb 0:8918a71cdbe9 240
Sergunb 0:8918a71cdbe9 241
Sergunb 0:8918a71cdbe9 242 /**
Sergunb 0:8918a71cdbe9 243 * @brief Write PHY register
Sergunb 0:8918a71cdbe9 244 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 245 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 246 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 247 **/
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249 void ar8031WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
Sergunb 0:8918a71cdbe9 250 {
Sergunb 0:8918a71cdbe9 251 uint8_t phyAddr;
Sergunb 0:8918a71cdbe9 252
Sergunb 0:8918a71cdbe9 253 //Get the address of the PHY transceiver
Sergunb 0:8918a71cdbe9 254 if(interface->phyAddr < 32)
Sergunb 0:8918a71cdbe9 255 phyAddr = interface->phyAddr;
Sergunb 0:8918a71cdbe9 256 else
Sergunb 0:8918a71cdbe9 257 phyAddr = AR8031_PHY_ADDR;
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Write the specified PHY register
Sergunb 0:8918a71cdbe9 260 interface->nicDriver->writePhyReg(phyAddr, address, data);
Sergunb 0:8918a71cdbe9 261 }
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263
Sergunb 0:8918a71cdbe9 264 /**
Sergunb 0:8918a71cdbe9 265 * @brief Read PHY register
Sergunb 0:8918a71cdbe9 266 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 267 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 268 * @return Register value
Sergunb 0:8918a71cdbe9 269 **/
Sergunb 0:8918a71cdbe9 270
Sergunb 0:8918a71cdbe9 271 uint16_t ar8031ReadPhyReg(NetInterface *interface, uint8_t address)
Sergunb 0:8918a71cdbe9 272 {
Sergunb 0:8918a71cdbe9 273 uint8_t phyAddr;
Sergunb 0:8918a71cdbe9 274
Sergunb 0:8918a71cdbe9 275 //Get the address of the PHY transceiver
Sergunb 0:8918a71cdbe9 276 if(interface->phyAddr < 32)
Sergunb 0:8918a71cdbe9 277 phyAddr = interface->phyAddr;
Sergunb 0:8918a71cdbe9 278 else
Sergunb 0:8918a71cdbe9 279 phyAddr = AR8031_PHY_ADDR;
Sergunb 0:8918a71cdbe9 280
Sergunb 0:8918a71cdbe9 281 //Read the specified PHY register
Sergunb 0:8918a71cdbe9 282 return interface->nicDriver->readPhyReg(phyAddr, address);
Sergunb 0:8918a71cdbe9 283 }
Sergunb 0:8918a71cdbe9 284
Sergunb 0:8918a71cdbe9 285
Sergunb 0:8918a71cdbe9 286 /**
Sergunb 0:8918a71cdbe9 287 * @brief Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 288 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 289 **/
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 void ar8031DumpPhyReg(NetInterface *interface)
Sergunb 0:8918a71cdbe9 292 {
Sergunb 0:8918a71cdbe9 293 uint8_t i;
Sergunb 0:8918a71cdbe9 294
Sergunb 0:8918a71cdbe9 295 //Loop through PHY registers
Sergunb 0:8918a71cdbe9 296 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 297 {
Sergunb 0:8918a71cdbe9 298 //Display current PHY register
Sergunb 0:8918a71cdbe9 299 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, ar8031ReadPhyReg(interface, i));
Sergunb 0:8918a71cdbe9 300 }
Sergunb 0:8918a71cdbe9 301
Sergunb 0:8918a71cdbe9 302 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 303 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 304 }
Sergunb 0:8918a71cdbe9 305