mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Committer:
hudakz
Date:
Sun Mar 08 20:26:56 2015 +0000
Revision:
4:d774541a34da
Parent:
3:5b17e4656dd0
Child:
8:4acb22344932
Version 1.09 (fixed leaking client-data caused by race-condition on remote close)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 4:d774541a34da 1 /*
hudakz 4:d774541a34da 2 Enc28J60Network.cpp
hudakz 4:d774541a34da 3 UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
hudakz 4:d774541a34da 4
hudakz 4:d774541a34da 5 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
hudakz 4:d774541a34da 6 All rights reserved.
hudakz 4:d774541a34da 7
hudakz 4:d774541a34da 8 based on enc28j60.c file from the AVRlib library by Pascal Stang.
hudakz 4:d774541a34da 9 For AVRlib See http://www.procyonengineering.com/
hudakz 4:d774541a34da 10
hudakz 4:d774541a34da 11 Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
hudakz 4:d774541a34da 12
hudakz 4:d774541a34da 13 This program is free software: you can redistribute it and/or modify
hudakz 4:d774541a34da 14 it under the terms of the GNU General Public License as published by
hudakz 4:d774541a34da 15 the Free Software Foundation, either version 3 of the License, or
hudakz 4:d774541a34da 16 (at your option) any later version.
hudakz 4:d774541a34da 17
hudakz 4:d774541a34da 18 This program is distributed in the hope that it will be useful,
hudakz 4:d774541a34da 19 but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 4:d774541a34da 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 4:d774541a34da 21 GNU General Public License for more details.
hudakz 4:d774541a34da 22
hudakz 4:d774541a34da 23 You should have received a copy of the GNU General Public License
hudakz 4:d774541a34da 24 along with this program. If not, see <http://www.gnu.org/licenses/>.
hudakz 4:d774541a34da 25 */
hudakz 4:d774541a34da 26 #include "Enc28J60Network.h"
hudakz 4:d774541a34da 27 #include <mbed.h>
hudakz 4:d774541a34da 28
hudakz 4:d774541a34da 29 extern "C"
hudakz 4:d774541a34da 30 {
hudakz 4:d774541a34da 31 #include "enc28j60.h"
hudakz 4:d774541a34da 32 #include "uip.h"
hudakz 4:d774541a34da 33 }
hudakz 4:d774541a34da 34 #ifdef ENC28J60DEBUG
hudakz 4:d774541a34da 35 #include "HardwareSerial.h"
hudakz 4:d774541a34da 36 #endif
hudakz 4:d774541a34da 37 uint16_t Enc28J60Network:: nextPacketPtr;
hudakz 4:d774541a34da 38 uint8_t Enc28J60Network:: bank = 0xff;
hudakz 4:d774541a34da 39
hudakz 4:d774541a34da 40 struct memblock Enc28J60Network:: receivePkt;
hudakz 4:d774541a34da 41
hudakz 4:d774541a34da 42 /**
hudakz 4:d774541a34da 43 * @brief
hudakz 4:d774541a34da 44 * @note
hudakz 4:d774541a34da 45 * @param
hudakz 4:d774541a34da 46 * @retval
hudakz 4:d774541a34da 47 */
hudakz 4:d774541a34da 48 Enc28J60Network::Enc28J60Network(PinName mosi, PinName miso, PinName sclk, PinName cs) :
hudakz 4:d774541a34da 49 MemoryPool(),
hudakz 4:d774541a34da 50 _spi(mosi, miso, sclk),
hudakz 4:d774541a34da 51 _cs(cs)
hudakz 4:d774541a34da 52 { }
hudakz 4:d774541a34da 53
hudakz 4:d774541a34da 54 /**
hudakz 4:d774541a34da 55 * @brief
hudakz 4:d774541a34da 56 * @note
hudakz 4:d774541a34da 57 * @param
hudakz 4:d774541a34da 58 * @retval
hudakz 4:d774541a34da 59 */
hudakz 4:d774541a34da 60 void Enc28J60Network::init(uint8_t* macaddr) {
hudakz 4:d774541a34da 61 MemoryPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
hudakz 4:d774541a34da 62
hudakz 4:d774541a34da 63 // initialize SPI interface
hudakz 4:d774541a34da 64 _spi.format(8, 0); // 8bit, mode 0
hudakz 4:d774541a34da 65 _spi.frequency(7000000); // 7MHz
hudakz 4:d774541a34da 66 wait(1); // 1 second for stable state
hudakz 4:d774541a34da 67
hudakz 4:d774541a34da 68 // initialize I/O
hudakz 4:d774541a34da 69 _cs = 1; // ss=0
hudakz 4:d774541a34da 70
hudakz 4:d774541a34da 71 // perform system reset
hudakz 4:d774541a34da 72 writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
hudakz 4:d774541a34da 73 wait_ms(50);
hudakz 4:d774541a34da 74
hudakz 4:d774541a34da 75 // check CLKRDY bit to see if reset is complete
hudakz 4:d774541a34da 76 // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
hudakz 4:d774541a34da 77 //while(!(readReg(ESTAT) & ESTAT_CLKRDY));
hudakz 4:d774541a34da 78 // do bank 0 stuff
hudakz 4:d774541a34da 79 // initialize receive buffer
hudakz 4:d774541a34da 80 // 16-bit transfers, must write low byte first
hudakz 4:d774541a34da 81 // set receive buffer start address
hudakz 4:d774541a34da 82 nextPacketPtr = RXSTART_INIT;
hudakz 4:d774541a34da 83
hudakz 4:d774541a34da 84 // Rx start
hudakz 4:d774541a34da 85 writeRegPair(ERXSTL, RXSTART_INIT);
hudakz 4:d774541a34da 86
hudakz 4:d774541a34da 87 // set receive pointer address
hudakz 4:d774541a34da 88 writeRegPair(ERXRDPTL, RXSTART_INIT);
hudakz 4:d774541a34da 89
hudakz 4:d774541a34da 90 // RX end
hudakz 4:d774541a34da 91 writeRegPair(ERXNDL, RXSTOP_INIT);
hudakz 4:d774541a34da 92
hudakz 4:d774541a34da 93 // TX start
hudakz 4:d774541a34da 94 //writeRegPair(ETXSTL, TXSTART_INIT);
hudakz 4:d774541a34da 95 // TX end
hudakz 4:d774541a34da 96 //writeRegPair(ETXNDL, TXSTOP_INIT);
hudakz 4:d774541a34da 97 // do bank 1 stuff, packet filter:
hudakz 4:d774541a34da 98 // For broadcast packets we allow only ARP packtets
hudakz 4:d774541a34da 99 // All other packets should be unicast only for our mac (MAADR)
hudakz 4:d774541a34da 100 //
hudakz 4:d774541a34da 101 // The pattern to match on is therefore
hudakz 4:d774541a34da 102 // Type ETH.DST
hudakz 4:d774541a34da 103 // ARP BROADCAST
hudakz 4:d774541a34da 104 // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
hudakz 4:d774541a34da 105 // in binary these poitions are:11 0000 0011 1111
hudakz 4:d774541a34da 106 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
hudakz 4:d774541a34da 107 //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN!
hudakz 4:d774541a34da 108 writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN);
hudakz 4:d774541a34da 109 writeRegPair(EPMM0, 0x303f);
hudakz 4:d774541a34da 110 writeRegPair(EPMCSL, 0xf7f9);
hudakz 4:d774541a34da 111
hudakz 4:d774541a34da 112 //
hudakz 4:d774541a34da 113 //
hudakz 4:d774541a34da 114 // do bank 2 stuff
hudakz 4:d774541a34da 115 // enable MAC receive
hudakz 4:d774541a34da 116 // and bring MAC out of reset (writes 0x00 to MACON2)
hudakz 4:d774541a34da 117 writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
hudakz 4:d774541a34da 118
hudakz 4:d774541a34da 119 // enable automatic padding to 60bytes and CRC operations
hudakz 4:d774541a34da 120 writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
hudakz 4:d774541a34da 121
hudakz 4:d774541a34da 122 // set inter-frame gap (non-back-to-back)
hudakz 4:d774541a34da 123 writeRegPair(MAIPGL, 0x0C12);
hudakz 4:d774541a34da 124
hudakz 4:d774541a34da 125 // set inter-frame gap (back-to-back)
hudakz 4:d774541a34da 126 writeReg(MABBIPG, 0x12);
hudakz 4:d774541a34da 127
hudakz 4:d774541a34da 128 // Set the maximum packet size which the controller will accept
hudakz 4:d774541a34da 129 // Do not send packets longer than MAX_FRAMELEN:
hudakz 4:d774541a34da 130 writeRegPair(MAMXFLL, MAX_FRAMELEN);
hudakz 4:d774541a34da 131
hudakz 4:d774541a34da 132 // do bank 3 stuff
hudakz 4:d774541a34da 133 // write MAC address
hudakz 4:d774541a34da 134 // NOTE: MAC address in ENC28J60 is byte-backward
hudakz 4:d774541a34da 135 writeReg(MAADR5, macaddr[0]);
hudakz 4:d774541a34da 136 writeReg(MAADR4, macaddr[1]);
hudakz 4:d774541a34da 137 writeReg(MAADR3, macaddr[2]);
hudakz 4:d774541a34da 138 writeReg(MAADR2, macaddr[3]);
hudakz 4:d774541a34da 139 writeReg(MAADR1, macaddr[4]);
hudakz 4:d774541a34da 140 writeReg(MAADR0, macaddr[5]);
hudakz 4:d774541a34da 141
hudakz 4:d774541a34da 142 // no loopback of transmitted frames
hudakz 4:d774541a34da 143 phyWrite(PHCON2, PHCON2_HDLDIS);
hudakz 4:d774541a34da 144
hudakz 4:d774541a34da 145 // switch to bank 0
hudakz 4:d774541a34da 146 setBank(ECON1);
hudakz 4:d774541a34da 147
hudakz 4:d774541a34da 148 // enable interrutps
hudakz 4:d774541a34da 149 writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);
hudakz 4:d774541a34da 150
hudakz 4:d774541a34da 151 // enable packet reception
hudakz 4:d774541a34da 152 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
hudakz 4:d774541a34da 153
hudakz 4:d774541a34da 154 clkout(2); // change clkout from 6.25MHz to 12.5MHz
hudakz 4:d774541a34da 155 wait_us(60); // 60us
hudakz 4:d774541a34da 156
hudakz 4:d774541a34da 157 //Configure leds
hudakz 4:d774541a34da 158 phyWrite(PHLCON, 0x476);
hudakz 4:d774541a34da 159 }
hudakz 4:d774541a34da 160
hudakz 4:d774541a34da 161 /**
hudakz 4:d774541a34da 162 * @brief
hudakz 4:d774541a34da 163 * @note
hudakz 4:d774541a34da 164 * @param
hudakz 4:d774541a34da 165 * @retval
hudakz 4:d774541a34da 166 */
hudakz 4:d774541a34da 167 memhandle Enc28J60Network::receivePacket(void) {
hudakz 4:d774541a34da 168 uint8_t rxstat;
hudakz 4:d774541a34da 169 uint16_t len;
hudakz 4:d774541a34da 170 // check if a packet has been received and buffered
hudakz 4:d774541a34da 171
hudakz 4:d774541a34da 172 //if( !(readReg(EIR) & EIR_PKTIF) ){
hudakz 4:d774541a34da 173 // The above does not work. See Rev. B4 Silicon Errata point 6.
hudakz 4:d774541a34da 174 if(readReg(EPKTCNT) != 0) {
hudakz 4:d774541a34da 175 uint16_t readPtr = nextPacketPtr +
hudakz 4:d774541a34da 176 6 > RXSTOP_INIT ? nextPacketPtr +
hudakz 4:d774541a34da 177 6 -
hudakz 4:d774541a34da 178 RXSTOP_INIT +
hudakz 4:d774541a34da 179 RXSTART_INIT : nextPacketPtr +
hudakz 4:d774541a34da 180 6;
hudakz 4:d774541a34da 181 // Set the read pointer to the start of the received packet
hudakz 4:d774541a34da 182
hudakz 4:d774541a34da 183 writeRegPair(ERDPTL, nextPacketPtr);
hudakz 4:d774541a34da 184
hudakz 4:d774541a34da 185 // read the next packet pointer
hudakz 4:d774541a34da 186 nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 4:d774541a34da 187 nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 4:d774541a34da 188
hudakz 4:d774541a34da 189 // read the packet length (see datasheet page 43)
hudakz 4:d774541a34da 190 len = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 4:d774541a34da 191 len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 4:d774541a34da 192 len -= 4; //remove the CRC count
hudakz 4:d774541a34da 193
hudakz 4:d774541a34da 194 // read the receive status (see datasheet page 43)
hudakz 4:d774541a34da 195 rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
hudakz 4:d774541a34da 196
hudakz 4:d774541a34da 197 //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
hudakz 4:d774541a34da 198 #ifdef ENC28J60DEBUG
hudakz 4:d774541a34da 199 Serial.print("receivePacket [");
hudakz 4:d774541a34da 200 Serial.print(readPtr, HEX);
hudakz 4:d774541a34da 201 Serial.print("-");
hudakz 4:d774541a34da 202 Serial.print((readPtr + len) % (RXSTOP_INIT + 1), HEX);
hudakz 4:d774541a34da 203 Serial.print("], next: ");
hudakz 4:d774541a34da 204 Serial.print(nextPacketPtr, HEX);
hudakz 4:d774541a34da 205 Serial.print(", stat: ");
hudakz 4:d774541a34da 206 Serial.print(rxstat, HEX);
hudakz 4:d774541a34da 207 Serial.print(", count: ");
hudakz 4:d774541a34da 208 Serial.print(readReg(EPKTCNT));
hudakz 4:d774541a34da 209 Serial.print(" -> ");
hudakz 4:d774541a34da 210 Serial.println((rxstat & 0x80) != 0 ? "OK" : "failed");
hudakz 4:d774541a34da 211 #endif
hudakz 4:d774541a34da 212 // decrement the packet counter indicate we are done with this packet
hudakz 4:d774541a34da 213
hudakz 4:d774541a34da 214 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
hudakz 4:d774541a34da 215
hudakz 4:d774541a34da 216 // check CRC and symbol errors (see datasheet page 44, table 7-3):
hudakz 4:d774541a34da 217 // The ERXFCON.CRCEN is set by default. Normally we should not
hudakz 4:d774541a34da 218 // need to check this.
hudakz 4:d774541a34da 219 if((rxstat & 0x80) != 0) {
hudakz 4:d774541a34da 220 receivePkt.begin = readPtr;
hudakz 4:d774541a34da 221 receivePkt.size = len;
hudakz 4:d774541a34da 222 return UIP_RECEIVEBUFFERHANDLE;
hudakz 4:d774541a34da 223 }
hudakz 4:d774541a34da 224
hudakz 4:d774541a34da 225 // Move the RX read pointer to the start of the next received packet
hudakz 4:d774541a34da 226 // This frees the memory we just read out
hudakz 4:d774541a34da 227 setERXRDPT();
hudakz 4:d774541a34da 228 }
hudakz 4:d774541a34da 229
hudakz 4:d774541a34da 230 return(NOBLOCK);
hudakz 4:d774541a34da 231 }
hudakz 4:d774541a34da 232
hudakz 4:d774541a34da 233 /**
hudakz 4:d774541a34da 234 * @brief
hudakz 4:d774541a34da 235 * @note
hudakz 4:d774541a34da 236 * @param
hudakz 4:d774541a34da 237 * @retval
hudakz 4:d774541a34da 238 */
hudakz 4:d774541a34da 239 void Enc28J60Network::setERXRDPT(void) {
hudakz 4:d774541a34da 240 writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1);
hudakz 4:d774541a34da 241 }
hudakz 4:d774541a34da 242
hudakz 4:d774541a34da 243 /**
hudakz 4:d774541a34da 244 * @brief
hudakz 4:d774541a34da 245 * @note
hudakz 4:d774541a34da 246 * @param
hudakz 4:d774541a34da 247 * @retval
hudakz 4:d774541a34da 248 */
hudakz 4:d774541a34da 249 memaddress Enc28J60Network::blockSize(memhandle handle) {
hudakz 4:d774541a34da 250 return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
hudakz 4:d774541a34da 251 }
hudakz 4:d774541a34da 252
hudakz 4:d774541a34da 253 /**
hudakz 4:d774541a34da 254 * @brief
hudakz 4:d774541a34da 255 * @note
hudakz 4:d774541a34da 256 * @param
hudakz 4:d774541a34da 257 * @retval
hudakz 4:d774541a34da 258 */
hudakz 4:d774541a34da 259 void Enc28J60Network::sendPacket(memhandle handle) {
hudakz 4:d774541a34da 260 memblock* packet = &blocks[handle];
hudakz 4:d774541a34da 261 uint16_t start = packet->begin - 1;
hudakz 4:d774541a34da 262 uint16_t end = start + packet->size;
hudakz 4:d774541a34da 263
hudakz 4:d774541a34da 264 // backup data at control-byte position
hudakz 4:d774541a34da 265 uint8_t data = readByte(start);
hudakz 4:d774541a34da 266 // write control-byte (if not 0 anyway)
hudakz 4:d774541a34da 267
hudakz 4:d774541a34da 268 if(data)
hudakz 4:d774541a34da 269 writeByte(start, 0);
hudakz 4:d774541a34da 270
hudakz 4:d774541a34da 271 #ifdef ENC28J60DEBUG
hudakz 4:d774541a34da 272 Serial.print("sendPacket(");
hudakz 4:d774541a34da 273 Serial.print(handle);
hudakz 4:d774541a34da 274 Serial.print(") [");
hudakz 4:d774541a34da 275 Serial.print(start, HEX);
hudakz 4:d774541a34da 276 Serial.print("-");
hudakz 4:d774541a34da 277 Serial.print(end, HEX);
hudakz 4:d774541a34da 278 Serial.print("]: ");
hudakz 4:d774541a34da 279 for(uint16_t i = start; i <= end; i++) {
hudakz 4:d774541a34da 280 Serial.print(readByte(i), HEX);
hudakz 4:d774541a34da 281 Serial.print(" ");
hudakz 4:d774541a34da 282 }
hudakz 4:d774541a34da 283
hudakz 4:d774541a34da 284 Serial.println();
hudakz 4:d774541a34da 285 #endif
hudakz 4:d774541a34da 286 // TX start
hudakz 4:d774541a34da 287
hudakz 4:d774541a34da 288 writeRegPair(ETXSTL, start);
hudakz 4:d774541a34da 289
hudakz 4:d774541a34da 290 // Set the TXND pointer to correspond to the packet size given
hudakz 4:d774541a34da 291 writeRegPair(ETXNDL, end);
hudakz 4:d774541a34da 292
hudakz 4:d774541a34da 293 // send the contents of the transmit buffer onto the network
hudakz 4:d774541a34da 294 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
hudakz 4:d774541a34da 295
hudakz 4:d774541a34da 296 // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
hudakz 4:d774541a34da 297 if((readReg(EIR) & EIR_TXERIF)) {
hudakz 4:d774541a34da 298 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
hudakz 4:d774541a34da 299 }
hudakz 4:d774541a34da 300
hudakz 4:d774541a34da 301 //restore data on control-byte position
hudakz 4:d774541a34da 302 if(data)
hudakz 4:d774541a34da 303 writeByte(start, data);
hudakz 4:d774541a34da 304 }
hudakz 4:d774541a34da 305
hudakz 4:d774541a34da 306 /**
hudakz 4:d774541a34da 307 * @brief
hudakz 4:d774541a34da 308 * @note
hudakz 4:d774541a34da 309 * @param
hudakz 4:d774541a34da 310 * @retval
hudakz 4:d774541a34da 311 */
hudakz 4:d774541a34da 312 uint16_t Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) {
hudakz 4:d774541a34da 313 memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle];
hudakz 4:d774541a34da 314 memaddress start = handle == UIP_RECEIVEBUFFERHANDLE
hudakz 4:d774541a34da 315 && packet->begin +
hudakz 4:d774541a34da 316 position > RXSTOP_INIT ? packet->begin +
hudakz 4:d774541a34da 317 position -
hudakz 4:d774541a34da 318 RXSTOP_INIT +
hudakz 4:d774541a34da 319 RXSTART_INIT : packet->begin +
hudakz 4:d774541a34da 320 position;
hudakz 4:d774541a34da 321
hudakz 4:d774541a34da 322 writeRegPair(ERDPTL, start);
hudakz 4:d774541a34da 323
hudakz 4:d774541a34da 324 if(len > packet->size - position)
hudakz 4:d774541a34da 325 len = packet->size - position;
hudakz 4:d774541a34da 326 return len;
hudakz 4:d774541a34da 327 }
hudakz 4:d774541a34da 328
hudakz 4:d774541a34da 329 /**
hudakz 4:d774541a34da 330 * @brief
hudakz 4:d774541a34da 331 * @note
hudakz 4:d774541a34da 332 * @param
hudakz 4:d774541a34da 333 * @retval
hudakz 4:d774541a34da 334 */
hudakz 4:d774541a34da 335 uint16_t Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) {
hudakz 4:d774541a34da 336 len = setReadPtr(handle, position, len);
hudakz 4:d774541a34da 337 readBuffer(len, buffer);
hudakz 4:d774541a34da 338 return len;
hudakz 4:d774541a34da 339 }
hudakz 4:d774541a34da 340
hudakz 4:d774541a34da 341 /**
hudakz 4:d774541a34da 342 * @brief
hudakz 4:d774541a34da 343 * @note
hudakz 4:d774541a34da 344 * @param
hudakz 4:d774541a34da 345 * @retval
hudakz 4:d774541a34da 346 */
hudakz 4:d774541a34da 347 uint16_t Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) {
hudakz 4:d774541a34da 348 memblock* packet = &blocks[handle];
hudakz 4:d774541a34da 349 uint16_t start = packet->begin + position;
hudakz 4:d774541a34da 350
hudakz 4:d774541a34da 351 writeRegPair(EWRPTL, start);
hudakz 4:d774541a34da 352
hudakz 4:d774541a34da 353 if(len > packet->size - position)
hudakz 4:d774541a34da 354 len = packet->size - position;
hudakz 4:d774541a34da 355 writeBuffer(len, buffer);
hudakz 4:d774541a34da 356 return len;
hudakz 4:d774541a34da 357 }
hudakz 4:d774541a34da 358
hudakz 4:d774541a34da 359 /**
hudakz 4:d774541a34da 360 * @brief
hudakz 4:d774541a34da 361 * @note
hudakz 4:d774541a34da 362 * @param
hudakz 4:d774541a34da 363 * @retval
hudakz 4:d774541a34da 364 */
hudakz 4:d774541a34da 365 uint8_t Enc28J60Network::readByte(uint16_t addr) {
hudakz 4:d774541a34da 366 uint8_t result;
hudakz 4:d774541a34da 367
hudakz 4:d774541a34da 368 writeRegPair(ERDPTL, addr);
hudakz 4:d774541a34da 369
hudakz 4:d774541a34da 370 _cs = 0;
hudakz 4:d774541a34da 371
hudakz 4:d774541a34da 372 // issue read command
hudakz 4:d774541a34da 373 _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 4:d774541a34da 374
hudakz 4:d774541a34da 375 // read data
hudakz 4:d774541a34da 376 result = _spi.write(0x00);
hudakz 4:d774541a34da 377 _cs = 1;
hudakz 4:d774541a34da 378 return(result);
hudakz 4:d774541a34da 379 }
hudakz 4:d774541a34da 380
hudakz 4:d774541a34da 381 /**
hudakz 4:d774541a34da 382 * @brief
hudakz 4:d774541a34da 383 * @note
hudakz 4:d774541a34da 384 * @param
hudakz 4:d774541a34da 385 * @retval
hudakz 4:d774541a34da 386 */
hudakz 4:d774541a34da 387 void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) {
hudakz 4:d774541a34da 388 writeRegPair(EWRPTL, addr);
hudakz 4:d774541a34da 389
hudakz 4:d774541a34da 390 _cs = 0;
hudakz 4:d774541a34da 391
hudakz 4:d774541a34da 392 // issue write command
hudakz 4:d774541a34da 393 _spi.write(ENC28J60_WRITE_BUF_MEM);
hudakz 4:d774541a34da 394
hudakz 4:d774541a34da 395 // write data
hudakz 4:d774541a34da 396 _spi.write(data);
hudakz 4:d774541a34da 397 _cs = 1;
hudakz 4:d774541a34da 398 }
hudakz 4:d774541a34da 399
hudakz 4:d774541a34da 400 /**
hudakz 4:d774541a34da 401 * @brief
hudakz 4:d774541a34da 402 * @note
hudakz 4:d774541a34da 403 * @param
hudakz 4:d774541a34da 404 * @retval
hudakz 4:d774541a34da 405 */
hudakz 4:d774541a34da 406 void Enc28J60Network::copyPacket
hudakz 4:d774541a34da 407 (
hudakz 4:d774541a34da 408 memhandle dest_pkt,
hudakz 4:d774541a34da 409 memaddress dest_pos,
hudakz 4:d774541a34da 410 memhandle src_pkt,
hudakz 4:d774541a34da 411 memaddress src_pos,
hudakz 4:d774541a34da 412 uint16_t len
hudakz 4:d774541a34da 413 ) {
hudakz 4:d774541a34da 414 memblock* dest = &blocks[dest_pkt];
hudakz 4:d774541a34da 415 memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
hudakz 4:d774541a34da 416 memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE
hudakz 4:d774541a34da 417 && src->begin +
hudakz 4:d774541a34da 418 src_pos > RXSTOP_INIT ? src->begin +
hudakz 4:d774541a34da 419 src_pos -
hudakz 4:d774541a34da 420 RXSTOP_INIT +
hudakz 4:d774541a34da 421 RXSTART_INIT : src->begin +
hudakz 4:d774541a34da 422 src_pos;
hudakz 4:d774541a34da 423 enc28J60_mempool_block_move_callback(dest->begin + dest_pos, start, len);
hudakz 4:d774541a34da 424
hudakz 4:d774541a34da 425 // Move the RX read pointer to the start of the next received packet
hudakz 4:d774541a34da 426 // This frees the memory we just read out
hudakz 4:d774541a34da 427 setERXRDPT();
hudakz 4:d774541a34da 428 }
hudakz 4:d774541a34da 429
hudakz 4:d774541a34da 430 /**
hudakz 4:d774541a34da 431 * @brief
hudakz 4:d774541a34da 432 * @note
hudakz 4:d774541a34da 433 * @param
hudakz 4:d774541a34da 434 * @retval
hudakz 4:d774541a34da 435 */
hudakz 4:d774541a34da 436 void Enc28J60Network::freePacket(void) {
hudakz 4:d774541a34da 437 setERXRDPT();
hudakz 4:d774541a34da 438 }
hudakz 4:d774541a34da 439
hudakz 4:d774541a34da 440 /**
hudakz 4:d774541a34da 441 * @brief
hudakz 4:d774541a34da 442 * @note
hudakz 4:d774541a34da 443 * @param
hudakz 4:d774541a34da 444 * @retval
hudakz 4:d774541a34da 445 */
hudakz 4:d774541a34da 446 uint8_t Enc28J60Network::readOp(uint8_t op, uint8_t address) {
hudakz 4:d774541a34da 447 uint8_t result;
hudakz 4:d774541a34da 448
hudakz 4:d774541a34da 449 _cs = 0;
hudakz 4:d774541a34da 450
hudakz 4:d774541a34da 451 // issue read command
hudakz 4:d774541a34da 452 _spi.write(op | (address & ADDR_MASK));
hudakz 4:d774541a34da 453
hudakz 4:d774541a34da 454 // read data
hudakz 4:d774541a34da 455 result = _spi.write(0x00);
hudakz 4:d774541a34da 456
hudakz 4:d774541a34da 457 // do dummy read if needed (for mac and mii, see datasheet page 29)
hudakz 4:d774541a34da 458 if(address & 0x80)
hudakz 4:d774541a34da 459 result = _spi.write(0x00);
hudakz 4:d774541a34da 460
hudakz 4:d774541a34da 461 // release CS
hudakz 4:d774541a34da 462 _cs = 1;
hudakz 4:d774541a34da 463 return(result);
hudakz 4:d774541a34da 464 }
hudakz 4:d774541a34da 465
hudakz 4:d774541a34da 466 /**
hudakz 4:d774541a34da 467 * @brief
hudakz 4:d774541a34da 468 * @note
hudakz 4:d774541a34da 469 * @param
hudakz 4:d774541a34da 470 * @retval
hudakz 4:d774541a34da 471 */
hudakz 4:d774541a34da 472 void Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) {
hudakz 4:d774541a34da 473 _cs = 0;
hudakz 4:d774541a34da 474
hudakz 4:d774541a34da 475 // issue write command
hudakz 4:d774541a34da 476 _spi.write(op | (address & ADDR_MASK));
hudakz 4:d774541a34da 477
hudakz 4:d774541a34da 478 // write data
hudakz 4:d774541a34da 479 _spi.write(data);
hudakz 4:d774541a34da 480 _cs = 1;
hudakz 4:d774541a34da 481 }
hudakz 4:d774541a34da 482
hudakz 4:d774541a34da 483 /**
hudakz 4:d774541a34da 484 * @brief
hudakz 4:d774541a34da 485 * @note
hudakz 4:d774541a34da 486 * @param
hudakz 4:d774541a34da 487 * @retval
hudakz 4:d774541a34da 488 */
hudakz 4:d774541a34da 489 void Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) {
hudakz 4:d774541a34da 490 _cs = 0;
hudakz 4:d774541a34da 491
hudakz 4:d774541a34da 492 // issue read command
hudakz 4:d774541a34da 493 _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 4:d774541a34da 494 while(len) {
hudakz 4:d774541a34da 495 len--;
hudakz 4:d774541a34da 496
hudakz 4:d774541a34da 497 // read data
hudakz 4:d774541a34da 498 *data = _spi.write(0x00);
hudakz 4:d774541a34da 499 data++;
hudakz 4:d774541a34da 500 }
hudakz 4:d774541a34da 501
hudakz 4:d774541a34da 502 *data = '\0';
hudakz 4:d774541a34da 503 _cs = 1;
hudakz 4:d774541a34da 504 }
hudakz 4:d774541a34da 505
hudakz 4:d774541a34da 506 /**
hudakz 4:d774541a34da 507 * @brief
hudakz 4:d774541a34da 508 * @note
hudakz 4:d774541a34da 509 * @param
hudakz 4:d774541a34da 510 * @retval
hudakz 4:d774541a34da 511 */
hudakz 4:d774541a34da 512 void Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) {
hudakz 4:d774541a34da 513 _cs = 0;
hudakz 4:d774541a34da 514
hudakz 4:d774541a34da 515 // issue write command
hudakz 4:d774541a34da 516 _spi.write(ENC28J60_WRITE_BUF_MEM);
hudakz 4:d774541a34da 517 while(len) {
hudakz 4:d774541a34da 518 len--;
hudakz 4:d774541a34da 519
hudakz 4:d774541a34da 520 // write data
hudakz 4:d774541a34da 521 _spi.write(*data);
hudakz 4:d774541a34da 522 data++;
hudakz 4:d774541a34da 523 }
hudakz 4:d774541a34da 524
hudakz 4:d774541a34da 525 _cs = 1;
hudakz 4:d774541a34da 526 }
hudakz 4:d774541a34da 527
hudakz 4:d774541a34da 528 /**
hudakz 4:d774541a34da 529 * @brief
hudakz 4:d774541a34da 530 * @note
hudakz 4:d774541a34da 531 * @param
hudakz 4:d774541a34da 532 * @retval
hudakz 4:d774541a34da 533 */
hudakz 4:d774541a34da 534 void Enc28J60Network::setBank(uint8_t address) {
hudakz 4:d774541a34da 535
hudakz 4:d774541a34da 536 // set the bank (if needed)
hudakz 4:d774541a34da 537
hudakz 4:d774541a34da 538 if((address & BANK_MASK) != bank) {
hudakz 4:d774541a34da 539
hudakz 4:d774541a34da 540 // set the bank
hudakz 4:d774541a34da 541 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));
hudakz 4:d774541a34da 542 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);
hudakz 4:d774541a34da 543 bank = (address & BANK_MASK);
hudakz 4:d774541a34da 544 }
hudakz 4:d774541a34da 545 }
hudakz 4:d774541a34da 546
hudakz 4:d774541a34da 547 /**
hudakz 4:d774541a34da 548 * @brief
hudakz 4:d774541a34da 549 * @note
hudakz 4:d774541a34da 550 * @param
hudakz 4:d774541a34da 551 * @retval
hudakz 4:d774541a34da 552 */
hudakz 4:d774541a34da 553 uint8_t Enc28J60Network::readReg(uint8_t address) {
hudakz 4:d774541a34da 554
hudakz 4:d774541a34da 555 // set the bank
hudakz 4:d774541a34da 556
hudakz 4:d774541a34da 557 setBank(address);
hudakz 4:d774541a34da 558
hudakz 4:d774541a34da 559 // do the read
hudakz 4:d774541a34da 560 return readOp(ENC28J60_READ_CTRL_REG, address);
hudakz 4:d774541a34da 561 }
hudakz 4:d774541a34da 562
hudakz 4:d774541a34da 563 /**
hudakz 4:d774541a34da 564 * @brief
hudakz 4:d774541a34da 565 * @note
hudakz 4:d774541a34da 566 * @param
hudakz 4:d774541a34da 567 * @retval
hudakz 4:d774541a34da 568 */
hudakz 4:d774541a34da 569 void Enc28J60Network::writeReg(uint8_t address, uint8_t data) {
hudakz 4:d774541a34da 570
hudakz 4:d774541a34da 571 // set the bank
hudakz 4:d774541a34da 572
hudakz 4:d774541a34da 573 setBank(address);
hudakz 4:d774541a34da 574
hudakz 4:d774541a34da 575 // do the write
hudakz 4:d774541a34da 576 writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
hudakz 4:d774541a34da 577 }
hudakz 4:d774541a34da 578
hudakz 4:d774541a34da 579 /**
hudakz 4:d774541a34da 580 * @brief
hudakz 4:d774541a34da 581 * @note
hudakz 4:d774541a34da 582 * @param
hudakz 4:d774541a34da 583 * @retval
hudakz 4:d774541a34da 584 */
hudakz 4:d774541a34da 585 void Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) {
hudakz 4:d774541a34da 586
hudakz 4:d774541a34da 587 // set the bank
hudakz 4:d774541a34da 588
hudakz 4:d774541a34da 589 setBank(address);
hudakz 4:d774541a34da 590
hudakz 4:d774541a34da 591 // do the write
hudakz 4:d774541a34da 592 writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF));
hudakz 4:d774541a34da 593 writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8);
hudakz 4:d774541a34da 594 }
hudakz 4:d774541a34da 595
hudakz 4:d774541a34da 596 /**
hudakz 4:d774541a34da 597 * @brief
hudakz 4:d774541a34da 598 * @note
hudakz 4:d774541a34da 599 * @param
hudakz 4:d774541a34da 600 * @retval
hudakz 4:d774541a34da 601 */
hudakz 4:d774541a34da 602 void Enc28J60Network::phyWrite(uint8_t address, uint16_t data) {
hudakz 4:d774541a34da 603
hudakz 4:d774541a34da 604 // set the PHY register address
hudakz 4:d774541a34da 605
hudakz 4:d774541a34da 606 writeReg(MIREGADR, address);
hudakz 4:d774541a34da 607
hudakz 4:d774541a34da 608 // write the PHY data
hudakz 4:d774541a34da 609 writeRegPair(MIWRL, data);
hudakz 4:d774541a34da 610
hudakz 4:d774541a34da 611 // wait until the PHY write completes
hudakz 4:d774541a34da 612 while(readReg(MISTAT) & MISTAT_BUSY) {
hudakz 4:d774541a34da 613 wait_us(15);
hudakz 4:d774541a34da 614 }
hudakz 4:d774541a34da 615 }
hudakz 4:d774541a34da 616
hudakz 4:d774541a34da 617 /**
hudakz 4:d774541a34da 618 * @brief
hudakz 4:d774541a34da 619 * @note
hudakz 4:d774541a34da 620 * @param
hudakz 4:d774541a34da 621 * @retval
hudakz 4:d774541a34da 622 */
hudakz 4:d774541a34da 623 uint16_t Enc28J60Network::phyRead(uint8_t address) {
hudakz 4:d774541a34da 624 writeReg(MIREGADR, address);
hudakz 4:d774541a34da 625 writeReg(MICMD, MICMD_MIIRD);
hudakz 4:d774541a34da 626
hudakz 4:d774541a34da 627 // wait until the PHY read completes
hudakz 4:d774541a34da 628 while(readReg(MISTAT) & MISTAT_BUSY) {
hudakz 4:d774541a34da 629 wait_us(15);
hudakz 4:d774541a34da 630 } //and MIRDH
hudakz 4:d774541a34da 631
hudakz 4:d774541a34da 632 writeReg(MICMD, 0);
hudakz 4:d774541a34da 633 return(readReg(MIRDL) | readReg(MIRDH) << 8);
hudakz 4:d774541a34da 634 }
hudakz 4:d774541a34da 635
hudakz 4:d774541a34da 636 /**
hudakz 4:d774541a34da 637 * @brief
hudakz 4:d774541a34da 638 * @note
hudakz 4:d774541a34da 639 * @param
hudakz 4:d774541a34da 640 * @retval
hudakz 4:d774541a34da 641 */
hudakz 4:d774541a34da 642 void Enc28J60Network::clkout(uint8_t clk) {
hudakz 4:d774541a34da 643
hudakz 4:d774541a34da 644 //setup clkout: 2 is 12.5MHz:
hudakz 4:d774541a34da 645
hudakz 4:d774541a34da 646 writeReg(ECOCON, clk & 0x7);
hudakz 4:d774541a34da 647 }
hudakz 4:d774541a34da 648
hudakz 4:d774541a34da 649 // read the revision of the chip:
hudakz 4:d774541a34da 650 uint8_t Enc28J60Network::getrev(void) {
hudakz 4:d774541a34da 651 return(readReg(EREVID));
hudakz 4:d774541a34da 652 }
hudakz 4:d774541a34da 653
hudakz 4:d774541a34da 654 /**
hudakz 4:d774541a34da 655 * @brief
hudakz 4:d774541a34da 656 * @note
hudakz 4:d774541a34da 657 * @param
hudakz 4:d774541a34da 658 * @retval
hudakz 4:d774541a34da 659 */
hudakz 4:d774541a34da 660 uint16_t Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) {
hudakz 4:d774541a34da 661 uint8_t spdr;
hudakz 4:d774541a34da 662 uint16_t t;
hudakz 4:d774541a34da 663 uint16_t i;
hudakz 4:d774541a34da 664
hudakz 4:d774541a34da 665 len = setReadPtr(handle, pos, len) - 1;
hudakz 4:d774541a34da 666 _cs = 0;
hudakz 4:d774541a34da 667
hudakz 4:d774541a34da 668 // issue read command
hudakz 4:d774541a34da 669 spdr = _spi.write(ENC28J60_READ_BUF_MEM);
hudakz 4:d774541a34da 670 for(i = 0; i < len; i += 2) {
hudakz 4:d774541a34da 671
hudakz 4:d774541a34da 672 // read data
hudakz 4:d774541a34da 673 spdr = _spi.write(0x00);
hudakz 4:d774541a34da 674 t = spdr << 8;
hudakz 4:d774541a34da 675 spdr = _spi.write(0x00);
hudakz 4:d774541a34da 676 t += spdr;
hudakz 4:d774541a34da 677 sum += t;
hudakz 4:d774541a34da 678 if(sum < t) {
hudakz 4:d774541a34da 679 sum++; /* carry */
hudakz 4:d774541a34da 680 }
hudakz 4:d774541a34da 681 }
hudakz 4:d774541a34da 682
hudakz 4:d774541a34da 683 if(i == len) {
hudakz 4:d774541a34da 684 spdr = _spi.write(0x00);
hudakz 4:d774541a34da 685 t = (spdr << 8) + 0;
hudakz 4:d774541a34da 686 sum += t;
hudakz 4:d774541a34da 687 if(sum < t) {
hudakz 4:d774541a34da 688 sum++; /* carry */
hudakz 4:d774541a34da 689 }
hudakz 4:d774541a34da 690 }
hudakz 4:d774541a34da 691
hudakz 4:d774541a34da 692 _cs = 1;
hudakz 4:d774541a34da 693
hudakz 4:d774541a34da 694 /* Return sum in host byte order. */
hudakz 4:d774541a34da 695 return sum;
hudakz 4:d774541a34da 696 }
hudakz 4:d774541a34da 697
hudakz 4:d774541a34da 698 /**
hudakz 4:d774541a34da 699 * @brief
hudakz 4:d774541a34da 700 * @note
hudakz 4:d774541a34da 701 * @param
hudakz 4:d774541a34da 702 * @retval
hudakz 4:d774541a34da 703 */
hudakz 4:d774541a34da 704 void Enc28J60Network::powerOff(void) {
hudakz 4:d774541a34da 705 writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
hudakz 4:d774541a34da 706 wait_ms(50);
hudakz 4:d774541a34da 707 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
hudakz 4:d774541a34da 708 wait_ms(50);
hudakz 4:d774541a34da 709 writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
hudakz 4:d774541a34da 710 }
hudakz 4:d774541a34da 711
hudakz 4:d774541a34da 712 /**
hudakz 4:d774541a34da 713 * @brief
hudakz 4:d774541a34da 714 * @note
hudakz 4:d774541a34da 715 * @param
hudakz 4:d774541a34da 716 * @retval
hudakz 4:d774541a34da 717 */
hudakz 4:d774541a34da 718 void Enc28J60Network::powerOn(void) {
hudakz 4:d774541a34da 719 writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
hudakz 4:d774541a34da 720 wait_ms(50);
hudakz 4:d774541a34da 721 writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
hudakz 4:d774541a34da 722 wait_ms(50);
hudakz 4:d774541a34da 723 }
hudakz 4:d774541a34da 724
hudakz 4:d774541a34da 725 /**
hudakz 4:d774541a34da 726 * @brief
hudakz 4:d774541a34da 727 * @note
hudakz 4:d774541a34da 728 * @param
hudakz 4:d774541a34da 729 * @retval
hudakz 4:d774541a34da 730 */
hudakz 4:d774541a34da 731 bool Enc28J60Network::linkStatus(void) {
hudakz 4:d774541a34da 732 return(phyRead(PHSTAT2) & 0x0400) > 0;
hudakz 4:d774541a34da 733 }