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 enc28j60.c
Sergunb 0:8918a71cdbe9 3 * @brief ENC28J60 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 <limits.h>
Sergunb 0:8918a71cdbe9 34 #include "core/net.h"
Sergunb 0:8918a71cdbe9 35 #include "drivers/enc28j60.h"
Sergunb 0:8918a71cdbe9 36 #include "debug.h"
Sergunb 0:8918a71cdbe9 37
Sergunb 0:8918a71cdbe9 38
Sergunb 0:8918a71cdbe9 39 /**
Sergunb 0:8918a71cdbe9 40 * @brief ENC28J60 driver
Sergunb 0:8918a71cdbe9 41 **/
Sergunb 0:8918a71cdbe9 42
Sergunb 0:8918a71cdbe9 43 const NicDriver enc28j60Driver =
Sergunb 0:8918a71cdbe9 44 {
Sergunb 0:8918a71cdbe9 45 NIC_TYPE_ETHERNET,
Sergunb 0:8918a71cdbe9 46 ETH_MTU,
Sergunb 0:8918a71cdbe9 47 enc28j60Init,
Sergunb 0:8918a71cdbe9 48 enc28j60Tick,
Sergunb 0:8918a71cdbe9 49 enc28j60EnableIrq,
Sergunb 0:8918a71cdbe9 50 enc28j60DisableIrq,
Sergunb 0:8918a71cdbe9 51 enc28j60EventHandler,
Sergunb 0:8918a71cdbe9 52 enc28j60SendPacket,
Sergunb 0:8918a71cdbe9 53 enc28j60SetMulticastFilter,
Sergunb 0:8918a71cdbe9 54 NULL,
Sergunb 0:8918a71cdbe9 55 NULL,
Sergunb 0:8918a71cdbe9 56 NULL,
Sergunb 0:8918a71cdbe9 57 TRUE,
Sergunb 0:8918a71cdbe9 58 TRUE,
Sergunb 0:8918a71cdbe9 59 TRUE,
Sergunb 0:8918a71cdbe9 60 FALSE
Sergunb 0:8918a71cdbe9 61 };
Sergunb 0:8918a71cdbe9 62
Sergunb 0:8918a71cdbe9 63
Sergunb 0:8918a71cdbe9 64 /**
Sergunb 0:8918a71cdbe9 65 * @brief ENC28J60 controller initialization
Sergunb 0:8918a71cdbe9 66 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 67 * @return Error code
Sergunb 0:8918a71cdbe9 68 **/
Sergunb 0:8918a71cdbe9 69
Sergunb 0:8918a71cdbe9 70 error_t enc28j60Init(NetInterface *interface)
Sergunb 0:8918a71cdbe9 71 {
Sergunb 0:8918a71cdbe9 72 uint8_t revisionId;
Sergunb 0:8918a71cdbe9 73 Enc28j60Context *context;
Sergunb 0:8918a71cdbe9 74
Sergunb 0:8918a71cdbe9 75 //Debug message
Sergunb 0:8918a71cdbe9 76 TRACE_INFO("Initializing ENC28J60 Ethernet controller...\r\n");
Sergunb 0:8918a71cdbe9 77
Sergunb 0:8918a71cdbe9 78 //Initialize SPI
Sergunb 0:8918a71cdbe9 79 interface->spiDriver->init();
Sergunb 0:8918a71cdbe9 80 //Initialize external interrupt line
Sergunb 0:8918a71cdbe9 81 interface->extIntDriver->init();
Sergunb 0:8918a71cdbe9 82
Sergunb 0:8918a71cdbe9 83 //Issue a system reset
Sergunb 0:8918a71cdbe9 84 enc28j60SoftReset(interface);
Sergunb 0:8918a71cdbe9 85
Sergunb 0:8918a71cdbe9 86 //After issuing the reset command, wait at least 1ms in firmware
Sergunb 0:8918a71cdbe9 87 //for the device to be ready
Sergunb 0:8918a71cdbe9 88 sleep(10);
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90 //Point to the driver context
Sergunb 0:8918a71cdbe9 91 context = (Enc28j60Context *) interface->nicContext;
Sergunb 0:8918a71cdbe9 92
Sergunb 0:8918a71cdbe9 93 //Initialize driver specific variables
Sergunb 0:8918a71cdbe9 94 context->currentBank = UINT16_MAX;
Sergunb 0:8918a71cdbe9 95 context->nextPacket = ENC28J60_RX_BUFFER_START;
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 //Allocate RX buffer
Sergunb 0:8918a71cdbe9 98 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE);
Sergunb 0:8918a71cdbe9 99 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 100 if(context->rxBuffer == NULL)
Sergunb 0:8918a71cdbe9 101 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 102
Sergunb 0:8918a71cdbe9 103 //Read silicon revision ID
Sergunb 0:8918a71cdbe9 104 revisionId = enc28j60ReadReg(interface, ENC28J60_REG_EREVID);
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //Debug message
Sergunb 0:8918a71cdbe9 107 TRACE_INFO("ENC28J60 revision ID: 0x%02X\r\n", revisionId);
Sergunb 0:8918a71cdbe9 108
Sergunb 0:8918a71cdbe9 109 //Disable CLKOUT output
Sergunb 0:8918a71cdbe9 110 enc28j60WriteReg(interface, ENC28J60_REG_ECOCON, 0x00);
Sergunb 0:8918a71cdbe9 111
Sergunb 0:8918a71cdbe9 112 //Set the MAC address
Sergunb 0:8918a71cdbe9 113 enc28j60WriteReg(interface, ENC28J60_REG_MAADR1, interface->macAddr.b[0]);
Sergunb 0:8918a71cdbe9 114 enc28j60WriteReg(interface, ENC28J60_REG_MAADR2, interface->macAddr.b[1]);
Sergunb 0:8918a71cdbe9 115 enc28j60WriteReg(interface, ENC28J60_REG_MAADR3, interface->macAddr.b[2]);
Sergunb 0:8918a71cdbe9 116 enc28j60WriteReg(interface, ENC28J60_REG_MAADR4, interface->macAddr.b[3]);
Sergunb 0:8918a71cdbe9 117 enc28j60WriteReg(interface, ENC28J60_REG_MAADR5, interface->macAddr.b[4]);
Sergunb 0:8918a71cdbe9 118 enc28j60WriteReg(interface, ENC28J60_REG_MAADR6, interface->macAddr.b[5]);
Sergunb 0:8918a71cdbe9 119
Sergunb 0:8918a71cdbe9 120 //Set receive buffer location
Sergunb 0:8918a71cdbe9 121 enc28j60WriteReg(interface, ENC28J60_REG_ERXSTL, LSB(ENC28J60_RX_BUFFER_START));
Sergunb 0:8918a71cdbe9 122 enc28j60WriteReg(interface, ENC28J60_REG_ERXSTH, MSB(ENC28J60_RX_BUFFER_START));
Sergunb 0:8918a71cdbe9 123 enc28j60WriteReg(interface, ENC28J60_REG_ERXNDL, LSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 124 enc28j60WriteReg(interface, ENC28J60_REG_ERXNDH, MSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 125
Sergunb 0:8918a71cdbe9 126 //The ERXRDPT register defines a location within the FIFO
Sergunb 0:8918a71cdbe9 127 //where the receive hardware is forbidden to write to
Sergunb 0:8918a71cdbe9 128 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 129 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 130
Sergunb 0:8918a71cdbe9 131 //Configure the receive filters
Sergunb 0:8918a71cdbe9 132 enc28j60WriteReg(interface, ENC28J60_REG_ERXFCON, ERXFCON_UCEN |
Sergunb 0:8918a71cdbe9 133 ERXFCON_CRCEN | ERXFCON_HTEN | ERXFCON_BCEN);
Sergunb 0:8918a71cdbe9 134
Sergunb 0:8918a71cdbe9 135 //Initialize the hash table
Sergunb 0:8918a71cdbe9 136 enc28j60WriteReg(interface, ENC28J60_REG_EHT0, 0x00);
Sergunb 0:8918a71cdbe9 137 enc28j60WriteReg(interface, ENC28J60_REG_EHT1, 0x00);
Sergunb 0:8918a71cdbe9 138 enc28j60WriteReg(interface, ENC28J60_REG_EHT2, 0x00);
Sergunb 0:8918a71cdbe9 139 enc28j60WriteReg(interface, ENC28J60_REG_EHT3, 0x00);
Sergunb 0:8918a71cdbe9 140 enc28j60WriteReg(interface, ENC28J60_REG_EHT4, 0x00);
Sergunb 0:8918a71cdbe9 141 enc28j60WriteReg(interface, ENC28J60_REG_EHT5, 0x00);
Sergunb 0:8918a71cdbe9 142 enc28j60WriteReg(interface, ENC28J60_REG_EHT6, 0x00);
Sergunb 0:8918a71cdbe9 143 enc28j60WriteReg(interface, ENC28J60_REG_EHT7, 0x00);
Sergunb 0:8918a71cdbe9 144
Sergunb 0:8918a71cdbe9 145 //Pull the MAC out of reset
Sergunb 0:8918a71cdbe9 146 enc28j60WriteReg(interface, ENC28J60_REG_MACON2, 0x00);
Sergunb 0:8918a71cdbe9 147
Sergunb 0:8918a71cdbe9 148 //Enable the MAC to receive frames
Sergunb 0:8918a71cdbe9 149 enc28j60WriteReg(interface, ENC28J60_REG_MACON1,
Sergunb 0:8918a71cdbe9 150 MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN);
Sergunb 0:8918a71cdbe9 151
Sergunb 0:8918a71cdbe9 152 //Enable automatic padding to at least 60 bytes, always append a valid CRC
Sergunb 0:8918a71cdbe9 153 //and check frame length. MAC can operate in half-duplex or full-duplex mode
Sergunb 0:8918a71cdbe9 154 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 155 enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) |
Sergunb 0:8918a71cdbe9 156 MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
Sergunb 0:8918a71cdbe9 157 #else
Sergunb 0:8918a71cdbe9 158 enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) |
Sergunb 0:8918a71cdbe9 159 MACON3_TXCRCEN | MACON3_FRMLNEN);
Sergunb 0:8918a71cdbe9 160 #endif
Sergunb 0:8918a71cdbe9 161
Sergunb 0:8918a71cdbe9 162 //When the medium is occupied, the MAC will wait indefinitely for it to
Sergunb 0:8918a71cdbe9 163 //become free when attempting to transmit
Sergunb 0:8918a71cdbe9 164 enc28j60WriteReg(interface, ENC28J60_REG_MACON4, MACON4_DEFER);
Sergunb 0:8918a71cdbe9 165
Sergunb 0:8918a71cdbe9 166 //Maximum frame length that can be received or transmitted (1518 bytes)
Sergunb 0:8918a71cdbe9 167 enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLL, LSB(1518));
Sergunb 0:8918a71cdbe9 168 enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLH, MSB(1518));
Sergunb 0:8918a71cdbe9 169
Sergunb 0:8918a71cdbe9 170 //Configure the back-to-back inter-packet gap register
Sergunb 0:8918a71cdbe9 171 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 172 enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x15);
Sergunb 0:8918a71cdbe9 173 #else
Sergunb 0:8918a71cdbe9 174 enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x12);
Sergunb 0:8918a71cdbe9 175 #endif
Sergunb 0:8918a71cdbe9 176
Sergunb 0:8918a71cdbe9 177 //Configure the non-back-to-back inter-packet gap register
Sergunb 0:8918a71cdbe9 178 enc28j60WriteReg(interface, ENC28J60_REG_MAIPGL, 0x12);
Sergunb 0:8918a71cdbe9 179 enc28j60WriteReg(interface, ENC28J60_REG_MAIPGH, 0x0C);
Sergunb 0:8918a71cdbe9 180
Sergunb 0:8918a71cdbe9 181 //Collision window register
Sergunb 0:8918a71cdbe9 182 enc28j60WriteReg(interface, ENC28J60_REG_MACLCON2, 63);
Sergunb 0:8918a71cdbe9 183
Sergunb 0:8918a71cdbe9 184 //Set the PHY to the proper duplex mode
Sergunb 0:8918a71cdbe9 185 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 186 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, PHCON1_PDPXMD);
Sergunb 0:8918a71cdbe9 187 #else
Sergunb 0:8918a71cdbe9 188 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, 0x0000);
Sergunb 0:8918a71cdbe9 189 #endif
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191 //Disable half-duplex loopback in PHY
Sergunb 0:8918a71cdbe9 192 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON2, PHCON2_HDLDIS);
Sergunb 0:8918a71cdbe9 193
Sergunb 0:8918a71cdbe9 194 //LEDA displays link status and LEDB displays TX/RX activity
Sergunb 0:8918a71cdbe9 195 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHLCON,
Sergunb 0:8918a71cdbe9 196 PHLCON_LACFG(4) | PHLCON_LBCFG(7) | PHLCON_LFRQ(0) | PHLCON_STRCH);
Sergunb 0:8918a71cdbe9 197
Sergunb 0:8918a71cdbe9 198 //Clear interrupt flags
Sergunb 0:8918a71cdbe9 199 enc28j60WriteReg(interface, ENC28J60_REG_EIR, 0x00);
Sergunb 0:8918a71cdbe9 200
Sergunb 0:8918a71cdbe9 201 //Configure interrupts as desired
Sergunb 0:8918a71cdbe9 202 enc28j60WriteReg(interface, ENC28J60_REG_EIE, EIE_INTIE |
Sergunb 0:8918a71cdbe9 203 EIE_PKTIE | EIE_LINKIE | EIE_TXIE | EIE_TXERIE);
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 //Configure PHY interrupts as desired
Sergunb 0:8918a71cdbe9 206 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHIE,
Sergunb 0:8918a71cdbe9 207 PHIE_PLNKIE | PHIE_PGEIE);
Sergunb 0:8918a71cdbe9 208
Sergunb 0:8918a71cdbe9 209 //Set RXEN to enable reception
Sergunb 0:8918a71cdbe9 210 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_RXEN);
Sergunb 0:8918a71cdbe9 211
Sergunb 0:8918a71cdbe9 212 //Dump registers for debugging purpose
Sergunb 0:8918a71cdbe9 213 enc28j60DumpReg(interface);
Sergunb 0:8918a71cdbe9 214 enc28j60DumpPhyReg(interface);
Sergunb 0:8918a71cdbe9 215
Sergunb 0:8918a71cdbe9 216 //Accept any packets from the upper layer
Sergunb 0:8918a71cdbe9 217 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 218
Sergunb 0:8918a71cdbe9 219 //Force the TCP/IP stack to poll the link state at startup
Sergunb 0:8918a71cdbe9 220 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 221 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 222 osSetEvent(&netEvent);
Sergunb 0:8918a71cdbe9 223
Sergunb 0:8918a71cdbe9 224 //Successful initialization
Sergunb 0:8918a71cdbe9 225 return NO_ERROR;
Sergunb 0:8918a71cdbe9 226 }
Sergunb 0:8918a71cdbe9 227
Sergunb 0:8918a71cdbe9 228
Sergunb 0:8918a71cdbe9 229 /**
Sergunb 0:8918a71cdbe9 230 * @brief ENC28J60 timer handler
Sergunb 0:8918a71cdbe9 231 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 232 **/
Sergunb 0:8918a71cdbe9 233
Sergunb 0:8918a71cdbe9 234 void enc28j60Tick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 235 {
Sergunb 0:8918a71cdbe9 236 }
Sergunb 0:8918a71cdbe9 237
Sergunb 0:8918a71cdbe9 238
Sergunb 0:8918a71cdbe9 239 /**
Sergunb 0:8918a71cdbe9 240 * @brief Enable interrupts
Sergunb 0:8918a71cdbe9 241 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 242 **/
Sergunb 0:8918a71cdbe9 243
Sergunb 0:8918a71cdbe9 244 void enc28j60EnableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 245 {
Sergunb 0:8918a71cdbe9 246 //Enable interrupts
Sergunb 0:8918a71cdbe9 247 interface->extIntDriver->enableIrq();
Sergunb 0:8918a71cdbe9 248 }
Sergunb 0:8918a71cdbe9 249
Sergunb 0:8918a71cdbe9 250
Sergunb 0:8918a71cdbe9 251 /**
Sergunb 0:8918a71cdbe9 252 * @brief Disable interrupts
Sergunb 0:8918a71cdbe9 253 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 254 **/
Sergunb 0:8918a71cdbe9 255
Sergunb 0:8918a71cdbe9 256 void enc28j60DisableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 257 {
Sergunb 0:8918a71cdbe9 258 //Disable interrupts
Sergunb 0:8918a71cdbe9 259 interface->extIntDriver->disableIrq();
Sergunb 0:8918a71cdbe9 260 }
Sergunb 0:8918a71cdbe9 261
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263 /**
Sergunb 0:8918a71cdbe9 264 * @brief ENC28J60 interrupt service routine
Sergunb 0:8918a71cdbe9 265 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 266 * @return TRUE if a higher priority task must be woken. Else FALSE is returned
Sergunb 0:8918a71cdbe9 267 **/
Sergunb 0:8918a71cdbe9 268
Sergunb 0:8918a71cdbe9 269 bool_t enc28j60IrqHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 270 {
Sergunb 0:8918a71cdbe9 271 bool_t flag;
Sergunb 0:8918a71cdbe9 272 uint8_t status;
Sergunb 0:8918a71cdbe9 273
Sergunb 0:8918a71cdbe9 274 //This flag will be set if a higher priority task must be woken
Sergunb 0:8918a71cdbe9 275 flag = FALSE;
Sergunb 0:8918a71cdbe9 276
Sergunb 0:8918a71cdbe9 277 //Clear the INTIE bit, immediately after an interrupt event
Sergunb 0:8918a71cdbe9 278 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_INTIE);
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 //Read interrupt status register
Sergunb 0:8918a71cdbe9 281 status = enc28j60ReadReg(interface, ENC28J60_REG_EIR);
Sergunb 0:8918a71cdbe9 282
Sergunb 0:8918a71cdbe9 283 //Link status change?
Sergunb 0:8918a71cdbe9 284 if(status & EIR_LINKIF)
Sergunb 0:8918a71cdbe9 285 {
Sergunb 0:8918a71cdbe9 286 //Disable LINKIE interrupt
Sergunb 0:8918a71cdbe9 287 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_LINKIE);
Sergunb 0:8918a71cdbe9 288
Sergunb 0:8918a71cdbe9 289 //Set event flag
Sergunb 0:8918a71cdbe9 290 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 291 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 292 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 293 }
Sergunb 0:8918a71cdbe9 294
Sergunb 0:8918a71cdbe9 295 //Packet received?
Sergunb 0:8918a71cdbe9 296 if(status & EIR_PKTIF)
Sergunb 0:8918a71cdbe9 297 {
Sergunb 0:8918a71cdbe9 298 //Disable PKTIE interrupt
Sergunb 0:8918a71cdbe9 299 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_PKTIE);
Sergunb 0:8918a71cdbe9 300
Sergunb 0:8918a71cdbe9 301 //Set event flag
Sergunb 0:8918a71cdbe9 302 interface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 303 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 304 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 305 }
Sergunb 0:8918a71cdbe9 306
Sergunb 0:8918a71cdbe9 307 //Packet transmission complete?
Sergunb 0:8918a71cdbe9 308 if(status & (EIR_TXIF | EIE_TXERIE))
Sergunb 0:8918a71cdbe9 309 {
Sergunb 0:8918a71cdbe9 310 //Clear interrupt flags
Sergunb 0:8918a71cdbe9 311 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIE_TXERIE);
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 //Notify the TCP/IP stack that the transmitter is ready to send
Sergunb 0:8918a71cdbe9 314 flag |= osSetEventFromIsr(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 315 }
Sergunb 0:8918a71cdbe9 316
Sergunb 0:8918a71cdbe9 317 //Once the interrupt has been serviced, the INTIE bit
Sergunb 0:8918a71cdbe9 318 //is set again to re-enable interrupts
Sergunb 0:8918a71cdbe9 319 enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_INTIE);
Sergunb 0:8918a71cdbe9 320
Sergunb 0:8918a71cdbe9 321 //A higher priority task must be woken?
Sergunb 0:8918a71cdbe9 322 return flag;
Sergunb 0:8918a71cdbe9 323 }
Sergunb 0:8918a71cdbe9 324
Sergunb 0:8918a71cdbe9 325
Sergunb 0:8918a71cdbe9 326 /**
Sergunb 0:8918a71cdbe9 327 * @brief ENC28J60 event handler
Sergunb 0:8918a71cdbe9 328 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 329 **/
Sergunb 0:8918a71cdbe9 330
Sergunb 0:8918a71cdbe9 331 void enc28j60EventHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 332 {
Sergunb 0:8918a71cdbe9 333 error_t error;
Sergunb 0:8918a71cdbe9 334 uint16_t status;
Sergunb 0:8918a71cdbe9 335 uint16_t value;
Sergunb 0:8918a71cdbe9 336
Sergunb 0:8918a71cdbe9 337 //Read interrupt status register
Sergunb 0:8918a71cdbe9 338 status = enc28j60ReadReg(interface, ENC28J60_REG_EIR);
Sergunb 0:8918a71cdbe9 339
Sergunb 0:8918a71cdbe9 340 //Check whether the link state has changed
Sergunb 0:8918a71cdbe9 341 if(status & EIR_LINKIF)
Sergunb 0:8918a71cdbe9 342 {
Sergunb 0:8918a71cdbe9 343 //Clear PHY interrupts flags
Sergunb 0:8918a71cdbe9 344 enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHIR);
Sergunb 0:8918a71cdbe9 345 //Clear interrupt flag
Sergunb 0:8918a71cdbe9 346 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_LINKIF);
Sergunb 0:8918a71cdbe9 347 //Read PHY status register
Sergunb 0:8918a71cdbe9 348 value = enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHSTAT2);
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 //Check link state
Sergunb 0:8918a71cdbe9 351 if(value & PHSTAT2_LSTAT)
Sergunb 0:8918a71cdbe9 352 {
Sergunb 0:8918a71cdbe9 353 //Link speed
Sergunb 0:8918a71cdbe9 354 interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
Sergunb 0:8918a71cdbe9 355
Sergunb 0:8918a71cdbe9 356 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 357 //Full-duplex mode
Sergunb 0:8918a71cdbe9 358 interface->duplexMode = NIC_FULL_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 359 #else
Sergunb 0:8918a71cdbe9 360 //Half-duplex mode
Sergunb 0:8918a71cdbe9 361 interface->duplexMode = NIC_HALF_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 362 #endif
Sergunb 0:8918a71cdbe9 363 //Link is up
Sergunb 0:8918a71cdbe9 364 interface->linkState = TRUE;
Sergunb 0:8918a71cdbe9 365 }
Sergunb 0:8918a71cdbe9 366 else
Sergunb 0:8918a71cdbe9 367 {
Sergunb 0:8918a71cdbe9 368 //Link is down
Sergunb 0:8918a71cdbe9 369 interface->linkState = FALSE;
Sergunb 0:8918a71cdbe9 370 }
Sergunb 0:8918a71cdbe9 371
Sergunb 0:8918a71cdbe9 372 //Process link state change event
Sergunb 0:8918a71cdbe9 373 nicNotifyLinkChange(interface);
Sergunb 0:8918a71cdbe9 374 }
Sergunb 0:8918a71cdbe9 375
Sergunb 0:8918a71cdbe9 376 //Check whether a packet has been received?
Sergunb 0:8918a71cdbe9 377 if(status & EIR_PKTIF)
Sergunb 0:8918a71cdbe9 378 {
Sergunb 0:8918a71cdbe9 379 //Clear interrupt flag
Sergunb 0:8918a71cdbe9 380 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_PKTIF);
Sergunb 0:8918a71cdbe9 381
Sergunb 0:8918a71cdbe9 382 //Process all pending packets
Sergunb 0:8918a71cdbe9 383 do
Sergunb 0:8918a71cdbe9 384 {
Sergunb 0:8918a71cdbe9 385 //Read incoming packet
Sergunb 0:8918a71cdbe9 386 error = enc28j60ReceivePacket(interface);
Sergunb 0:8918a71cdbe9 387
Sergunb 0:8918a71cdbe9 388 //No more data in the receive buffer?
Sergunb 0:8918a71cdbe9 389 } while(error != ERROR_BUFFER_EMPTY);
Sergunb 0:8918a71cdbe9 390 }
Sergunb 0:8918a71cdbe9 391
Sergunb 0:8918a71cdbe9 392 //Re-enable LINKIE and PKTIE interrupts
Sergunb 0:8918a71cdbe9 393 enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_LINKIE | EIE_PKTIE);
Sergunb 0:8918a71cdbe9 394 }
Sergunb 0:8918a71cdbe9 395
Sergunb 0:8918a71cdbe9 396
Sergunb 0:8918a71cdbe9 397 /**
Sergunb 0:8918a71cdbe9 398 * @brief Send a packet
Sergunb 0:8918a71cdbe9 399 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 400 * @param[in] buffer Multi-part buffer containing the data to send
Sergunb 0:8918a71cdbe9 401 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 402 * @return Error code
Sergunb 0:8918a71cdbe9 403 **/
Sergunb 0:8918a71cdbe9 404
Sergunb 0:8918a71cdbe9 405 error_t enc28j60SendPacket(NetInterface *interface,
Sergunb 0:8918a71cdbe9 406 const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 407 {
Sergunb 0:8918a71cdbe9 408 size_t length;
Sergunb 0:8918a71cdbe9 409
Sergunb 0:8918a71cdbe9 410 //Retrieve the length of the packet
Sergunb 0:8918a71cdbe9 411 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 412
Sergunb 0:8918a71cdbe9 413 //Check the frame length
Sergunb 0:8918a71cdbe9 414 if(length > 1536)
Sergunb 0:8918a71cdbe9 415 {
Sergunb 0:8918a71cdbe9 416 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 417 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 418 //Report an error
Sergunb 0:8918a71cdbe9 419 return ERROR_INVALID_LENGTH;
Sergunb 0:8918a71cdbe9 420 }
Sergunb 0:8918a71cdbe9 421
Sergunb 0:8918a71cdbe9 422 //Make sure the link is up before transmitting the frame
Sergunb 0:8918a71cdbe9 423 if(!interface->linkState)
Sergunb 0:8918a71cdbe9 424 {
Sergunb 0:8918a71cdbe9 425 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 426 osSetEventFromIsr(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 427 //Drop current packet
Sergunb 0:8918a71cdbe9 428 return NO_ERROR;
Sergunb 0:8918a71cdbe9 429 }
Sergunb 0:8918a71cdbe9 430
Sergunb 0:8918a71cdbe9 431 //It is recommended to reset the transmit logic before
Sergunb 0:8918a71cdbe9 432 //attempting to transmit a packet
Sergunb 0:8918a71cdbe9 433 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST);
Sergunb 0:8918a71cdbe9 434 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST);
Sergunb 0:8918a71cdbe9 435
Sergunb 0:8918a71cdbe9 436 //Interrupt flags should be cleared after the reset is completed
Sergunb 0:8918a71cdbe9 437 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIR_TXERIF);
Sergunb 0:8918a71cdbe9 438
Sergunb 0:8918a71cdbe9 439 //Set transmit buffer location
Sergunb 0:8918a71cdbe9 440 enc28j60WriteReg(interface, ENC28J60_REG_ETXSTL, LSB(ENC28J60_TX_BUFFER_START));
Sergunb 0:8918a71cdbe9 441 enc28j60WriteReg(interface, ENC28J60_REG_ETXSTH, MSB(ENC28J60_TX_BUFFER_START));
Sergunb 0:8918a71cdbe9 442
Sergunb 0:8918a71cdbe9 443 //Point to start of transmit buffer
Sergunb 0:8918a71cdbe9 444 enc28j60WriteReg(interface, ENC28J60_REG_EWRPTL, LSB(ENC28J60_TX_BUFFER_START));
Sergunb 0:8918a71cdbe9 445 enc28j60WriteReg(interface, ENC28J60_REG_EWRPTH, MSB(ENC28J60_TX_BUFFER_START));
Sergunb 0:8918a71cdbe9 446
Sergunb 0:8918a71cdbe9 447 //Copy the data to the transmit buffer
Sergunb 0:8918a71cdbe9 448 enc28j60WriteBuffer(interface, buffer, offset);
Sergunb 0:8918a71cdbe9 449
Sergunb 0:8918a71cdbe9 450 //ETXND should point to the last byte in the data payload
Sergunb 0:8918a71cdbe9 451 enc28j60WriteReg(interface, ENC28J60_REG_ETXNDL, LSB(ENC28J60_TX_BUFFER_START + length));
Sergunb 0:8918a71cdbe9 452 enc28j60WriteReg(interface, ENC28J60_REG_ETXNDH, MSB(ENC28J60_TX_BUFFER_START + length));
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 //Start transmission
Sergunb 0:8918a71cdbe9 455 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRTS);
Sergunb 0:8918a71cdbe9 456
Sergunb 0:8918a71cdbe9 457 //Successful processing
Sergunb 0:8918a71cdbe9 458 return NO_ERROR;
Sergunb 0:8918a71cdbe9 459 }
Sergunb 0:8918a71cdbe9 460
Sergunb 0:8918a71cdbe9 461
Sergunb 0:8918a71cdbe9 462 /**
Sergunb 0:8918a71cdbe9 463 * @brief Receive a packet
Sergunb 0:8918a71cdbe9 464 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 465 * @return Error code
Sergunb 0:8918a71cdbe9 466 **/
Sergunb 0:8918a71cdbe9 467
Sergunb 0:8918a71cdbe9 468 error_t enc28j60ReceivePacket(NetInterface *interface)
Sergunb 0:8918a71cdbe9 469 {
Sergunb 0:8918a71cdbe9 470 error_t error;
Sergunb 0:8918a71cdbe9 471 uint16_t n;
Sergunb 0:8918a71cdbe9 472 uint16_t status;
Sergunb 0:8918a71cdbe9 473 Enc28j60Context *context;
Sergunb 0:8918a71cdbe9 474
Sergunb 0:8918a71cdbe9 475 //Point to the driver context
Sergunb 0:8918a71cdbe9 476 context = (Enc28j60Context *) interface->nicContext;
Sergunb 0:8918a71cdbe9 477
Sergunb 0:8918a71cdbe9 478 //Any packet pending in the receive buffer?
Sergunb 0:8918a71cdbe9 479 if(enc28j60ReadReg(interface, ENC28J60_REG_EPKTCNT))
Sergunb 0:8918a71cdbe9 480 {
Sergunb 0:8918a71cdbe9 481 //Point to the start of the received packet
Sergunb 0:8918a71cdbe9 482 enc28j60WriteReg(interface, ENC28J60_REG_ERDPTL, LSB(context->nextPacket));
Sergunb 0:8918a71cdbe9 483 enc28j60WriteReg(interface, ENC28J60_REG_ERDPTH, MSB(context->nextPacket));
Sergunb 0:8918a71cdbe9 484
Sergunb 0:8918a71cdbe9 485 //Read the first two bytes, which are the address of the next packet
Sergunb 0:8918a71cdbe9 486 enc28j60ReadBuffer(interface, (uint8_t *) &context->nextPacket, sizeof(uint16_t));
Sergunb 0:8918a71cdbe9 487 //Get the length of the received frame in bytes
Sergunb 0:8918a71cdbe9 488 enc28j60ReadBuffer(interface, (uint8_t *) &n, sizeof(uint16_t));
Sergunb 0:8918a71cdbe9 489 //Read the receive status vector (RSV)
Sergunb 0:8918a71cdbe9 490 enc28j60ReadBuffer(interface, (uint8_t *) &status, sizeof(uint16_t));
Sergunb 0:8918a71cdbe9 491
Sergunb 0:8918a71cdbe9 492 //Make sure no error occurred
Sergunb 0:8918a71cdbe9 493 if(status & RSV_RECEIVED_OK)
Sergunb 0:8918a71cdbe9 494 {
Sergunb 0:8918a71cdbe9 495 //Limit the number of data to read
Sergunb 0:8918a71cdbe9 496 n = MIN(n, ETH_MAX_FRAME_SIZE);
Sergunb 0:8918a71cdbe9 497 //Read the Ethernet frame
Sergunb 0:8918a71cdbe9 498 enc28j60ReadBuffer(interface, context->rxBuffer, n);
Sergunb 0:8918a71cdbe9 499 //Valid packet received
Sergunb 0:8918a71cdbe9 500 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 501 }
Sergunb 0:8918a71cdbe9 502 else
Sergunb 0:8918a71cdbe9 503 {
Sergunb 0:8918a71cdbe9 504 //The received packet contains an error
Sergunb 0:8918a71cdbe9 505 error = ERROR_INVALID_PACKET;
Sergunb 0:8918a71cdbe9 506 }
Sergunb 0:8918a71cdbe9 507
Sergunb 0:8918a71cdbe9 508 //Advance the ERXRDPT pointer, taking care to wrap back at the
Sergunb 0:8918a71cdbe9 509 //end of the received memory buffer
Sergunb 0:8918a71cdbe9 510 if(context->nextPacket == ENC28J60_RX_BUFFER_START)
Sergunb 0:8918a71cdbe9 511 {
Sergunb 0:8918a71cdbe9 512 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 513 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
Sergunb 0:8918a71cdbe9 514 }
Sergunb 0:8918a71cdbe9 515 else
Sergunb 0:8918a71cdbe9 516 {
Sergunb 0:8918a71cdbe9 517 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(context->nextPacket - 1));
Sergunb 0:8918a71cdbe9 518 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(context->nextPacket - 1));
Sergunb 0:8918a71cdbe9 519 }
Sergunb 0:8918a71cdbe9 520
Sergunb 0:8918a71cdbe9 521 //Decrement the packet counter
Sergunb 0:8918a71cdbe9 522 enc28j60SetBit(interface, ENC28J60_REG_ECON2, ECON2_PKTDEC);
Sergunb 0:8918a71cdbe9 523 }
Sergunb 0:8918a71cdbe9 524 else
Sergunb 0:8918a71cdbe9 525 {
Sergunb 0:8918a71cdbe9 526 //No more data in the receive buffer
Sergunb 0:8918a71cdbe9 527 error = ERROR_BUFFER_EMPTY;
Sergunb 0:8918a71cdbe9 528 }
Sergunb 0:8918a71cdbe9 529
Sergunb 0:8918a71cdbe9 530 //Check whether a valid packet has been received
Sergunb 0:8918a71cdbe9 531 if(!error)
Sergunb 0:8918a71cdbe9 532 {
Sergunb 0:8918a71cdbe9 533 //Pass the packet to the upper layer
Sergunb 0:8918a71cdbe9 534 nicProcessPacket(interface, context->rxBuffer, n);
Sergunb 0:8918a71cdbe9 535 }
Sergunb 0:8918a71cdbe9 536
Sergunb 0:8918a71cdbe9 537 //Return status code
Sergunb 0:8918a71cdbe9 538 return error;
Sergunb 0:8918a71cdbe9 539 }
Sergunb 0:8918a71cdbe9 540
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542 /**
Sergunb 0:8918a71cdbe9 543 * @brief Configure multicast MAC address filtering
Sergunb 0:8918a71cdbe9 544 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 545 * @return Error code
Sergunb 0:8918a71cdbe9 546 **/
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548 error_t enc28j60SetMulticastFilter(NetInterface *interface)
Sergunb 0:8918a71cdbe9 549 {
Sergunb 0:8918a71cdbe9 550 uint_t i;
Sergunb 0:8918a71cdbe9 551 uint_t k;
Sergunb 0:8918a71cdbe9 552 uint32_t crc;
Sergunb 0:8918a71cdbe9 553 uint8_t hashTable[8];
Sergunb 0:8918a71cdbe9 554 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 555
Sergunb 0:8918a71cdbe9 556 //Debug message
Sergunb 0:8918a71cdbe9 557 TRACE_DEBUG("Updating ENC28J60 hash table...\r\n");
Sergunb 0:8918a71cdbe9 558
Sergunb 0:8918a71cdbe9 559 //Clear hash table
Sergunb 0:8918a71cdbe9 560 memset(hashTable, 0, sizeof(hashTable));
Sergunb 0:8918a71cdbe9 561
Sergunb 0:8918a71cdbe9 562 //The MAC filter table contains the multicast MAC addresses
Sergunb 0:8918a71cdbe9 563 //to accept when receiving an Ethernet frame
Sergunb 0:8918a71cdbe9 564 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 565 {
Sergunb 0:8918a71cdbe9 566 //Point to the current entry
Sergunb 0:8918a71cdbe9 567 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 568
Sergunb 0:8918a71cdbe9 569 //Valid entry?
Sergunb 0:8918a71cdbe9 570 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 571 {
Sergunb 0:8918a71cdbe9 572 //Compute CRC over the current MAC address
Sergunb 0:8918a71cdbe9 573 crc = enc28j60CalcCrc(&entry->addr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 574 //Calculate the corresponding index in the table
Sergunb 0:8918a71cdbe9 575 k = (crc >> 23) & 0x3F;
Sergunb 0:8918a71cdbe9 576 //Update hash table contents
Sergunb 0:8918a71cdbe9 577 hashTable[k / 8] |= (1 << (k % 8));
Sergunb 0:8918a71cdbe9 578 }
Sergunb 0:8918a71cdbe9 579 }
Sergunb 0:8918a71cdbe9 580
Sergunb 0:8918a71cdbe9 581 //Write the hash table to the ENC28J60 controller
Sergunb 0:8918a71cdbe9 582 enc28j60WriteReg(interface, ENC28J60_REG_EHT0, hashTable[0]);
Sergunb 0:8918a71cdbe9 583 enc28j60WriteReg(interface, ENC28J60_REG_EHT1, hashTable[1]);
Sergunb 0:8918a71cdbe9 584 enc28j60WriteReg(interface, ENC28J60_REG_EHT2, hashTable[2]);
Sergunb 0:8918a71cdbe9 585 enc28j60WriteReg(interface, ENC28J60_REG_EHT3, hashTable[3]);
Sergunb 0:8918a71cdbe9 586 enc28j60WriteReg(interface, ENC28J60_REG_EHT4, hashTable[4]);
Sergunb 0:8918a71cdbe9 587 enc28j60WriteReg(interface, ENC28J60_REG_EHT5, hashTable[5]);
Sergunb 0:8918a71cdbe9 588 enc28j60WriteReg(interface, ENC28J60_REG_EHT6, hashTable[6]);
Sergunb 0:8918a71cdbe9 589 enc28j60WriteReg(interface, ENC28J60_REG_EHT7, hashTable[7]);
Sergunb 0:8918a71cdbe9 590
Sergunb 0:8918a71cdbe9 591 //Debug message
Sergunb 0:8918a71cdbe9 592 TRACE_DEBUG(" EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT0));
Sergunb 0:8918a71cdbe9 593 TRACE_DEBUG(" EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT1));
Sergunb 0:8918a71cdbe9 594 TRACE_DEBUG(" EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT2));
Sergunb 0:8918a71cdbe9 595 TRACE_DEBUG(" EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT3));
Sergunb 0:8918a71cdbe9 596 TRACE_DEBUG(" EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT4));
Sergunb 0:8918a71cdbe9 597 TRACE_DEBUG(" EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT5));
Sergunb 0:8918a71cdbe9 598 TRACE_DEBUG(" EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT6));
Sergunb 0:8918a71cdbe9 599 TRACE_DEBUG(" EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT7));
Sergunb 0:8918a71cdbe9 600
Sergunb 0:8918a71cdbe9 601 //Successful processing
Sergunb 0:8918a71cdbe9 602 return NO_ERROR;
Sergunb 0:8918a71cdbe9 603 }
Sergunb 0:8918a71cdbe9 604
Sergunb 0:8918a71cdbe9 605
Sergunb 0:8918a71cdbe9 606 /**
Sergunb 0:8918a71cdbe9 607 * @brief ENC28J60 controller reset
Sergunb 0:8918a71cdbe9 608 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 609 **/
Sergunb 0:8918a71cdbe9 610
Sergunb 0:8918a71cdbe9 611 void enc28j60SoftReset(NetInterface *interface)
Sergunb 0:8918a71cdbe9 612 {
Sergunb 0:8918a71cdbe9 613 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 614 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 615
Sergunb 0:8918a71cdbe9 616 //Write opcode
Sergunb 0:8918a71cdbe9 617 interface->spiDriver->transfer(ENC28J60_CMD_SRC);
Sergunb 0:8918a71cdbe9 618
Sergunb 0:8918a71cdbe9 619 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 620 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 621 }
Sergunb 0:8918a71cdbe9 622
Sergunb 0:8918a71cdbe9 623
Sergunb 0:8918a71cdbe9 624 /**
Sergunb 0:8918a71cdbe9 625 * @brief Bank selection
Sergunb 0:8918a71cdbe9 626 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 627 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 628 **/
Sergunb 0:8918a71cdbe9 629
Sergunb 0:8918a71cdbe9 630 void enc28j60SelectBank(NetInterface *interface, uint16_t address)
Sergunb 0:8918a71cdbe9 631 {
Sergunb 0:8918a71cdbe9 632 uint16_t bank;
Sergunb 0:8918a71cdbe9 633 Enc28j60Context *context;
Sergunb 0:8918a71cdbe9 634
Sergunb 0:8918a71cdbe9 635 //Point to the driver context
Sergunb 0:8918a71cdbe9 636 context = (Enc28j60Context *) interface->nicContext;
Sergunb 0:8918a71cdbe9 637
Sergunb 0:8918a71cdbe9 638 //Get the bank number from the specified address
Sergunb 0:8918a71cdbe9 639 bank = address & REG_BANK_MASK;
Sergunb 0:8918a71cdbe9 640
Sergunb 0:8918a71cdbe9 641 //Rewrite the bank number only if a change is detected
Sergunb 0:8918a71cdbe9 642 if(bank != context->currentBank)
Sergunb 0:8918a71cdbe9 643 {
Sergunb 0:8918a71cdbe9 644 //Select specified bank
Sergunb 0:8918a71cdbe9 645 switch(bank)
Sergunb 0:8918a71cdbe9 646 {
Sergunb 0:8918a71cdbe9 647 case BANK_0:
Sergunb 0:8918a71cdbe9 648 //Select bank 0
Sergunb 0:8918a71cdbe9 649 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0);
Sergunb 0:8918a71cdbe9 650 break;
Sergunb 0:8918a71cdbe9 651 case BANK_1:
Sergunb 0:8918a71cdbe9 652 //Select bank 1
Sergunb 0:8918a71cdbe9 653 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0);
Sergunb 0:8918a71cdbe9 654 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1);
Sergunb 0:8918a71cdbe9 655 break;
Sergunb 0:8918a71cdbe9 656 case BANK_2:
Sergunb 0:8918a71cdbe9 657 //Select bank 2
Sergunb 0:8918a71cdbe9 658 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0);
Sergunb 0:8918a71cdbe9 659 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1);
Sergunb 0:8918a71cdbe9 660 break;
Sergunb 0:8918a71cdbe9 661 case BANK_3:
Sergunb 0:8918a71cdbe9 662 //Select bank 3
Sergunb 0:8918a71cdbe9 663 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0);
Sergunb 0:8918a71cdbe9 664 break;
Sergunb 0:8918a71cdbe9 665 default:
Sergunb 0:8918a71cdbe9 666 //Invalid bank
Sergunb 0:8918a71cdbe9 667 break;
Sergunb 0:8918a71cdbe9 668 }
Sergunb 0:8918a71cdbe9 669
Sergunb 0:8918a71cdbe9 670 //Save bank number
Sergunb 0:8918a71cdbe9 671 context->currentBank = bank;
Sergunb 0:8918a71cdbe9 672 }
Sergunb 0:8918a71cdbe9 673 }
Sergunb 0:8918a71cdbe9 674
Sergunb 0:8918a71cdbe9 675
Sergunb 0:8918a71cdbe9 676 /**
Sergunb 0:8918a71cdbe9 677 * @brief Write ENC28J60 register
Sergunb 0:8918a71cdbe9 678 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 679 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 680 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 681 **/
Sergunb 0:8918a71cdbe9 682
Sergunb 0:8918a71cdbe9 683 void enc28j60WriteReg(NetInterface *interface, uint16_t address, uint8_t data)
Sergunb 0:8918a71cdbe9 684 {
Sergunb 0:8918a71cdbe9 685 //Make sure the corresponding bank is selected
Sergunb 0:8918a71cdbe9 686 enc28j60SelectBank(interface, address);
Sergunb 0:8918a71cdbe9 687
Sergunb 0:8918a71cdbe9 688 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 689 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 690
Sergunb 0:8918a71cdbe9 691 //Write opcode and register address
Sergunb 0:8918a71cdbe9 692 interface->spiDriver->transfer(ENC28J60_CMD_WCR | (address & REG_ADDR_MASK));
Sergunb 0:8918a71cdbe9 693 //Write register value
Sergunb 0:8918a71cdbe9 694 interface->spiDriver->transfer(data);
Sergunb 0:8918a71cdbe9 695
Sergunb 0:8918a71cdbe9 696 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 697 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 698 }
Sergunb 0:8918a71cdbe9 699
Sergunb 0:8918a71cdbe9 700
Sergunb 0:8918a71cdbe9 701 /**
Sergunb 0:8918a71cdbe9 702 * @brief Read ENC28J60 register
Sergunb 0:8918a71cdbe9 703 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 704 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 705 * @return Register value
Sergunb 0:8918a71cdbe9 706 **/
Sergunb 0:8918a71cdbe9 707
Sergunb 0:8918a71cdbe9 708 uint8_t enc28j60ReadReg(NetInterface *interface, uint16_t address)
Sergunb 0:8918a71cdbe9 709 {
Sergunb 0:8918a71cdbe9 710 uint16_t data;
Sergunb 0:8918a71cdbe9 711
Sergunb 0:8918a71cdbe9 712 //Make sure the corresponding bank is selected
Sergunb 0:8918a71cdbe9 713 enc28j60SelectBank(interface, address);
Sergunb 0:8918a71cdbe9 714
Sergunb 0:8918a71cdbe9 715 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 716 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 717
Sergunb 0:8918a71cdbe9 718 //Write opcode and register address
Sergunb 0:8918a71cdbe9 719 interface->spiDriver->transfer(ENC28J60_CMD_RCR | (address & REG_ADDR_MASK));
Sergunb 0:8918a71cdbe9 720
Sergunb 0:8918a71cdbe9 721 //When reading MAC or MII registers, a dummy byte is first shifted out
Sergunb 0:8918a71cdbe9 722 if((address & REG_TYPE_MASK) != ETH_REG_TYPE)
Sergunb 0:8918a71cdbe9 723 interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 724
Sergunb 0:8918a71cdbe9 725 //Read register contents
Sergunb 0:8918a71cdbe9 726 data = interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 727
Sergunb 0:8918a71cdbe9 728 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 729 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 //Return register contents
Sergunb 0:8918a71cdbe9 732 return data;
Sergunb 0:8918a71cdbe9 733 }
Sergunb 0:8918a71cdbe9 734
Sergunb 0:8918a71cdbe9 735
Sergunb 0:8918a71cdbe9 736 /**
Sergunb 0:8918a71cdbe9 737 * @brief Write PHY register
Sergunb 0:8918a71cdbe9 738 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 739 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 740 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 741 **/
Sergunb 0:8918a71cdbe9 742
Sergunb 0:8918a71cdbe9 743 void enc28j60WritePhyReg(NetInterface *interface, uint16_t address, uint16_t data)
Sergunb 0:8918a71cdbe9 744 {
Sergunb 0:8918a71cdbe9 745 //Write register address
Sergunb 0:8918a71cdbe9 746 enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK);
Sergunb 0:8918a71cdbe9 747
Sergunb 0:8918a71cdbe9 748 //Write the lower 8 bits
Sergunb 0:8918a71cdbe9 749 enc28j60WriteReg(interface, ENC28J60_REG_MIWRL, LSB(data));
Sergunb 0:8918a71cdbe9 750 //Write the upper 8 bits
Sergunb 0:8918a71cdbe9 751 enc28j60WriteReg(interface, ENC28J60_REG_MIWRH, MSB(data));
Sergunb 0:8918a71cdbe9 752
Sergunb 0:8918a71cdbe9 753 //Wait until the PHY register has been written
Sergunb 0:8918a71cdbe9 754 while(enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY);
Sergunb 0:8918a71cdbe9 755 }
Sergunb 0:8918a71cdbe9 756
Sergunb 0:8918a71cdbe9 757
Sergunb 0:8918a71cdbe9 758 /**
Sergunb 0:8918a71cdbe9 759 * @brief Read PHY register
Sergunb 0:8918a71cdbe9 760 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 761 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 762 * @return Register value
Sergunb 0:8918a71cdbe9 763 **/
Sergunb 0:8918a71cdbe9 764
Sergunb 0:8918a71cdbe9 765 uint16_t enc28j60ReadPhyReg(NetInterface *interface, uint16_t address)
Sergunb 0:8918a71cdbe9 766 {
Sergunb 0:8918a71cdbe9 767 uint16_t data;
Sergunb 0:8918a71cdbe9 768
Sergunb 0:8918a71cdbe9 769 //Write register address
Sergunb 0:8918a71cdbe9 770 enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK);
Sergunb 0:8918a71cdbe9 771
Sergunb 0:8918a71cdbe9 772 //Start read operation
Sergunb 0:8918a71cdbe9 773 enc28j60WriteReg(interface, ENC28J60_REG_MICMD, MICMD_MIIRD);
Sergunb 0:8918a71cdbe9 774 //Wait for the read operation to complete
Sergunb 0:8918a71cdbe9 775 while(enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY);
Sergunb 0:8918a71cdbe9 776 //Clear command register
Sergunb 0:8918a71cdbe9 777 enc28j60WriteReg(interface, ENC28J60_REG_MICMD, 0);
Sergunb 0:8918a71cdbe9 778
Sergunb 0:8918a71cdbe9 779 //Read the lower 8 bits
Sergunb 0:8918a71cdbe9 780 data = enc28j60ReadReg(interface, ENC28J60_REG_MIRDL);
Sergunb 0:8918a71cdbe9 781 //Read the upper 8 bits
Sergunb 0:8918a71cdbe9 782 data |= enc28j60ReadReg(interface, ENC28J60_REG_MIRDH) << 8;
Sergunb 0:8918a71cdbe9 783
Sergunb 0:8918a71cdbe9 784 //Return register contents
Sergunb 0:8918a71cdbe9 785 return data;
Sergunb 0:8918a71cdbe9 786 }
Sergunb 0:8918a71cdbe9 787
Sergunb 0:8918a71cdbe9 788
Sergunb 0:8918a71cdbe9 789 /**
Sergunb 0:8918a71cdbe9 790 * @brief Write SRAM buffer
Sergunb 0:8918a71cdbe9 791 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 792 * @param[in] buffer Multi-part buffer containing the data to be written
Sergunb 0:8918a71cdbe9 793 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 794 **/
Sergunb 0:8918a71cdbe9 795
Sergunb 0:8918a71cdbe9 796 void enc28j60WriteBuffer(NetInterface *interface,
Sergunb 0:8918a71cdbe9 797 const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 798 {
Sergunb 0:8918a71cdbe9 799 uint_t i;
Sergunb 0:8918a71cdbe9 800 size_t j;
Sergunb 0:8918a71cdbe9 801 size_t n;
Sergunb 0:8918a71cdbe9 802 uint8_t *p;
Sergunb 0:8918a71cdbe9 803
Sergunb 0:8918a71cdbe9 804 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 805 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 806
Sergunb 0:8918a71cdbe9 807 //Write opcode
Sergunb 0:8918a71cdbe9 808 interface->spiDriver->transfer(ENC28J60_CMD_WBM);
Sergunb 0:8918a71cdbe9 809 //Write per-packet control byte
Sergunb 0:8918a71cdbe9 810 interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 811
Sergunb 0:8918a71cdbe9 812 //Loop through data chunks
Sergunb 0:8918a71cdbe9 813 for(i = 0; i < buffer->chunkCount; i++)
Sergunb 0:8918a71cdbe9 814 {
Sergunb 0:8918a71cdbe9 815 //Is there any data to copy from the current chunk?
Sergunb 0:8918a71cdbe9 816 if(offset < buffer->chunk[i].length)
Sergunb 0:8918a71cdbe9 817 {
Sergunb 0:8918a71cdbe9 818 //Point to the first byte to be read
Sergunb 0:8918a71cdbe9 819 p = (uint8_t *) buffer->chunk[i].address + offset;
Sergunb 0:8918a71cdbe9 820 //Compute the number of bytes to copy at a time
Sergunb 0:8918a71cdbe9 821 n = buffer->chunk[i].length - offset;
Sergunb 0:8918a71cdbe9 822
Sergunb 0:8918a71cdbe9 823 //Copy data to SRAM buffer
Sergunb 0:8918a71cdbe9 824 for(j = 0; j < n; j++)
Sergunb 0:8918a71cdbe9 825 interface->spiDriver->transfer(p[j]);
Sergunb 0:8918a71cdbe9 826
Sergunb 0:8918a71cdbe9 827 //Process the next block from the start
Sergunb 0:8918a71cdbe9 828 offset = 0;
Sergunb 0:8918a71cdbe9 829 }
Sergunb 0:8918a71cdbe9 830 else
Sergunb 0:8918a71cdbe9 831 {
Sergunb 0:8918a71cdbe9 832 //Skip the current chunk
Sergunb 0:8918a71cdbe9 833 offset -= buffer->chunk[i].length;
Sergunb 0:8918a71cdbe9 834 }
Sergunb 0:8918a71cdbe9 835 }
Sergunb 0:8918a71cdbe9 836
Sergunb 0:8918a71cdbe9 837 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 838 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 839 }
Sergunb 0:8918a71cdbe9 840
Sergunb 0:8918a71cdbe9 841
Sergunb 0:8918a71cdbe9 842 /**
Sergunb 0:8918a71cdbe9 843 * @brief Read SRAM buffer
Sergunb 0:8918a71cdbe9 844 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 845 * @param[in] data Buffer where to store the incoming data
Sergunb 0:8918a71cdbe9 846 * @param[in] length Number of data to read
Sergunb 0:8918a71cdbe9 847 **/
Sergunb 0:8918a71cdbe9 848
Sergunb 0:8918a71cdbe9 849 void enc28j60ReadBuffer(NetInterface *interface,
Sergunb 0:8918a71cdbe9 850 uint8_t *data, size_t length)
Sergunb 0:8918a71cdbe9 851 {
Sergunb 0:8918a71cdbe9 852 size_t i;
Sergunb 0:8918a71cdbe9 853
Sergunb 0:8918a71cdbe9 854 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 855 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 856
Sergunb 0:8918a71cdbe9 857 //Write opcode
Sergunb 0:8918a71cdbe9 858 interface->spiDriver->transfer(ENC28J60_CMD_RBM);
Sergunb 0:8918a71cdbe9 859
Sergunb 0:8918a71cdbe9 860 //Copy data from SRAM buffer
Sergunb 0:8918a71cdbe9 861 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 862 data[i] = interface->spiDriver->transfer(0x00);
Sergunb 0:8918a71cdbe9 863
Sergunb 0:8918a71cdbe9 864 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 865 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 866 }
Sergunb 0:8918a71cdbe9 867
Sergunb 0:8918a71cdbe9 868
Sergunb 0:8918a71cdbe9 869 /**
Sergunb 0:8918a71cdbe9 870 * @brief Set bit field
Sergunb 0:8918a71cdbe9 871 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 872 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 873 * @param[in] mask Bits to set in the target register
Sergunb 0:8918a71cdbe9 874 **/
Sergunb 0:8918a71cdbe9 875
Sergunb 0:8918a71cdbe9 876 void enc28j60SetBit(NetInterface *interface, uint16_t address, uint16_t mask)
Sergunb 0:8918a71cdbe9 877 {
Sergunb 0:8918a71cdbe9 878 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 879 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 880
Sergunb 0:8918a71cdbe9 881 //Write opcode and register address
Sergunb 0:8918a71cdbe9 882 interface->spiDriver->transfer(ENC28J60_CMD_BFS | (address & REG_ADDR_MASK));
Sergunb 0:8918a71cdbe9 883 //Write bit mask
Sergunb 0:8918a71cdbe9 884 interface->spiDriver->transfer(mask);
Sergunb 0:8918a71cdbe9 885
Sergunb 0:8918a71cdbe9 886 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 887 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 888 }
Sergunb 0:8918a71cdbe9 889
Sergunb 0:8918a71cdbe9 890
Sergunb 0:8918a71cdbe9 891 /**
Sergunb 0:8918a71cdbe9 892 * @brief Clear bit field
Sergunb 0:8918a71cdbe9 893 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 894 * @param[in] address Register address
Sergunb 0:8918a71cdbe9 895 * @param[in] mask Bits to clear in the target register
Sergunb 0:8918a71cdbe9 896 **/
Sergunb 0:8918a71cdbe9 897
Sergunb 0:8918a71cdbe9 898 void enc28j60ClearBit(NetInterface *interface, uint16_t address, uint16_t mask)
Sergunb 0:8918a71cdbe9 899 {
Sergunb 0:8918a71cdbe9 900 //Pull the CS pin low
Sergunb 0:8918a71cdbe9 901 interface->spiDriver->assertCs();
Sergunb 0:8918a71cdbe9 902
Sergunb 0:8918a71cdbe9 903 //Write opcode and register address
Sergunb 0:8918a71cdbe9 904 interface->spiDriver->transfer(ENC28J60_CMD_BFC | (address & REG_ADDR_MASK));
Sergunb 0:8918a71cdbe9 905 //Write bit mask
Sergunb 0:8918a71cdbe9 906 interface->spiDriver->transfer(mask);
Sergunb 0:8918a71cdbe9 907
Sergunb 0:8918a71cdbe9 908 //Terminate the operation by raising the CS pin
Sergunb 0:8918a71cdbe9 909 interface->spiDriver->deassertCs();
Sergunb 0:8918a71cdbe9 910 }
Sergunb 0:8918a71cdbe9 911
Sergunb 0:8918a71cdbe9 912
Sergunb 0:8918a71cdbe9 913 /**
Sergunb 0:8918a71cdbe9 914 * @brief CRC calculation using the polynomial 0x4C11DB7
Sergunb 0:8918a71cdbe9 915 * @param[in] data Pointer to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 916 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 917 * @return Resulting CRC value
Sergunb 0:8918a71cdbe9 918 **/
Sergunb 0:8918a71cdbe9 919
Sergunb 0:8918a71cdbe9 920 uint32_t enc28j60CalcCrc(const void *data, size_t length)
Sergunb 0:8918a71cdbe9 921 {
Sergunb 0:8918a71cdbe9 922 uint_t i;
Sergunb 0:8918a71cdbe9 923 uint_t j;
Sergunb 0:8918a71cdbe9 924
Sergunb 0:8918a71cdbe9 925 //Point to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 926 const uint8_t *p = (uint8_t *) data;
Sergunb 0:8918a71cdbe9 927 //CRC preset value
Sergunb 0:8918a71cdbe9 928 uint32_t crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 929
Sergunb 0:8918a71cdbe9 930 //Loop through data
Sergunb 0:8918a71cdbe9 931 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 932 {
Sergunb 0:8918a71cdbe9 933 //The message is processed bit by bit
Sergunb 0:8918a71cdbe9 934 for(j = 0; j < 8; j++)
Sergunb 0:8918a71cdbe9 935 {
Sergunb 0:8918a71cdbe9 936 //Update CRC value
Sergunb 0:8918a71cdbe9 937 if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
Sergunb 0:8918a71cdbe9 938 crc = (crc << 1) ^ 0x04C11DB7;
Sergunb 0:8918a71cdbe9 939 else
Sergunb 0:8918a71cdbe9 940 crc = crc << 1;
Sergunb 0:8918a71cdbe9 941 }
Sergunb 0:8918a71cdbe9 942 }
Sergunb 0:8918a71cdbe9 943
Sergunb 0:8918a71cdbe9 944 //Return CRC value
Sergunb 0:8918a71cdbe9 945 return crc;
Sergunb 0:8918a71cdbe9 946 }
Sergunb 0:8918a71cdbe9 947
Sergunb 0:8918a71cdbe9 948
Sergunb 0:8918a71cdbe9 949 /**
Sergunb 0:8918a71cdbe9 950 * @brief Dump registers for debugging purpose
Sergunb 0:8918a71cdbe9 951 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 952 **/
Sergunb 0:8918a71cdbe9 953
Sergunb 0:8918a71cdbe9 954 void enc28j60DumpReg(NetInterface *interface)
Sergunb 0:8918a71cdbe9 955 {
Sergunb 0:8918a71cdbe9 956 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
Sergunb 0:8918a71cdbe9 957 uint8_t i;
Sergunb 0:8918a71cdbe9 958 uint8_t bank;
Sergunb 0:8918a71cdbe9 959 uint16_t address;
Sergunb 0:8918a71cdbe9 960
Sergunb 0:8918a71cdbe9 961 //Display header
Sergunb 0:8918a71cdbe9 962 TRACE_DEBUG(" Bank 0 Bank 1 Bank 2 Bank 3\r\n");
Sergunb 0:8918a71cdbe9 963
Sergunb 0:8918a71cdbe9 964 //Loop through register addresses
Sergunb 0:8918a71cdbe9 965 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 966 {
Sergunb 0:8918a71cdbe9 967 //Display register address
Sergunb 0:8918a71cdbe9 968 TRACE_DEBUG("%02" PRIX8 ": ", i);
Sergunb 0:8918a71cdbe9 969
Sergunb 0:8918a71cdbe9 970 //Loop through bank numbers
Sergunb 0:8918a71cdbe9 971 for(bank = 0; bank < 4; bank++)
Sergunb 0:8918a71cdbe9 972 {
Sergunb 0:8918a71cdbe9 973 //Format register address
Sergunb 0:8918a71cdbe9 974 address = (bank << 8) | i;
Sergunb 0:8918a71cdbe9 975
Sergunb 0:8918a71cdbe9 976 //MAC and MII registers require a specific read sequence
Sergunb 0:8918a71cdbe9 977 if(address >= 0x200 && address <= 0x219)
Sergunb 0:8918a71cdbe9 978 address |= MAC_REG_TYPE;
Sergunb 0:8918a71cdbe9 979 else if(address >= 0x300 && address <= 0x305)
Sergunb 0:8918a71cdbe9 980 address |= MAC_REG_TYPE;
Sergunb 0:8918a71cdbe9 981 else if(address == 0x30A)
Sergunb 0:8918a71cdbe9 982 address |= MAC_REG_TYPE;
Sergunb 0:8918a71cdbe9 983
Sergunb 0:8918a71cdbe9 984 //Display register contents
Sergunb 0:8918a71cdbe9 985 TRACE_DEBUG("0x%02" PRIX8 " ", enc28j60ReadReg(interface, address));
Sergunb 0:8918a71cdbe9 986 }
Sergunb 0:8918a71cdbe9 987
Sergunb 0:8918a71cdbe9 988 //Jump to the following line
Sergunb 0:8918a71cdbe9 989 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 990 }
Sergunb 0:8918a71cdbe9 991
Sergunb 0:8918a71cdbe9 992 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 993 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 994 #endif
Sergunb 0:8918a71cdbe9 995 }
Sergunb 0:8918a71cdbe9 996
Sergunb 0:8918a71cdbe9 997
Sergunb 0:8918a71cdbe9 998 /**
Sergunb 0:8918a71cdbe9 999 * @brief Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 1000 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 1001 **/
Sergunb 0:8918a71cdbe9 1002
Sergunb 0:8918a71cdbe9 1003 void enc28j60DumpPhyReg(NetInterface *interface)
Sergunb 0:8918a71cdbe9 1004 {
Sergunb 0:8918a71cdbe9 1005 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
Sergunb 0:8918a71cdbe9 1006 uint8_t i;
Sergunb 0:8918a71cdbe9 1007
Sergunb 0:8918a71cdbe9 1008 //Loop through PHY registers
Sergunb 0:8918a71cdbe9 1009 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 1010 {
Sergunb 0:8918a71cdbe9 1011 //Display current PHY register
Sergunb 0:8918a71cdbe9 1012 TRACE_DEBUG("%02" PRIX8 ": 0x%04" PRIX16 "\r\n", i, enc28j60ReadPhyReg(interface, i));
Sergunb 0:8918a71cdbe9 1013 }
Sergunb 0:8918a71cdbe9 1014
Sergunb 0:8918a71cdbe9 1015 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 1016 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 1017 #endif
Sergunb 0:8918a71cdbe9 1018 }
Sergunb 0:8918a71cdbe9 1019