Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Enc28j60Eth.cpp Source File

Enc28j60Eth.cpp

00001 /*
00002  Enc28J60Network.cpp
00003  UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface.
00004 
00005  Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
00006  All rights reserved.
00007 
00008  based on enc28j60.c file from the AVRlib library by Pascal Stang.
00009  For AVRlib See http://www.procyonengineering.com/
00010 
00011  Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
00012 
00013  This program is free software: you can redistribute it and/or modify
00014  it under the terms of the GNU General Public License as published by
00015  the Free Software Foundation, either version 3 of the License, or
00016  (at your option) any later version.
00017 
00018  This program is distributed in the hope that it will be useful,
00019  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  GNU General Public License for more details.
00022 
00023  You should have received a copy of the GNU General Public License
00024  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  */
00026 #include "Enc28j60Eth.h"
00027 #include "mbed.h"
00028 #include "mbed_version.h"
00029 
00030 extern "C"
00031 {
00032 #include "enc28j60.h"
00033 #include "uip.h"
00034 }
00035 
00036 // Static member initialization
00037 uint16_t    Enc28j60Eth::nextPacketPtr;
00038 uint8_t     Enc28j60Eth::bank = 0xff;
00039 struct      memblock Enc28j60Eth::receivePkt;
00040 
00041 /**
00042  * @brief
00043  * @note
00044  * @param
00045  * @retval
00046  */
00047 Enc28j60Eth::Enc28j60Eth(PinName mosi, PinName miso, PinName sclk, PinName cs) :
00048     MemPool(),
00049     _spi(mosi, miso, sclk),
00050     _cs(cs)
00051 { }
00052 
00053 /**
00054  * @brief
00055  * @note
00056  * @param
00057  * @retval
00058  */
00059 void Enc28j60Eth::init(uint8_t* macaddr)
00060 {
00061     MemPool::init();            // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte
00062     
00063     // initialize SPI interface
00064     _cs = 1;
00065     _spi.format(8, 0);          // 8-bit, mode 0
00066     _spi.frequency(10000000);   // 10 Mbit/s
00067 #if MBED_MAJOR_VERSION == 2
00068     wait_ms(100);
00069 #else
00070     thread_sleep_for(100);
00071 #endif
00072 
00073     // perform system reset
00074     writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
00075 
00076     // check CLKRDY bit to see if reset is complete
00077     // while(!(readReg(ESTAT) & ESTAT_CLKRDY));
00078     // The CLKRDY does not work. See Rev. B4 Silicon Errata point.
00079     // Just wait.
00080 #if MBED_MAJOR_VERSION == 2
00081     wait_ms(50);
00082 #else
00083     thread_sleep_for(50);
00084 #endif
00085 
00086     // do bank 0 stuff
00087     // initialize receive buffer
00088     // 16-bit transfers, must write low byte first
00089     // set receive buffer start address
00090     nextPacketPtr = RXSTART_INIT;
00091 
00092     // Rx start
00093     writeRegPair(ERXSTL, RXSTART_INIT);
00094 
00095     // set receive pointer address
00096     writeRegPair(ERXRDPTL, RXSTART_INIT);
00097 
00098     // RX end
00099     writeRegPair(ERXNDL, RXEND_INIT);
00100 
00101     //All memory which is not used by the receive buffer is considered the transmission buffer.
00102     // No explicit action is required to initialize the transmission buffer.
00103     // TX start
00104     //writeRegPair(ETXSTL, TXSTART_INIT);
00105     // TX end
00106     //writeRegPair(ETXNDL, TXEND_INIT);
00107     // However, he host controller should leave at least seven bytes between each
00108     // packet and the beginning of the receive buffer.
00109 
00110     // do bank 1 stuff, packet filter:
00111     // For broadcast packets we allow only ARP packtets
00112     // All other packets should be unicast only for our mac (MAADR)
00113     //
00114     // The pattern to match is therefore
00115     // Type     ETH.DST
00116     // ARP      BROADCAST
00117     // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
00118     // in binary these poitions are:11 0000 0011 1111
00119     // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
00120     //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN!
00121     writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN);
00122     writeRegPair(EPMM0, 0x303f);
00123     writeRegPair(EPMCSL, 0xf7f9);
00124 
00125     //
00126     //
00127     // do bank 2 stuff,
00128     // enable MAC receive
00129     // and bring MAC out of reset (writes 0x00 to MACON2)
00130     writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
00131 
00132     // enable automatic padding to 60bytes and CRC operations
00133     writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN);
00134 
00135     // set inter-frame gap (non-back-to-back)
00136     writeRegPair(MAIPGL, 0x0C12);
00137 
00138     // set inter-frame gap (back-to-back)
00139     writeReg(MABBIPG, 0x12);
00140 
00141     // Set the maximum packet size which the controller will accept
00142     // Do not send packets longer than MAX_FRAMELEN:
00143     writeRegPair(MAMXFLL, MAX_FRAMELEN);
00144 
00145     // do bank 3 stuff
00146     // write MAC address
00147     // NOTE: MAC address in ENC28J60 is byte-backward
00148     writeReg(MAADR5, macaddr[0]);
00149     writeReg(MAADR4, macaddr[1]);
00150     writeReg(MAADR3, macaddr[2]);
00151     writeReg(MAADR2, macaddr[3]);
00152     writeReg(MAADR1, macaddr[4]);
00153     writeReg(MAADR0, macaddr[5]);
00154 
00155     // no loopback of transmitted frames
00156     phyWrite(PHCON2, PHCON2_HDLDIS);
00157 
00158     // switch to bank 0
00159     setBank(ECON1);
00160 
00161     // enable interrutps
00162     writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);
00163 
00164     // enable packet reception
00165     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00166 
00167     //Configure leds
00168     phyWrite(PHLCON, 0x476);
00169 }
00170 
00171 /**
00172  * @brief
00173  * @note
00174  * @param
00175  * @retval
00176  */
00177 memhandle Enc28j60Eth::receivePacket()
00178 {
00179     uint8_t     rxstat;
00180     uint16_t    len;
00181     // check if a packet has been received and buffered
00182     //if( !(readReg(EIR) & EIR_PKTIF) ){
00183     // The above does not work. See Rev. B4 Silicon Errata point 6.
00184     if (readReg(EPKTCNT) != 0) {
00185         uint16_t    readPtr = nextPacketPtr +
00186             6 > RXEND_INIT ? nextPacketPtr +
00187             6 -
00188             RXEND_INIT +
00189             RXSTART_INIT : nextPacketPtr +
00190             6;
00191         // Set the read pointer to the start of the received packet
00192         writeRegPair(ERDPTL, nextPacketPtr);
00193 
00194         // read the next packet pointer
00195         nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0);
00196         nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00197 
00198         // read the packet length (see datasheet page 43)
00199         len = readOp(ENC28J60_READ_BUF_MEM, 0);
00200         len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00201         len -= 4;   //remove the CRC count
00202         // read the receive status (see datasheet page 43)
00203         rxstat = readOp(ENC28J60_READ_BUF_MEM, 0);
00204 
00205         //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8;
00206 #ifdef ENC28J60DEBUG
00207         printf
00208         (
00209             "receivePacket [%d-%d], next: %d, stat: %d, count: %d -> ",
00210             readPtr,
00211             (readPtr + len) % (RXEND_INIT + 1),
00212             nextPacketPtr,
00213             rxstat,
00214             readReg(EPKTCNT)
00215         );
00216         (rxstat & 0x80) != 0 ? printf("OK") : printf("failed");
00217         printf("\r\n");
00218 #endif
00219         // decrement the packet counter indicate we are done with this packet
00220 
00221         writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
00222 
00223         // check CRC and symbol errors (see datasheet page 44, table 7-3):
00224         // The ERXFCON.CRCEN is set by default. Normally we should not
00225         // need to check this.
00226         if ((rxstat & 0x80) != 0) {
00227             receivePkt.begin = readPtr;
00228             receivePkt.size = len;
00229             return UIP_RECEIVEBUFFERHANDLE;
00230         }
00231 
00232         // Move the RX read pointer to the start of the next received packet
00233         // This frees the memory we just read out
00234         setERXRDPT();
00235     }
00236 
00237     return(NOBLOCK);
00238 }
00239 
00240 /**
00241  * @brief
00242  * @note
00243  * @param
00244  * @retval
00245  */
00246 void Enc28j60Eth::setERXRDPT()
00247 {
00248     writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXEND_INIT : nextPacketPtr - 1);
00249 }
00250 
00251 /**
00252  * @brief
00253  * @note
00254  * @param
00255  * @retval
00256  */
00257 size_t Enc28j60Eth::blockSize(memhandle handle)
00258 {
00259     return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size;
00260 }
00261 
00262 /**
00263  * @brief
00264  * @note
00265  * @param
00266  * @retval
00267  */
00268 void Enc28j60Eth::sendPacket(memhandle handle)
00269 {
00270     memblock*   packet = &blocks[handle];
00271     uint16_t    start = packet->begin - 1;
00272     uint16_t    end = start + packet->size;
00273 
00274     // backup data at control-byte position
00275     uint8_t     data = readByte(start);
00276     // write control-byte (if not 0 anyway)
00277     if (data)
00278         writeByte(start, 0);
00279 
00280 #ifdef ENC28J60DEBUG
00281     printf("sendPacket(%d) [%d-%d]: ", handle, start, end);
00282     for (uint16_t i = start; i <= end; i++) {
00283         printf("%d ", readByte(i));
00284     }
00285 
00286     printf("\r\n");
00287 #endif
00288     // TX start
00289 
00290     writeRegPair(ETXSTL, start);
00291 
00292     // Set the TXND pointer to correspond to the packet size given
00293     writeRegPair(ETXNDL, end);
00294 
00295     // send the contents of the transmit buffer onto the network
00296     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
00297 
00298     // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
00299     if ((readReg(EIR) & EIR_TXERIF)) {
00300         writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
00301     }
00302 
00303     //restore data on control-byte position
00304     if (data)
00305         writeByte(start, data);
00306 }
00307 
00308 /**
00309  * @brief
00310  * @note
00311  * @param
00312  * @retval
00313  */
00314 uint16_t Enc28j60Eth::setReadPtr(memhandle handle, memaddress position, uint16_t len)
00315 {
00316     memblock*   packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle];
00317     memaddress  start = handle == UIP_RECEIVEBUFFERHANDLE &&
00318         packet->begin +
00319         position > RXEND_INIT ? packet->begin +
00320         position -
00321         RXEND_INIT +
00322         RXSTART_INIT : packet->begin +
00323         position;
00324 
00325     writeRegPair(ERDPTL, start);
00326 
00327     if (len > packet->size - position)
00328         len = packet->size - position;
00329     return len;
00330 }
00331 
00332 /**
00333  * @brief
00334  * @note
00335  * @param
00336  * @retval
00337  */
00338 uint16_t Enc28j60Eth::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
00339 {
00340     len = setReadPtr(handle, position, len);
00341     readBuffer(len, buffer);
00342     return len;
00343 }
00344 
00345 /**
00346  * @brief
00347  * @note
00348  * @param
00349  * @retval
00350  */
00351 uint16_t Enc28j60Eth::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len)
00352 {
00353     memblock*   packet = &blocks[handle];
00354     uint16_t    start = packet->begin + position;
00355 
00356     writeRegPair(EWRPTL, start);
00357 
00358     if (len > packet->size - position)
00359         len = packet->size - position;
00360     writeBuffer(len, buffer);
00361     return len;
00362 }
00363 
00364 /**
00365  * @brief
00366  * @note
00367  * @param
00368  * @retval
00369  */
00370 uint8_t Enc28j60Eth::readByte(uint16_t addr)
00371 {
00372     uint8_t result;
00373 
00374     writeRegPair(ERDPTL, addr);
00375 
00376     _cs = 0;
00377 
00378     // issue read command
00379     _spi.write(ENC28J60_READ_BUF_MEM);
00380 
00381     // read data
00382     result = _spi.write(0x00);
00383     
00384     _cs = 1;
00385     
00386     return(result);
00387 }
00388 
00389 /**
00390  * @brief
00391  * @note
00392  * @param
00393  * @retval
00394  */
00395 void Enc28j60Eth::writeByte(uint16_t addr, uint8_t data)
00396 {
00397     writeRegPair(EWRPTL, addr);
00398 
00399     _cs = 0;
00400 
00401     // issue write command
00402     _spi.write(ENC28J60_WRITE_BUF_MEM);
00403 
00404     // write data
00405     _spi.write(data);
00406     
00407     _cs = 1;
00408 }
00409 
00410 /**
00411  * @brief
00412  * @note
00413  * @param
00414  * @retval
00415  */
00416 void Enc28j60Eth::copyPacket
00417 (
00418     memhandle   dest_pkt,
00419     memaddress  dest_pos,
00420     memhandle   src_pkt,
00421     memaddress  src_pos,
00422     uint16_t    len
00423 )
00424 {
00425     memblock*   dest = &blocks[dest_pkt];
00426     memblock*   src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt];
00427     memaddress  start = src_pkt == UIP_RECEIVEBUFFERHANDLE &&
00428         src->begin +
00429         src_pos > RXEND_INIT ? src->begin +
00430         src_pos -
00431         RXEND_INIT +
00432         RXSTART_INIT : src->begin +
00433         src_pos;
00434     enc28j60_mempool_block_move_callback(dest->begin + dest_pos, start, len);
00435 
00436     // Move the RX read pointer to the start of the next received packet
00437     // This frees the memory we just read out
00438     //setERXRDPT();
00439 }
00440 
00441 /**
00442  * @brief
00443  * @note
00444  * @param
00445  * @retval
00446  */
00447 void Enc28j60Eth::freePacket()
00448 {
00449     setERXRDPT();
00450 }
00451 
00452 /**
00453  * @brief
00454  * @note
00455  * @param
00456  * @retval
00457  */
00458 uint8_t Enc28j60Eth::readOp(uint8_t op, uint8_t address)
00459 {
00460     uint8_t result;
00461 
00462     _cs = 0;
00463 
00464     // issue read command
00465     _spi.write(op | (address & ADDR_MASK));
00466 
00467     // read data
00468     result = _spi.write(0x00);
00469 
00470     // do dummy read if needed (for mac and mii, see datasheet page 29)
00471     if (address & 0x80)
00472         result = _spi.write(0x00);
00473 
00474     _cs = 1;
00475     return(result);
00476 }
00477 
00478 /**
00479  * @brief
00480  * @note
00481  * @param
00482  * @retval
00483  */
00484 void Enc28j60Eth::writeOp(uint8_t op, uint8_t address, uint8_t data)
00485 {
00486     _cs = 0;
00487 
00488     // issue write command
00489     _spi.write(op | (address & ADDR_MASK));
00490 
00491     // write data
00492     _spi.write(data);
00493     
00494     _cs = 1;
00495 }
00496 
00497 /**
00498  * @brief
00499  * @note
00500  * @param
00501  * @retval
00502  */
00503 void Enc28j60Eth::readBuffer(uint16_t len, uint8_t* data)
00504 {
00505     _cs = 0;
00506 
00507     // issue read command
00508     _spi.write(ENC28J60_READ_BUF_MEM);
00509  
00510     // read data
00511     while (len) {
00512         len--;
00513         *data = _spi.write(0x00);
00514         data++;
00515     }
00516 
00517     *data = '\0';
00518     
00519     _cs = 1;
00520 }
00521 
00522 /**
00523  * @brief
00524  * @note
00525  * @param
00526  * @retval
00527  */
00528 void Enc28j60Eth::writeBuffer(uint16_t len, uint8_t* data)
00529 {
00530     _cs = 0;
00531 
00532     // issue write command
00533     _spi.write(ENC28J60_WRITE_BUF_MEM);
00534 
00535     // write data
00536     while (len) {
00537         len--;
00538         _spi.write(*data);
00539         data++;
00540     }
00541 
00542     _cs = 1;
00543 }
00544 
00545 /**
00546  * @brief
00547  * @note
00548  * @param
00549  * @retval
00550  */
00551 void Enc28j60Eth::setBank(uint8_t address)
00552 {
00553     // set the bank (if needed)
00554     if ((address & BANK_MASK) != bank) {
00555         // set the bank
00556         writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));
00557         writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);
00558         bank = (address & BANK_MASK);
00559     }
00560 }
00561 
00562 /**
00563  * @brief
00564  * @note
00565  * @param
00566  * @retval
00567  */
00568 uint8_t Enc28j60Eth::readReg(uint8_t address)
00569 {
00570     // set the bank
00571     setBank(address);
00572 
00573     // do the read
00574     return readOp(ENC28J60_READ_CTRL_REG, address);
00575 }
00576 
00577 /**
00578  * @brief
00579  * @note
00580  * @param
00581  * @retval
00582  */
00583 void Enc28j60Eth::writeReg(uint8_t address, uint8_t data)
00584 {
00585     // set the bank
00586     setBank(address);
00587 
00588     // do the write
00589     writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
00590 }
00591 
00592 /**
00593  * @brief
00594  * @note
00595  * @param
00596  * @retval
00597  */
00598 void Enc28j60Eth::writeRegPair(uint8_t address, uint16_t data)
00599 {
00600     // set the bank
00601     setBank(address);
00602 
00603     // do the write
00604     writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF));
00605     writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8);
00606 }
00607 
00608 /**
00609  * @brief
00610  * @note
00611  * @param
00612  * @retval
00613  */
00614 void Enc28j60Eth::phyWrite(uint8_t address, uint16_t data)
00615 {
00616     // set the PHY register address
00617     writeReg(MIREGADR, address);
00618 
00619     // write the PHY data
00620     writeRegPair(MIWRL, data);
00621 
00622     // wait until the PHY write completes
00623     while (readReg(MISTAT) & MISTAT_BUSY) {
00624         wait_us(15);
00625     }
00626 }
00627 
00628 /**
00629  * @brief
00630  * @note
00631  * @param
00632  * @retval
00633  */
00634 uint16_t Enc28j60Eth::phyRead(uint8_t address)
00635 {
00636     writeReg(MIREGADR, address);
00637     writeReg(MICMD, MICMD_MIIRD);
00638 
00639     // wait until the PHY read completes
00640     while (readReg(MISTAT) & MISTAT_BUSY) {
00641         wait_us(15);
00642     }   //and MIRDH
00643 
00644     writeReg(MICMD, 0);
00645     return(readReg(MIRDL) | readReg(MIRDH) << 8);
00646 }
00647 
00648 /**
00649  * @brief
00650  * @note
00651  * @param
00652  * @retval
00653  */
00654 void Enc28j60Eth::clkout(uint8_t clk)
00655 {
00656     //setup clkout: 2 is 12.5MHz:
00657     writeReg(ECOCON, clk & 0x7);
00658 }
00659 
00660 // read the revision of the chip:
00661 uint8_t Enc28j60Eth::getrev()
00662 {
00663     return(readReg(EREVID));
00664 }
00665 
00666 /**
00667  * @brief
00668  * @note
00669  * @param
00670  * @retval
00671  */
00672 uint16_t Enc28j60Eth::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len)
00673 {
00674     uint8_t     spdr;
00675     uint16_t    t;
00676     uint16_t    i;
00677 
00678     len = setReadPtr(handle, pos, len) - 1;
00679     _cs = 0;
00680 
00681     // issue read command
00682     spdr = _spi.write(ENC28J60_READ_BUF_MEM);
00683     for (i = 0; i < len; i += 2) {
00684         // read data
00685         spdr = _spi.write(0x00);
00686         t = spdr << 8;
00687         spdr = _spi.write(0x00);
00688         t += spdr;
00689         sum += t;
00690         if (sum < t) {
00691             sum++;  /* carry */
00692         }
00693     }
00694 
00695     if (i == len) {
00696         spdr = _spi.write(0x00);
00697         t = (spdr << 8) + 0;
00698         sum += t;
00699         if (sum < t) {
00700             sum++;  /* carry */
00701         }
00702     }
00703 
00704     _cs = 1;
00705 
00706     /* Return sum in host byte order. */
00707     return sum;
00708 }
00709 
00710 /**
00711  * @brief
00712  * @note
00713  * @param
00714  * @retval
00715  */
00716 void Enc28j60Eth::powerOff()
00717 {
00718     writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN);
00719 #if MBED_MAJOR_VERSION == 2
00720     wait_ms(50);
00721 #else
00722     thread_sleep_for(50);
00723 #endif
00724     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS);
00725 #if MBED_MAJOR_VERSION == 2
00726     wait_ms(50);
00727 #else
00728     thread_sleep_for(50);
00729 #endif
00730     writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV);
00731 }
00732 
00733 /**
00734  * @brief
00735  * @note
00736  * @param
00737  * @retval
00738  */
00739 void Enc28j60Eth::powerOn()
00740 {
00741     writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV);
00742 #if MBED_MAJOR_VERSION == 2
00743     wait_ms(50);
00744 #else
00745     thread_sleep_for(50);
00746 #endif
00747     writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00748 #if MBED_MAJOR_VERSION == 2
00749     wait_ms(50);
00750 #else
00751     thread_sleep_for(50);
00752 #endif
00753 }
00754 
00755 /**
00756  * @brief
00757  * @note
00758  * @param
00759  * @retval
00760  */
00761 bool Enc28j60Eth::linkStatus()
00762 {
00763     return(phyRead(PHSTAT2) & 0x0400) > 0;
00764 }