123

Committer:
hudakz
Date:
Sat Sep 07 17:42:42 2019 +0000
Revision:
15:53715cc81c63
Parent:
14:7648334eb41b
Child:
16:269f652b4d0b
Timeout parameter added for the 'connect' function, SPI speed reduced from 20 to 10 Mb/s, debug messages fixed ...

Who changed what in which revision?

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