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 enc624j600.c
Sergunb 0:8918a71cdbe9 3 * @brief ENC624J600/ENC424J600 Ethernet controller
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/enc624j600.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 ENC624J600 driver
Sergunb 0:8918a71cdbe9 40 **/
Sergunb 0:8918a71cdbe9 41
Sergunb 0:8918a71cdbe9 42 const NicDriver enc624j600Driver =
Sergunb 0:8918a71cdbe9 43 {
Sergunb 0:8918a71cdbe9 44 NIC_TYPE_ETHERNET,
Sergunb 0:8918a71cdbe9 45 ETH_MTU,
Sergunb 0:8918a71cdbe9 46 enc624j600Init,
Sergunb 0:8918a71cdbe9 47 enc624j600Tick,
Sergunb 0:8918a71cdbe9 48 enc624j600EnableIrq,
Sergunb 0:8918a71cdbe9 49 enc624j600DisableIrq,
Sergunb 0:8918a71cdbe9 50 enc624j600EventHandler,
Sergunb 0:8918a71cdbe9 51 enc624j600SendPacket,
Sergunb 0:8918a71cdbe9 52 enc624j600SetMulticastFilter,
Sergunb 0:8918a71cdbe9 53 NULL,
Sergunb 0:8918a71cdbe9 54 NULL,
Sergunb 0:8918a71cdbe9 55 NULL,
Sergunb 0:8918a71cdbe9 56 TRUE,
Sergunb 0:8918a71cdbe9 57 TRUE,
Sergunb 0:8918a71cdbe9 58 TRUE,
Sergunb 0:8918a71cdbe9 59 FALSE
Sergunb 0:8918a71cdbe9 60 };
Sergunb 0:8918a71cdbe9 61
Sergunb 0:8918a71cdbe9 62
Sergunb 0:8918a71cdbe9 63 /**
Sergunb 0:8918a71cdbe9 64 * @brief ENC624J600 controller initialization
Sergunb 0:8918a71cdbe9 65 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 66 * @return Error code
Sergunb 0:8918a71cdbe9 67 **/
Sergunb 0:8918a71cdbe9 68
Sergunb 0:8918a71cdbe9 69 error_t enc624j600Init(NetInterface *interface)
Sergunb 0:8918a71cdbe9 70 {
Sergunb 0:8918a71cdbe9 71 Enc624j600Context *context;
Sergunb 0:8918a71cdbe9 72
Sergunb 0:8918a71cdbe9 73 //Debug message
Sergunb 0:8918a71cdbe9 74 TRACE_INFO("Initializing ENC624J600 Ethernet controller...\r\n");
Sergunb 0:8918a71cdbe9 75
Sergunb 0:8918a71cdbe9 76 //Initialize SPI
Sergunb 0:8918a71cdbe9 77 interface->spiDriver->init();
Sergunb 0:8918a71cdbe9 78 //Initialize external interrupt line
Sergunb 0:8918a71cdbe9 79 interface->extIntDriver->init();
Sergunb 0:8918a71cdbe9 80
Sergunb 0:8918a71cdbe9 81 //Point to the driver context
Sergunb 0:8918a71cdbe9 82 context = (Enc624j600Context *) interface->nicContext;
Sergunb 0:8918a71cdbe9 83
Sergunb 0:8918a71cdbe9 84 //Initialize driver specific variables
Sergunb 0:8918a71cdbe9 85 context->nextPacket = ENC624J600_RX_BUFFER_START;
Sergunb 0:8918a71cdbe9 86
Sergunb 0:8918a71cdbe9 87 //Allocate RX buffer
Sergunb 0:8918a71cdbe9 88 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE);
Sergunb 0:8918a71cdbe9 89 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 90 if(context->rxBuffer == NULL)
Sergunb 0:8918a71cdbe9 91 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 92
Sergunb 0:8918a71cdbe9 93 //Issue a system reset
Sergunb 0:8918a71cdbe9 94 enc624j600SoftReset(interface);
Sergunb 0:8918a71cdbe9 95
Sergunb 0:8918a71cdbe9 96 //Disable CLKOUT output
Sergunb 0:8918a71cdbe9 97 enc624j600WriteReg(interface, ENC624J600_REG_ECON2, ECON2_ETHEN | ECON2_STRCH);
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99 //Optionally set the station MAC address
Sergunb 0:8918a71cdbe9 100 if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 101 {
Sergunb 0:8918a71cdbe9 102 //Use the factory preprogrammed station address
Sergunb 0:8918a71cdbe9 103 interface->macAddr.w[0] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR1);
Sergunb 0:8918a71cdbe9 104 interface->macAddr.w[1] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR2);
Sergunb 0:8918a71cdbe9 105 interface->macAddr.w[2] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR3);
Sergunb 0:8918a71cdbe9 106
Sergunb 0:8918a71cdbe9 107 //Generate the 64-bit interface identifier
Sergunb 0:8918a71cdbe9 108 macAddrToEui64(&interface->macAddr, &interface->eui64);
Sergunb 0:8918a71cdbe9 109 }
Sergunb 0:8918a71cdbe9 110 else
Sergunb 0:8918a71cdbe9 111 {
Sergunb 0:8918a71cdbe9 112 //Override the factory preprogrammed address
Sergunb 0:8918a71cdbe9 113 enc624j600WriteReg(interface, ENC624J600_REG_MAADR1, interface->macAddr.w[0]);
Sergunb 0:8918a71cdbe9 114 enc624j600WriteReg(interface, ENC624J600_REG_MAADR2, interface->macAddr.w[1]);
Sergunb 0:8918a71cdbe9 115 enc624j600WriteReg(interface, ENC624J600_REG_MAADR3, interface->macAddr.w[2]);
Sergunb 0:8918a71cdbe9 116 }
Sergunb 0:8918a71cdbe9 117
Sergunb 0:8918a71cdbe9 118 //Set receive buffer location
Sergunb 0:8918a71cdbe9 119 enc624j600WriteReg(interface, ENC624J600_REG_ERXST, ENC624J600_RX_BUFFER_START);
Sergunb 0:8918a71cdbe9 120 //Program the tail pointer ERXTAIL to the last even address of the buffer
Sergunb 0:8918a71cdbe9 121 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP);
Sergunb 0:8918a71cdbe9 122
Sergunb 0:8918a71cdbe9 123 //Configure the receive filters
Sergunb 0:8918a71cdbe9 124 enc624j600WriteReg(interface, ENC624J600_REG_ERXFCON, ERXFCON_HTEN |
Sergunb 0:8918a71cdbe9 125 ERXFCON_CRCEN | ERXFCON_RUNTEN | ERXFCON_UCEN | ERXFCON_BCEN);
Sergunb 0:8918a71cdbe9 126
Sergunb 0:8918a71cdbe9 127 //Initialize the hash table
Sergunb 0:8918a71cdbe9 128 enc624j600WriteReg(interface, ENC624J600_REG_EHT1, 0x0000);
Sergunb 0:8918a71cdbe9 129 enc624j600WriteReg(interface, ENC624J600_REG_EHT2, 0x0000);
Sergunb 0:8918a71cdbe9 130 enc624j600WriteReg(interface, ENC624J600_REG_EHT3, 0x0000);
Sergunb 0:8918a71cdbe9 131 enc624j600WriteReg(interface, ENC624J600_REG_EHT4, 0x0000);
Sergunb 0:8918a71cdbe9 132
Sergunb 0:8918a71cdbe9 133 //All short frames will be zero-padded to 60 bytes and a valid CRC is then appended
Sergunb 0:8918a71cdbe9 134 enc624j600WriteReg(interface, ENC624J600_REG_MACON2,
Sergunb 0:8918a71cdbe9 135 MACON2_DEFER | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1);
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137 //Program the MAMXFL register with the maximum frame length to be accepted
Sergunb 0:8918a71cdbe9 138 enc624j600WriteReg(interface, ENC624J600_REG_MAMXFL, 1518);
Sergunb 0:8918a71cdbe9 139
Sergunb 0:8918a71cdbe9 140 //PHY initialization
Sergunb 0:8918a71cdbe9 141 enc624j600WritePhyReg(interface, ENC624J600_PHY_REG_PHANA, PHANA_ADPAUS0 |
Sergunb 0:8918a71cdbe9 142 PHANA_AD100FD | PHANA_AD100 | PHANA_AD10FD | PHANA_AD10 | PHANA_ADIEEE0);
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 //Clear interrupt flags
Sergunb 0:8918a71cdbe9 145 enc624j600WriteReg(interface, ENC624J600_REG_EIR, 0x0000);
Sergunb 0:8918a71cdbe9 146
Sergunb 0:8918a71cdbe9 147 //Configure interrupts as desired
Sergunb 0:8918a71cdbe9 148 enc624j600WriteReg(interface, ENC624J600_REG_EIE, EIE_INTIE |
Sergunb 0:8918a71cdbe9 149 EIE_LINKIE | EIE_PKTIE | EIE_TXIE | EIE_TXABTIE);
Sergunb 0:8918a71cdbe9 150
Sergunb 0:8918a71cdbe9 151 //Set RXEN to enable reception
Sergunb 0:8918a71cdbe9 152 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_RXEN);
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Dump registers for debugging purpose
Sergunb 0:8918a71cdbe9 155 enc624j600DumpReg(interface);
Sergunb 0:8918a71cdbe9 156 enc624j600DumpPhyReg(interface);
Sergunb 0:8918a71cdbe9 157
Sergunb 0:8918a71cdbe9 158 //Accept any packets from the upper layer
Sergunb 0:8918a71cdbe9 159 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161 //Force the TCP/IP stack to poll the link state at startup
Sergunb 0:8918a71cdbe9 162 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 163 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 164 osSetEvent(&netEvent);
Sergunb 0:8918a71cdbe9 165
Sergunb 0:8918a71cdbe9 166 //Successful initialization
Sergunb 0:8918a71cdbe9 167 return NO_ERROR;
Sergunb 0:8918a71cdbe9 168 }
Sergunb 0:8918a71cdbe9 169
Sergunb 0:8918a71cdbe9 170
Sergunb 0:8918a71cdbe9 171 /**
Sergunb 0:8918a71cdbe9 172 * @brief ENC624J600 timer handler
Sergunb 0:8918a71cdbe9 173 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 174 **/
Sergunb 0:8918a71cdbe9 175
Sergunb 0:8918a71cdbe9 176 void enc624j600Tick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 177 {
Sergunb 0:8918a71cdbe9 178 }
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180
Sergunb 0:8918a71cdbe9 181 /**
Sergunb 0:8918a71cdbe9 182 * @brief Enable interrupts
Sergunb 0:8918a71cdbe9 183 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 184 **/
Sergunb 0:8918a71cdbe9 185
Sergunb 0:8918a71cdbe9 186 void enc624j600EnableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 187 {
Sergunb 0:8918a71cdbe9 188 //Enable interrupts
Sergunb 0:8918a71cdbe9 189 interface->extIntDriver->enableIrq();
Sergunb 0:8918a71cdbe9 190 }
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192
Sergunb 0:8918a71cdbe9 193 /**
Sergunb 0:8918a71cdbe9 194 * @brief Disable interrupts
Sergunb 0:8918a71cdbe9 195 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 196 **/
Sergunb 0:8918a71cdbe9 197
Sergunb 0:8918a71cdbe9 198 void enc624j600DisableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 199 {
Sergunb 0:8918a71cdbe9 200 //Disable interrupts
Sergunb 0:8918a71cdbe9 201 interface->extIntDriver->disableIrq();
Sergunb 0:8918a71cdbe9 202 }
Sergunb 0:8918a71cdbe9 203
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 /**
Sergunb 0:8918a71cdbe9 206 * @brief ENC624J600 interrupt service routine
Sergunb 0:8918a71cdbe9 207 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 208 * @return TRUE if a higher priority task must be woken. Else FALSE is returned
Sergunb 0:8918a71cdbe9 209 **/
Sergunb 0:8918a71cdbe9 210
Sergunb 0:8918a71cdbe9 211 bool_t enc624j600IrqHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 212 {
Sergunb 0:8918a71cdbe9 213 bool_t flag;
Sergunb 0:8918a71cdbe9 214 uint16_t status;
Sergunb 0:8918a71cdbe9 215
Sergunb 0:8918a71cdbe9 216 //This flag will be set if a higher priority task must be woken
Sergunb 0:8918a71cdbe9 217 flag = FALSE;
Sergunb 0:8918a71cdbe9 218
Sergunb 0:8918a71cdbe9 219 //Clear the INTIE bit, immediately after an interrupt event
Sergunb 0:8918a71cdbe9 220 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_INTIE);
Sergunb 0:8918a71cdbe9 221
Sergunb 0:8918a71cdbe9 222 //Read interrupt status register
Sergunb 0:8918a71cdbe9 223 status = enc624j600ReadReg(interface, ENC624J600_REG_EIR);
Sergunb 0:8918a71cdbe9 224
Sergunb 0:8918a71cdbe9 225 //Link status change?
Sergunb 0:8918a71cdbe9 226 if(status & EIR_LINKIF)
Sergunb 0:8918a71cdbe9 227 {
Sergunb 0:8918a71cdbe9 228 //Disable LINKIE interrupt
Sergunb 0:8918a71cdbe9 229 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_LINKIE);
Sergunb 0:8918a71cdbe9 230
Sergunb 0:8918a71cdbe9 231 //Set event flag
Sergunb 0:8918a71cdbe9 232 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 233 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 234 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 235 }
Sergunb 0:8918a71cdbe9 236
Sergunb 0:8918a71cdbe9 237 //Packet received?
Sergunb 0:8918a71cdbe9 238 if(status & EIR_PKTIF)
Sergunb 0:8918a71cdbe9 239 {
Sergunb 0:8918a71cdbe9 240 //Disable PKTIE interrupt
Sergunb 0:8918a71cdbe9 241 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_PKTIE);
Sergunb 0:8918a71cdbe9 242
Sergunb 0:8918a71cdbe9 243 //Set event flag
Sergunb 0:8918a71cdbe9 244 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 245 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 246 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 247 }
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249 //Packet transmission complete?
Sergunb 0:8918a71cdbe9 250 if(status & (EIR_TXIF | EIR_TXABTIF))
Sergunb 0:8918a71cdbe9 251 {
Sergunb 0:8918a71cdbe9 252 //Clear interrupt flags
Sergunb 0:8918a71cdbe9 253 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF);
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Notify the TCP/IP stack that the transmitter is ready to send
Sergunb 0:8918a71cdbe9 256 flag |= osSetEventFromIsr(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 257 }
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Once the interrupt has been serviced, the INTIE bit
Sergunb 0:8918a71cdbe9 260 //is set again to re-enable interrupts
Sergunb 0:8918a71cdbe9 261 enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_INTIE);
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263 //A higher priority task must be woken?
Sergunb 0:8918a71cdbe9 264 return flag;
Sergunb 0:8918a71cdbe9 265 }
Sergunb 0:8918a71cdbe9 266
Sergunb 0:8918a71cdbe9 267
Sergunb 0:8918a71cdbe9 268 /**
Sergunb 0:8918a71cdbe9 269 * @brief ENC624J600 event handler
Sergunb 0:8918a71cdbe9 270 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 271 **/
Sergunb 0:8918a71cdbe9 272
Sergunb 0:8918a71cdbe9 273 void enc624j600EventHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 274 {
Sergunb 0:8918a71cdbe9 275 error_t error;
Sergunb 0:8918a71cdbe9 276 uint16_t status;
Sergunb 0:8918a71cdbe9 277 uint16_t value;
Sergunb 0:8918a71cdbe9 278
Sergunb 0:8918a71cdbe9 279 //Read interrupt status register
Sergunb 0:8918a71cdbe9 280 status = enc624j600ReadReg(interface, ENC624J600_REG_EIR);
Sergunb 0:8918a71cdbe9 281
Sergunb 0:8918a71cdbe9 282 //Check whether the link state has changed
Sergunb 0:8918a71cdbe9 283 if(status & EIR_LINKIF)
Sergunb 0:8918a71cdbe9 284 {
Sergunb 0:8918a71cdbe9 285 //Clear interrupt flag
Sergunb 0:8918a71cdbe9 286 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_LINKIF);
Sergunb 0:8918a71cdbe9 287 //Read Ethernet status register
Sergunb 0:8918a71cdbe9 288 value = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT);
Sergunb 0:8918a71cdbe9 289
Sergunb 0:8918a71cdbe9 290 //Check link state
Sergunb 0:8918a71cdbe9 291 if(value & ESTAT_PHYLNK)
Sergunb 0:8918a71cdbe9 292 {
Sergunb 0:8918a71cdbe9 293 //Read PHY status register 3
Sergunb 0:8918a71cdbe9 294 value = enc624j600ReadPhyReg(interface, ENC624J600_PHY_REG_PHSTAT3);
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296 //Get current speed
Sergunb 0:8918a71cdbe9 297 if(value & PHSTAT3_SPDDPX1)
Sergunb 0:8918a71cdbe9 298 interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
Sergunb 0:8918a71cdbe9 299 else
Sergunb 0:8918a71cdbe9 300 interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
Sergunb 0:8918a71cdbe9 301
Sergunb 0:8918a71cdbe9 302 //Determine the new duplex mode
Sergunb 0:8918a71cdbe9 303 if(value & PHSTAT3_SPDDPX2)
Sergunb 0:8918a71cdbe9 304 interface->duplexMode = NIC_FULL_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 305 else
Sergunb 0:8918a71cdbe9 306 interface->duplexMode = NIC_HALF_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 307
Sergunb 0:8918a71cdbe9 308 //Link is up
Sergunb 0:8918a71cdbe9 309 interface->linkState = TRUE;
Sergunb 0:8918a71cdbe9 310
Sergunb 0:8918a71cdbe9 311 //Update MAC configuration parameters for proper operation
Sergunb 0:8918a71cdbe9 312 enc624j600UpdateMacConfig(interface);
Sergunb 0:8918a71cdbe9 313 }
Sergunb 0:8918a71cdbe9 314 else
Sergunb 0:8918a71cdbe9 315 {
Sergunb 0:8918a71cdbe9 316 //Link is down
Sergunb 0:8918a71cdbe9 317 interface->linkState = FALSE;
Sergunb 0:8918a71cdbe9 318 }
Sergunb 0:8918a71cdbe9 319
Sergunb 0:8918a71cdbe9 320 //Process link state change event
Sergunb 0:8918a71cdbe9 321 nicNotifyLinkChange(interface);
Sergunb 0:8918a71cdbe9 322 }
Sergunb 0:8918a71cdbe9 323
Sergunb 0:8918a71cdbe9 324 //Check whether a packet has been received?
Sergunb 0:8918a71cdbe9 325 if(status & EIR_PKTIF)
Sergunb 0:8918a71cdbe9 326 {
Sergunb 0:8918a71cdbe9 327 //Clear interrupt flag
Sergunb 0:8918a71cdbe9 328 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_PKTIF);
Sergunb 0:8918a71cdbe9 329
Sergunb 0:8918a71cdbe9 330 //Process all pending packets
Sergunb 0:8918a71cdbe9 331 do
Sergunb 0:8918a71cdbe9 332 {
Sergunb 0:8918a71cdbe9 333 //Read incoming packet
Sergunb 0:8918a71cdbe9 334 error = enc624j600ReceivePacket(interface);
Sergunb 0:8918a71cdbe9 335
Sergunb 0:8918a71cdbe9 336 //No more data in the receive buffer?
Sergunb 0:8918a71cdbe9 337 } while(error != ERROR_BUFFER_EMPTY);
Sergunb 0:8918a71cdbe9 338 }
Sergunb 0:8918a71cdbe9 339
Sergunb 0:8918a71cdbe9 340 //Re-enable LINKIE and PKTIE interrupts
Sergunb 0:8918a71cdbe9 341 enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_LINKIE | EIE_PKTIE);
Sergunb 0:8918a71cdbe9 342 }
Sergunb 0:8918a71cdbe9 343
Sergunb 0:8918a71cdbe9 344
Sergunb 0:8918a71cdbe9 345 /**
Sergunb 0:8918a71cdbe9 346 * @brief Send a packet
Sergunb 0:8918a71cdbe9 347 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 348 * @param[in] buffer Multi-part buffer containing the data to send
Sergunb 0:8918a71cdbe9 349 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 350 * @return Error code
Sergunb 0:8918a71cdbe9 351 **/
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 error_t enc624j600SendPacket(NetInterface *interface,
Sergunb 0:8918a71cdbe9 354 const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 355 {
Sergunb 0:8918a71cdbe9 356 size_t length;
Sergunb 0:8918a71cdbe9 357
Sergunb 0:8918a71cdbe9 358 //Retrieve the length of the packet
Sergunb 0:8918a71cdbe9 359 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //Check the frame length
Sergunb 0:8918a71cdbe9 362 if(length > 1536)
Sergunb 0:8918a71cdbe9 363 {
Sergunb 0:8918a71cdbe9 364 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 365 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 366 //Report an error
Sergunb 0:8918a71cdbe9 367 return ERROR_INVALID_LENGTH;
Sergunb 0:8918a71cdbe9 368 }
Sergunb 0:8918a71cdbe9 369
Sergunb 0:8918a71cdbe9 370 //Make sure the link is up before transmitting the frame
Sergunb 0:8918a71cdbe9 371 if(!interface->linkState)
Sergunb 0:8918a71cdbe9 372 {
Sergunb 0:8918a71cdbe9 373 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 374 osSetEventFromIsr(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 375 //Drop current packet
Sergunb 0:8918a71cdbe9 376 return NO_ERROR;
Sergunb 0:8918a71cdbe9 377 }
Sergunb 0:8918a71cdbe9 378
Sergunb 0:8918a71cdbe9 379 //Ensure that the transmitter is ready to send
Sergunb 0:8918a71cdbe9 380 if(enc624j600ReadReg(interface, ENC624J600_REG_ECON1) & ECON1_TXRTS)
Sergunb 0:8918a71cdbe9 381 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 382
Sergunb 0:8918a71cdbe9 383 //Point to the SRAM buffer
Sergunb 0:8918a71cdbe9 384 enc624j600WriteReg(interface, ENC624J600_REG_EGPWRPT, ENC624J600_TX_BUFFER_START);
Sergunb 0:8918a71cdbe9 385 //Copy the packet to the SRAM buffer
Sergunb 0:8918a71cdbe9 386 enc624j600WriteBuffer(interface, ENC624J600_CMD_WGPDATA, buffer, offset);
Sergunb 0:8918a71cdbe9 387
Sergunb 0:8918a71cdbe9 388 //Program ETXST to the start address of the packet
Sergunb 0:8918a71cdbe9 389 enc624j600WriteReg(interface, ENC624J600_REG_ETXST, ENC624J600_TX_BUFFER_START);
Sergunb 0:8918a71cdbe9 390 //Program ETXLEN with the length of data copied to the memory
Sergunb 0:8918a71cdbe9 391 enc624j600WriteReg(interface, ENC624J600_REG_ETXLEN, length);
Sergunb 0:8918a71cdbe9 392
Sergunb 0:8918a71cdbe9 393 //Clear TXIF and TXABTIF interrupt flags
Sergunb 0:8918a71cdbe9 394 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF);
Sergunb 0:8918a71cdbe9 395 //Set the TXRTS bit to initiate transmission
Sergunb 0:8918a71cdbe9 396 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_TXRTS);
Sergunb 0:8918a71cdbe9 397
Sergunb 0:8918a71cdbe9 398 //Successful processing
Sergunb 0:8918a71cdbe9 399 return NO_ERROR;
Sergunb 0:8918a71cdbe9 400 }
Sergunb 0:8918a71cdbe9 401
Sergunb 0:8918a71cdbe9 402
Sergunb 0:8918a71cdbe9 403 /**
Sergunb 0:8918a71cdbe9 404 * @brief Receive a packet
Sergunb 0:8918a71cdbe9 405 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 406 * @return Error code
Sergunb 0:8918a71cdbe9 407 **/
Sergunb 0:8918a71cdbe9 408
Sergunb 0:8918a71cdbe9 409 error_t enc624j600ReceivePacket(NetInterface *interface)
Sergunb 0:8918a71cdbe9 410 {
Sergunb 0:8918a71cdbe9 411 error_t error;
Sergunb 0:8918a71cdbe9 412 uint16_t n;
Sergunb 0:8918a71cdbe9 413 uint32_t status;
Sergunb 0:8918a71cdbe9 414 Enc624j600Context *context;
Sergunb 0:8918a71cdbe9 415
Sergunb 0:8918a71cdbe9 416 //Point to the driver context
Sergunb 0:8918a71cdbe9 417 context = (Enc624j600Context *) interface->nicContext;
Sergunb 0:8918a71cdbe9 418
Sergunb 0:8918a71cdbe9 419 //Verify that a packet is waiting by ensuring that PKTCNT is non-zero
Sergunb 0:8918a71cdbe9 420 if(enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PKTCNT)
Sergunb 0:8918a71cdbe9 421 {
Sergunb 0:8918a71cdbe9 422 //Point to the next packet
Sergunb 0:8918a71cdbe9 423 enc624j600WriteReg(interface, ENC624J600_REG_ERXRDPT, context->nextPacket);
Sergunb 0:8918a71cdbe9 424
Sergunb 0:8918a71cdbe9 425 //Read the first two bytes, which are the address of the next packet
Sergunb 0:8918a71cdbe9 426 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
Sergunb 0:8918a71cdbe9 427 (uint8_t *) &context->nextPacket, sizeof(uint16_t));
Sergunb 0:8918a71cdbe9 428
Sergunb 0:8918a71cdbe9 429 //Get the length of the received frame in bytes
Sergunb 0:8918a71cdbe9 430 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
Sergunb 0:8918a71cdbe9 431 (uint8_t *) &n, sizeof(uint16_t));
Sergunb 0:8918a71cdbe9 432
Sergunb 0:8918a71cdbe9 433 //Read the receive status vector (RSV)
Sergunb 0:8918a71cdbe9 434 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
Sergunb 0:8918a71cdbe9 435 (uint8_t *) &status, sizeof(uint32_t));
Sergunb 0:8918a71cdbe9 436
Sergunb 0:8918a71cdbe9 437 //Make sure no error occurred
Sergunb 0:8918a71cdbe9 438 if(status & RSV_RECEIVED_OK)
Sergunb 0:8918a71cdbe9 439 {
Sergunb 0:8918a71cdbe9 440 //Limit the number of data to read
Sergunb 0:8918a71cdbe9 441 n = MIN(n, ETH_MAX_FRAME_SIZE);
Sergunb 0:8918a71cdbe9 442 //Read the Ethernet frame
Sergunb 0:8918a71cdbe9 443 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, context->rxBuffer, n);
Sergunb 0:8918a71cdbe9 444 //Valid packet received
Sergunb 0:8918a71cdbe9 445 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 446 }
Sergunb 0:8918a71cdbe9 447 else
Sergunb 0:8918a71cdbe9 448 {
Sergunb 0:8918a71cdbe9 449 //The received packet contains an error
Sergunb 0:8918a71cdbe9 450 error = ERROR_INVALID_PACKET;
Sergunb 0:8918a71cdbe9 451 }
Sergunb 0:8918a71cdbe9 452
Sergunb 0:8918a71cdbe9 453 //Update the ERXTAIL pointer value to the point where the packet
Sergunb 0:8918a71cdbe9 454 //has been processed, taking care to wrap back at the end of the
Sergunb 0:8918a71cdbe9 455 //received memory buffer
Sergunb 0:8918a71cdbe9 456 if(context->nextPacket == ENC624J600_RX_BUFFER_START)
Sergunb 0:8918a71cdbe9 457 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP);
Sergunb 0:8918a71cdbe9 458 else
Sergunb 0:8918a71cdbe9 459 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, context->nextPacket - 2);
Sergunb 0:8918a71cdbe9 460
Sergunb 0:8918a71cdbe9 461 //Set PKTDEC to decrement the PKTCNT bits
Sergunb 0:8918a71cdbe9 462 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_PKTDEC);
Sergunb 0:8918a71cdbe9 463 }
Sergunb 0:8918a71cdbe9 464 else
Sergunb 0:8918a71cdbe9 465 {
Sergunb 0:8918a71cdbe9 466 //No more data in the receive buffer
Sergunb 0:8918a71cdbe9 467 error = ERROR_BUFFER_EMPTY;
Sergunb 0:8918a71cdbe9 468 }
Sergunb 0:8918a71cdbe9 469
Sergunb 0:8918a71cdbe9 470 //Check whether a valid packet has been received
Sergunb 0:8918a71cdbe9 471 if(!error)
Sergunb 0:8918a71cdbe9 472 {
Sergunb 0:8918a71cdbe9 473 //Pass the packet to the upper layer
Sergunb 0:8918a71cdbe9 474 nicProcessPacket(interface, context->rxBuffer, n);
Sergunb 0:8918a71cdbe9 475 }
Sergunb 0:8918a71cdbe9 476
Sergunb 0:8918a71cdbe9 477 //Return status code
Sergunb 0:8918a71cdbe9 478 return error;
Sergunb 0:8918a71cdbe9 479 }
Sergunb 0:8918a71cdbe9 480
Sergunb 0:8918a71cdbe9 481
Sergunb 0:8918a71cdbe9 482 /**
Sergunb 0:8918a71cdbe9 483 * @brief Configure multicast MAC address filtering
Sergunb 0:8918a71cdbe9 484 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 485 * @return Error code
Sergunb 0:8918a71cdbe9 486 **/
Sergunb 0:8918a71cdbe9 487
Sergunb 0:8918a71cdbe9 488 error_t enc624j600SetMulticastFilter(NetInterface *interface)
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 uint_t i;
Sergunb 0:8918a71cdbe9 491 uint_t k;
Sergunb 0:8918a71cdbe9 492 uint32_t crc;
Sergunb 0:8918a71cdbe9 493 uint16_t hashTable[4];
Sergunb 0:8918a71cdbe9 494 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 495
Sergunb 0:8918a71cdbe9 496 //Debug message
Sergunb 0:8918a71cdbe9 497 TRACE_DEBUG("Updating ENC624J600 hash table...\r\n");
Sergunb 0:8918a71cdbe9 498
Sergunb 0:8918a71cdbe9 499 //Clear hash table
Sergunb 0:8918a71cdbe9 500 memset(hashTable, 0, sizeof(hashTable));
Sergunb 0:8918a71cdbe9 501
Sergunb 0:8918a71cdbe9 502 //The MAC filter table contains the multicast MAC addresses
Sergunb 0:8918a71cdbe9 503 //to accept when receiving an Ethernet frame
Sergunb 0:8918a71cdbe9 504 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 505 {
Sergunb 0:8918a71cdbe9 506 //Point to the current entry
Sergunb 0:8918a71cdbe9 507 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 508
Sergunb 0:8918a71cdbe9 509 //Valid entry?
Sergunb 0:8918a71cdbe9 510 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 511 {
Sergunb 0:8918a71cdbe9 512 //Compute CRC over the current MAC address
Sergunb 0:8918a71cdbe9 513 crc = enc624j600CalcCrc(&entry->addr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 514 //Calculate the corresponding index in the table
Sergunb 0:8918a71cdbe9 515 k = (crc >> 23) & 0x3F;
Sergunb 0:8918a71cdbe9 516 //Update hash table contents
Sergunb 0:8918a71cdbe9 517 hashTable[k / 16] |= (1 << (k % 16));
Sergunb 0:8918a71cdbe9 518 }
Sergunb 0:8918a71cdbe9 519 }
Sergunb 0:8918a71cdbe9 520
Sergunb 0:8918a71cdbe9 521 //Write the hash table to the ENC624J600 controller
Sergunb 0:8918a71cdbe9 522 enc624j600WriteReg(interface, ENC624J600_REG_EHT1, hashTable[0]);
Sergunb 0:8918a71cdbe9 523 enc624j600WriteReg(interface, ENC624J600_REG_EHT2, hashTable[1]);
Sergunb 0:8918a71cdbe9 524 enc624j600WriteReg(interface, ENC624J600_REG_EHT3, hashTable[2]);
Sergunb 0:8918a71cdbe9 525 enc624j600WriteReg(interface, ENC624J600_REG_EHT4, hashTable[3]);
Sergunb 0:8918a71cdbe9 526
Sergunb 0:8918a71cdbe9 527 //Debug message
Sergunb 0:8918a71cdbe9 528 TRACE_DEBUG(" EHT1 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT1));
Sergunb 0:8918a71cdbe9 529 TRACE_DEBUG(" EHT2 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT2));
Sergunb 0:8918a71cdbe9 530 TRACE_DEBUG(" EHT3 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT3));
Sergunb 0:8918a71cdbe9 531 TRACE_DEBUG(" EHT4 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT4));
Sergunb 0:8918a71cdbe9 532
Sergunb 0:8918a71cdbe9 533 //Successful processing
Sergunb 0:8918a71cdbe9 534 return NO_ERROR;
Sergunb 0:8918a71cdbe9 535 }
Sergunb 0:8918a71cdbe9 536
Sergunb 0:8918a71cdbe9 537
Sergunb 0:8918a71cdbe9 538 /**
Sergunb 0:8918a71cdbe9 539 * @brief Adjust MAC configuration parameters for proper operation
Sergunb 0:8918a71cdbe9 540 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 541 **/
Sergunb 0:8918a71cdbe9 542
Sergunb 0:8918a71cdbe9 543 void enc624j600UpdateMacConfig(NetInterface *interface)
Sergunb 0:8918a71cdbe9 544 {
Sergunb 0:8918a71cdbe9 545 uint16_t duplexMode;
Sergunb 0:8918a71cdbe9 546
Sergunb 0:8918a71cdbe9 547 //Determine the new duplex mode by reading the PHYDPX bit
Sergunb 0:8918a71cdbe9 548 duplexMode = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PHYDPX;
Sergunb 0:8918a71cdbe9 549
Sergunb 0:8918a71cdbe9 550 //Full-duplex mode?
Sergunb 0:8918a71cdbe9 551 if(duplexMode)
Sergunb 0:8918a71cdbe9 552 {
Sergunb 0:8918a71cdbe9 553 //Configure the FULDPX bit to match the current duplex mode
Sergunb 0:8918a71cdbe9 554 enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER |
Sergunb 0:8918a71cdbe9 555 MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1 | MACON2_FULDPX);
Sergunb 0:8918a71cdbe9 556 //Configure the Back-to-Back Inter-Packet Gap register
Sergunb 0:8918a71cdbe9 557 enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x15);
Sergunb 0:8918a71cdbe9 558 }
Sergunb 0:8918a71cdbe9 559 //Half-duplex mode?
Sergunb 0:8918a71cdbe9 560 else
Sergunb 0:8918a71cdbe9 561 {
Sergunb 0:8918a71cdbe9 562 //Configure the FULDPX bit to match the current duplex mode
Sergunb 0:8918a71cdbe9 563 enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER |
Sergunb 0:8918a71cdbe9 564 MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1);
Sergunb 0:8918a71cdbe9 565 //Configure the Back-to-Back Inter-Packet Gap register
Sergunb 0:8918a71cdbe9 566 enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x12);
Sergunb 0:8918a71cdbe9 567 }
Sergunb 0:8918a71cdbe9 568 }
Sergunb 0:8918a71cdbe9 569
Sergunb 0:8918a71cdbe9 570
Sergunb 0:8918a71cdbe9 571 /**
Sergunb 0:8918a71cdbe9 572 * @brief Reset ENC624J600 controller
Sergunb 0:8918a71cdbe9 573 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 574 * @return Error code
Sergunb 0:8918a71cdbe9 575 **/
Sergunb 0:8918a71cdbe9 576
Sergunb 0:8918a71cdbe9 577 error_t enc624j600SoftReset(NetInterface *interface)
Sergunb 0:8918a71cdbe9 578 {
Sergunb 0:8918a71cdbe9 579 //Wait for the SPI interface to be ready
Sergunb 0:8918a71cdbe9 580 do
Sergunb 0:8918a71cdbe9 581 {
Sergunb 0:8918a71cdbe9 582 //Write 0x1234 to EUDAST
Sergunb 0:8918a71cdbe9 583 enc624j600WriteReg(interface, ENC624J600_REG_EUDAST, 0x1234);
Sergunb 0:8918a71cdbe9 584 //Read back register and check contents
Sergunb 0:8918a71cdbe9 585 } while(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x1234);
Sergunb 0:8918a71cdbe9 586
Sergunb 0:8918a71cdbe9 587 //Poll CLKRDY and wait for it to become set
Sergunb 0:8918a71cdbe9 588 while(!(enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_CLKRDY));
Sergunb 0:8918a71cdbe9 589
Sergunb 0:8918a71cdbe9 590 //Issue a system reset command by setting ETHRST
Sergunb 0:8918a71cdbe9 591 enc624j600SetBit(interface, ENC624J600_REG_ECON2, ECON2_ETHRST);
Sergunb 0:8918a71cdbe9 592 //Wait at least 25us for the reset to take place
Sergunb 0:8918a71cdbe9 593 sleep(1);
Sergunb 0:8918a71cdbe9 594
Sergunb 0:8918a71cdbe9 595 //Read EUDAST to confirm that the system reset took place.
Sergunb 0:8918a71cdbe9 596 //EUDAST should have reverted back to its reset default
Sergunb 0:8918a71cdbe9 597 if(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x0000)
Sergunb 0:8918a71cdbe9 598 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 599
Sergunb 0:8918a71cdbe9 600 //Wait at least 256us for the PHY registers and PHY
Sergunb 0:8918a71cdbe9 601 //status bits to become available
Sergunb 0:8918a71cdbe9 602 sleep(1);
Sergunb 0:8918a71cdbe9 603
Sergunb 0:8918a71cdbe9 604 //The controller is now ready to accept further commands
Sergunb 0:8918a71cdbe9 605 return NO_ERROR;
Sergunb 0:8918a71cdbe9 606 }
Sergunb 0:8918a71cdbe9 607
Sergunb 0:8918a71cdbe9 608
Sergunb 0:8918a71cdbe9 609 /**
Sergunb 0:8918a71cdbe9 610 * @brief Write ENC624J600 register
Sergunb 0:8918a71cdbe9 611 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 612 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 613 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 614 **/
Sergunb 0:8918a71cdbe9 615
Sergunb 0:8918a71cdbe9 616 void enc624j600WriteReg(NetInterface *interface, uint8_t address, uint16_t data)
Sergunb 0:8918a71cdbe9 617 {
Sergunb 0:8918a71cdbe9 618 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 619 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 620
Sergunb 0:8918a71cdbe9 621 //Write opcode
Sergunb 0:8918a71cdbe9 622 interface->spiDriver->transfer(ENC624J600_CMD_WCRU);
Sergunb 0:8918a71cdbe9 623 //Write register address
Sergunb 0:8918a71cdbe9 624 interface->spiDriver->transfer(address);
Sergunb 0:8918a71cdbe9 625 //Write register value
Sergunb 0:8918a71cdbe9 626 interface->spiDriver->transfer(LSB(data));
Sergunb 0:8918a71cdbe9 627 interface->spiDriver->transfer(MSB(data));
Sergunb 0:8918a71cdbe9 628
Sergunb 0:8918a71cdbe9 629 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 630 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 631 }
Sergunb 0:8918a71cdbe9 632
Sergunb 0:8918a71cdbe9 633
Sergunb 0:8918a71cdbe9 634 /**
Sergunb 0:8918a71cdbe9 635 * @brief Read ENC624J600 register
Sergunb 0:8918a71cdbe9 636 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 637 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 638 * @return Register value
Sergunb 0:8918a71cdbe9 639 **/
Sergunb 0:8918a71cdbe9 640
Sergunb 0:8918a71cdbe9 641 uint16_t enc624j600ReadReg(NetInterface *interface, uint8_t address)
Sergunb 0:8918a71cdbe9 642 {
Sergunb 0:8918a71cdbe9 643 uint16_t data;
Sergunb 0:8918a71cdbe9 644
Sergunb 0:8918a71cdbe9 645 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 646 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 647
Sergunb 0:8918a71cdbe9 648 //Write opcode
Sergunb 0:8918a71cdbe9 649 interface->spiDriver->transfer(ENC624J600_CMD_RCRU);
Sergunb 0:8918a71cdbe9 650 //Write register address
Sergunb 0:8918a71cdbe9 651 interface->spiDriver->transfer(address);
Sergunb 0:8918a71cdbe9 652 //Read the lower 8 bits of data
Sergunb 0:8918a71cdbe9 653 data = interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 654 //Read the upper 8 bits of data
Sergunb 0:8918a71cdbe9 655 data |= interface->spiDriver->transfer(0x00) << 8;
Sergunb 0:8918a71cdbe9 656
Sergunb 0:8918a71cdbe9 657 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 658 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 659
Sergunb 0:8918a71cdbe9 660 //Return register contents
Sergunb 0:8918a71cdbe9 661 return data;
Sergunb 0:8918a71cdbe9 662 }
Sergunb 0:8918a71cdbe9 663
Sergunb 0:8918a71cdbe9 664
Sergunb 0:8918a71cdbe9 665 /**
Sergunb 0:8918a71cdbe9 666 * @brief Write PHY register
Sergunb 0:8918a71cdbe9 667 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 668 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 669 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 670 **/
Sergunb 0:8918a71cdbe9 671
Sergunb 0:8918a71cdbe9 672 void enc624j600WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
Sergunb 0:8918a71cdbe9 673 {
Sergunb 0:8918a71cdbe9 674 //Write the address of the PHY register to write to
Sergunb 0:8918a71cdbe9 675 enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address);
Sergunb 0:8918a71cdbe9 676 //Write the 16 bits of data into the MIWR register
Sergunb 0:8918a71cdbe9 677 enc624j600WriteReg(interface, ENC624J600_REG_MIWR, data);
Sergunb 0:8918a71cdbe9 678
Sergunb 0:8918a71cdbe9 679 //Wait until the PHY register has been written
Sergunb 0:8918a71cdbe9 680 while(enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY);
Sergunb 0:8918a71cdbe9 681 }
Sergunb 0:8918a71cdbe9 682
Sergunb 0:8918a71cdbe9 683
Sergunb 0:8918a71cdbe9 684 /**
Sergunb 0:8918a71cdbe9 685 * @brief Read PHY register
Sergunb 0:8918a71cdbe9 686 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 687 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 688 * @return Register value
Sergunb 0:8918a71cdbe9 689 **/
Sergunb 0:8918a71cdbe9 690
Sergunb 0:8918a71cdbe9 691 uint16_t enc624j600ReadPhyReg(NetInterface *interface, uint8_t address)
Sergunb 0:8918a71cdbe9 692 {
Sergunb 0:8918a71cdbe9 693 //Write the address of the PHY register to read from
Sergunb 0:8918a71cdbe9 694 enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address);
Sergunb 0:8918a71cdbe9 695 //Start read operation
Sergunb 0:8918a71cdbe9 696 enc624j600WriteReg(interface, ENC624J600_REG_MICMD, MICMD_MIIRD);
Sergunb 0:8918a71cdbe9 697
Sergunb 0:8918a71cdbe9 698 //Wait at least 25.6us before polling the BUSY bit
Sergunb 0:8918a71cdbe9 699 usleep(100);
Sergunb 0:8918a71cdbe9 700 //Wait for the read operation to complete
Sergunb 0:8918a71cdbe9 701 while(enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY);
Sergunb 0:8918a71cdbe9 702
Sergunb 0:8918a71cdbe9 703 //Clear command register
Sergunb 0:8918a71cdbe9 704 enc624j600WriteReg(interface, ENC624J600_REG_MICMD, 0x00);
Sergunb 0:8918a71cdbe9 705
Sergunb 0:8918a71cdbe9 706 //Return register contents
Sergunb 0:8918a71cdbe9 707 return enc624j600ReadReg(interface, ENC624J600_REG_MIRD);
Sergunb 0:8918a71cdbe9 708 }
Sergunb 0:8918a71cdbe9 709
Sergunb 0:8918a71cdbe9 710
Sergunb 0:8918a71cdbe9 711 /**
Sergunb 0:8918a71cdbe9 712 * @brief Write SRAM buffer
Sergunb 0:8918a71cdbe9 713 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 714 * @param[in] opcode SRAM buffer operation
Sergunb 0:8918a71cdbe9 715 * @param[in] buffer Multi-part buffer containing the data to be written
Sergunb 0:8918a71cdbe9 716 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 717 **/
Sergunb 0:8918a71cdbe9 718
Sergunb 0:8918a71cdbe9 719 void enc624j600WriteBuffer(NetInterface *interface,
Sergunb 0:8918a71cdbe9 720 uint8_t opcode, const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 721 {
Sergunb 0:8918a71cdbe9 722 uint_t i;
Sergunb 0:8918a71cdbe9 723 size_t j;
Sergunb 0:8918a71cdbe9 724 size_t n;
Sergunb 0:8918a71cdbe9 725 uint8_t *p;
Sergunb 0:8918a71cdbe9 726
Sergunb 0:8918a71cdbe9 727 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 728 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 729
Sergunb 0:8918a71cdbe9 730 //Write opcode
Sergunb 0:8918a71cdbe9 731 interface->spiDriver->transfer(opcode);
Sergunb 0:8918a71cdbe9 732
Sergunb 0:8918a71cdbe9 733 //Loop through data chunks
Sergunb 0:8918a71cdbe9 734 for(i = 0; i < buffer->chunkCount; i++)
Sergunb 0:8918a71cdbe9 735 {
Sergunb 0:8918a71cdbe9 736 //Is there any data to copy from the current chunk?
Sergunb 0:8918a71cdbe9 737 if(offset < buffer->chunk[i].length)
Sergunb 0:8918a71cdbe9 738 {
Sergunb 0:8918a71cdbe9 739 //Point to the first byte to be read
Sergunb 0:8918a71cdbe9 740 p = (uint8_t *) buffer->chunk[i].address + offset;
Sergunb 0:8918a71cdbe9 741 //Compute the number of bytes to copy at a time
Sergunb 0:8918a71cdbe9 742 n = buffer->chunk[i].length - offset;
Sergunb 0:8918a71cdbe9 743
Sergunb 0:8918a71cdbe9 744 //Copy data to SRAM buffer
Sergunb 0:8918a71cdbe9 745 for(j = 0; j < n; j++)
Sergunb 0:8918a71cdbe9 746 interface->spiDriver->transfer(p[j]);
Sergunb 0:8918a71cdbe9 747
Sergunb 0:8918a71cdbe9 748 //Process the next block from the start
Sergunb 0:8918a71cdbe9 749 offset = 0;
Sergunb 0:8918a71cdbe9 750 }
Sergunb 0:8918a71cdbe9 751 else
Sergunb 0:8918a71cdbe9 752 {
Sergunb 0:8918a71cdbe9 753 //Skip the current chunk
Sergunb 0:8918a71cdbe9 754 offset -= buffer->chunk[i].length;
Sergunb 0:8918a71cdbe9 755 }
Sergunb 0:8918a71cdbe9 756 }
Sergunb 0:8918a71cdbe9 757
Sergunb 0:8918a71cdbe9 758 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 759 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 760 }
Sergunb 0:8918a71cdbe9 761
Sergunb 0:8918a71cdbe9 762
Sergunb 0:8918a71cdbe9 763 /**
Sergunb 0:8918a71cdbe9 764 * @brief Read SRAM buffer
Sergunb 0:8918a71cdbe9 765 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 766 * @param[in] opcode SRAM buffer operation
Sergunb 0:8918a71cdbe9 767 * @param[in] data Buffer where to store the incoming data
Sergunb 0:8918a71cdbe9 768 * @param[in] length Number of data to read
Sergunb 0:8918a71cdbe9 769 **/
Sergunb 0:8918a71cdbe9 770
Sergunb 0:8918a71cdbe9 771 void enc624j600ReadBuffer(NetInterface *interface,
Sergunb 0:8918a71cdbe9 772 uint8_t opcode, uint8_t *data, size_t length)
Sergunb 0:8918a71cdbe9 773 {
Sergunb 0:8918a71cdbe9 774 size_t i;
Sergunb 0:8918a71cdbe9 775
Sergunb 0:8918a71cdbe9 776 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 777 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 778
Sergunb 0:8918a71cdbe9 779 //Write opcode
Sergunb 0:8918a71cdbe9 780 interface->spiDriver->transfer(opcode);
Sergunb 0:8918a71cdbe9 781
Sergunb 0:8918a71cdbe9 782 //Copy data from SRAM buffer
Sergunb 0:8918a71cdbe9 783 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 784 data[i] = interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 785
Sergunb 0:8918a71cdbe9 786 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 787 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 788 }
Sergunb 0:8918a71cdbe9 789
Sergunb 0:8918a71cdbe9 790
Sergunb 0:8918a71cdbe9 791 /**
Sergunb 0:8918a71cdbe9 792 * @brief Set bit field
Sergunb 0:8918a71cdbe9 793 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 794 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 795 * @param[in] mask Bits to set in the target register
Sergunb 0:8918a71cdbe9 796 **/
Sergunb 0:8918a71cdbe9 797
Sergunb 0:8918a71cdbe9 798 void enc624j600SetBit(NetInterface *interface, uint8_t address, uint16_t mask)
Sergunb 0:8918a71cdbe9 799 {
Sergunb 0:8918a71cdbe9 800 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 801 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 802
Sergunb 0:8918a71cdbe9 803 //Write opcode
Sergunb 0:8918a71cdbe9 804 interface->spiDriver->transfer(ENC624J600_CMD_BFSU);
Sergunb 0:8918a71cdbe9 805 //Write register address
Sergunb 0:8918a71cdbe9 806 interface->spiDriver->transfer(address);
Sergunb 0:8918a71cdbe9 807 //Write bit mask
Sergunb 0:8918a71cdbe9 808 interface->spiDriver->transfer(LSB(mask));
Sergunb 0:8918a71cdbe9 809 interface->spiDriver->transfer(MSB(mask));
Sergunb 0:8918a71cdbe9 810
Sergunb 0:8918a71cdbe9 811 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 812 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 813 }
Sergunb 0:8918a71cdbe9 814
Sergunb 0:8918a71cdbe9 815
Sergunb 0:8918a71cdbe9 816 /**
Sergunb 0:8918a71cdbe9 817 * @brief Clear bit field
Sergunb 0:8918a71cdbe9 818 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 819 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 820 * @param[in] mask Bits to clear in the target register
Sergunb 0:8918a71cdbe9 821 **/
Sergunb 0:8918a71cdbe9 822
Sergunb 0:8918a71cdbe9 823 void enc624j600ClearBit(NetInterface *interface, uint8_t address, uint16_t mask)
Sergunb 0:8918a71cdbe9 824 {
Sergunb 0:8918a71cdbe9 825 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 826 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 827
Sergunb 0:8918a71cdbe9 828 //Write opcode
Sergunb 0:8918a71cdbe9 829 interface->spiDriver->transfer(ENC624J600_CMD_BFCU);
Sergunb 0:8918a71cdbe9 830 //Write register address
Sergunb 0:8918a71cdbe9 831 interface->spiDriver->transfer(address);
Sergunb 0:8918a71cdbe9 832 //Write bit mask
Sergunb 0:8918a71cdbe9 833 interface->spiDriver->transfer(LSB(mask));
Sergunb 0:8918a71cdbe9 834 interface->spiDriver->transfer(MSB(mask));
Sergunb 0:8918a71cdbe9 835
Sergunb 0:8918a71cdbe9 836 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 837 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 838 }
Sergunb 0:8918a71cdbe9 839
Sergunb 0:8918a71cdbe9 840
Sergunb 0:8918a71cdbe9 841 /**
Sergunb 0:8918a71cdbe9 842 * @brief CRC calculation using the polynomial 0x4C11DB7
Sergunb 0:8918a71cdbe9 843 * @param[in] data Pointer to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 844 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 845 * @return Resulting CRC value
Sergunb 0:8918a71cdbe9 846 **/
Sergunb 0:8918a71cdbe9 847
Sergunb 0:8918a71cdbe9 848 uint32_t enc624j600CalcCrc(const void *data, size_t length)
Sergunb 0:8918a71cdbe9 849 {
Sergunb 0:8918a71cdbe9 850 uint_t i;
Sergunb 0:8918a71cdbe9 851 uint_t j;
Sergunb 0:8918a71cdbe9 852
Sergunb 0:8918a71cdbe9 853 //Point to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 854 const uint8_t *p = (uint8_t *) data;
Sergunb 0:8918a71cdbe9 855 //CRC preset value
Sergunb 0:8918a71cdbe9 856 uint32_t crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 857
Sergunb 0:8918a71cdbe9 858 //Loop through data
Sergunb 0:8918a71cdbe9 859 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 860 {
Sergunb 0:8918a71cdbe9 861 //The message is processed bit by bit
Sergunb 0:8918a71cdbe9 862 for(j = 0; j < 8; j++)
Sergunb 0:8918a71cdbe9 863 {
Sergunb 0:8918a71cdbe9 864 //Update CRC value
Sergunb 0:8918a71cdbe9 865 if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
Sergunb 0:8918a71cdbe9 866 crc = (crc << 1) ^ 0x04C11DB7;
Sergunb 0:8918a71cdbe9 867 else
Sergunb 0:8918a71cdbe9 868 crc = crc << 1;
Sergunb 0:8918a71cdbe9 869 }
Sergunb 0:8918a71cdbe9 870 }
Sergunb 0:8918a71cdbe9 871
Sergunb 0:8918a71cdbe9 872 //Return CRC value
Sergunb 0:8918a71cdbe9 873 return crc;
Sergunb 0:8918a71cdbe9 874 }
Sergunb 0:8918a71cdbe9 875
Sergunb 0:8918a71cdbe9 876
Sergunb 0:8918a71cdbe9 877 /**
Sergunb 0:8918a71cdbe9 878 * @brief Dump registers for debugging purpose
Sergunb 0:8918a71cdbe9 879 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 880 **/
Sergunb 0:8918a71cdbe9 881
Sergunb 0:8918a71cdbe9 882 void enc624j600DumpReg(NetInterface *interface)
Sergunb 0:8918a71cdbe9 883 {
Sergunb 0:8918a71cdbe9 884 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
Sergunb 0:8918a71cdbe9 885 uint8_t i;
Sergunb 0:8918a71cdbe9 886 uint8_t bank;
Sergunb 0:8918a71cdbe9 887 uint16_t address;
Sergunb 0:8918a71cdbe9 888
Sergunb 0:8918a71cdbe9 889 //Display header
Sergunb 0:8918a71cdbe9 890 TRACE_DEBUG(" Bank 0 Bank 1 Bank 2 Bank 3 Unbanked\r\n");
Sergunb 0:8918a71cdbe9 891
Sergunb 0:8918a71cdbe9 892 //Loop through register addresses
Sergunb 0:8918a71cdbe9 893 for(i = 0; i < 32; i += 2)
Sergunb 0:8918a71cdbe9 894 {
Sergunb 0:8918a71cdbe9 895 //Display register address
Sergunb 0:8918a71cdbe9 896 TRACE_DEBUG("%02" PRIX8 ": ", i);
Sergunb 0:8918a71cdbe9 897
Sergunb 0:8918a71cdbe9 898 //Loop through bank numbers
Sergunb 0:8918a71cdbe9 899 for(bank = 0; bank < 5; bank++)
Sergunb 0:8918a71cdbe9 900 {
Sergunb 0:8918a71cdbe9 901 //Format register address
Sergunb 0:8918a71cdbe9 902 address = 0x7E00 | (bank << 5) | i;
Sergunb 0:8918a71cdbe9 903 //Display register contents
Sergunb 0:8918a71cdbe9 904 TRACE_DEBUG("0x%04" PRIX16 " ", enc624j600ReadReg(interface, address));
Sergunb 0:8918a71cdbe9 905 }
Sergunb 0:8918a71cdbe9 906
Sergunb 0:8918a71cdbe9 907 //Jump to the following line
Sergunb 0:8918a71cdbe9 908 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 909 }
Sergunb 0:8918a71cdbe9 910
Sergunb 0:8918a71cdbe9 911 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 912 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 913 #endif
Sergunb 0:8918a71cdbe9 914 }
Sergunb 0:8918a71cdbe9 915
Sergunb 0:8918a71cdbe9 916
Sergunb 0:8918a71cdbe9 917 /**
Sergunb 0:8918a71cdbe9 918 * @brief Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 919 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 920 **/
Sergunb 0:8918a71cdbe9 921
Sergunb 0:8918a71cdbe9 922 void enc624j600DumpPhyReg(NetInterface *interface)
Sergunb 0:8918a71cdbe9 923 {
Sergunb 0:8918a71cdbe9 924 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
Sergunb 0:8918a71cdbe9 925 uint8_t i;
Sergunb 0:8918a71cdbe9 926
Sergunb 0:8918a71cdbe9 927 //Loop through PHY registers
Sergunb 0:8918a71cdbe9 928 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 929 {
Sergunb 0:8918a71cdbe9 930 //Display current PHY register
Sergunb 0:8918a71cdbe9 931 TRACE_DEBUG("%02" PRIX8 ": 0x%04" PRIX16 "\r\n", i, enc624j600ReadPhyReg(interface, i));
Sergunb 0:8918a71cdbe9 932 }
Sergunb 0:8918a71cdbe9 933
Sergunb 0:8918a71cdbe9 934 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 935 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 936 #endif
Sergunb 0:8918a71cdbe9 937 }
Sergunb 0:8918a71cdbe9 938