uIP 1.0 based webserver for LPC1114 + ENC28J60

Dependencies:   mbed TMP102

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers enc28j60.cpp Source File

enc28j60.cpp

00001 #include "mbed.h"
00002 
00003 #include "enc28j60.h"
00004 #include "uip-conf.h"
00005 
00006 u8 Enc28j60Bank;
00007 u16 NextPacketPtr;
00008 
00009 ENC28J60::ENC28J60(SPI* _spi, PinName _cs, PinName _int):
00010     cs_pin(_cs), int_pin(_int)
00011 {
00012     this->spi = _spi;
00013     
00014     this->spi->format(8,0);
00015     this->spi->frequency(8000000);
00016 
00017     cs_pin = 1;
00018 }
00019 
00020 u8 ENC28J60::readOp(u8 op, u8 address)
00021 {
00022     u8 data;
00023    
00024     // assert CS
00025     cs_pin = 0;
00026 
00027     // issue read command
00028     spi->write(op | (address & ADDR_MASK));
00029     // read data
00030     data = spi->write(0x00);
00031     // do dummy read if needed
00032     if(address & 0x80)
00033     {
00034         data = spi->write(0x00);
00035     }
00036 
00037     // release CS
00038     cs_pin = 1;
00039 
00040     return data;
00041 }
00042 
00043 void ENC28J60::writeOp(u8 op, u8 address, u8 data)
00044 {
00045     // assert CS
00046     cs_pin = 0;
00047 
00048     // issue write command
00049     spi->write(op | (address & ADDR_MASK));
00050     // write data
00051     spi->write(data);
00052 
00053     // release CS
00054     cs_pin = 1;
00055 }
00056 
00057 void ENC28J60::readBuffer(u16 len, u8* data)
00058 {
00059     // assert CS
00060     cs_pin = 0;
00061 
00062     // issue read command
00063     spi->write(ENC28J60_READ_BUF_MEM);
00064     while(len--)
00065     {
00066         // read data
00067         *data++ = spi->write(0x00);
00068     }
00069 
00070     // release CS
00071     cs_pin = 1;
00072 }
00073 
00074 void ENC28J60::writeBuffer(u16 len, u8* data)
00075 {
00076     // assert CS
00077     cs_pin = 0;
00078 
00079     // issue write command
00080     spi->write(ENC28J60_WRITE_BUF_MEM);
00081     while(len--)
00082     {
00083         // write data
00084         spi->write(*data++);
00085     }
00086     
00087     // release CS
00088     cs_pin = 1;
00089 }
00090 
00091 void ENC28J60::setBank(u8 address)
00092 {
00093     // set the bank (if needed)
00094     if((address & BANK_MASK) != Enc28j60Bank)
00095     {
00096         // set the bank
00097         this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
00098         this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
00099         Enc28j60Bank = (address & BANK_MASK);
00100     }
00101 }
00102 
00103 u8 ENC28J60::read(u8 address)
00104 {
00105     // set the bank
00106     this->setBank(address);
00107     // do the read
00108     return this->readOp(ENC28J60_READ_CTRL_REG, address);
00109 }
00110 
00111 void ENC28J60::write(u8 address, u8 data)
00112 {
00113     // set the bank
00114     this->setBank(address);
00115     // do the write
00116     this->writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
00117 }
00118 
00119 u16 ENC28J60::phyRead(u8 address)
00120 {
00121     u16 data;
00122 
00123     // Set the right address and start the register read operation
00124     this->write(MIREGADR, address);
00125     this->write(MICMD, MICMD_MIIRD);
00126 
00127     // wait until the PHY read completes
00128     while(this->read(MISTAT) & MISTAT_BUSY);
00129 
00130     // quit reading
00131     this->write(MICMD, 0x00);
00132     
00133     // get data value
00134     data  = this->read(MIRDL);
00135     data |= this->read(MIRDH);
00136     // return the data
00137     return data;
00138 }
00139 
00140 void ENC28J60::phyWrite(u8 address, u16 data)
00141 {
00142     // set the PHY register address
00143     this->write(MIREGADR, address);
00144     
00145     // write the PHY data
00146     this->write(MIWRL, data);   
00147     this->write(MIWRH, data>>8);
00148 
00149     // wait until the PHY write completes
00150     while(this->read(MISTAT) & MISTAT_BUSY);
00151 }
00152 
00153 void ENC28J60::init(void)
00154 {
00155     cs_pin = 1;         //Disable CS
00156     
00157     // perform system reset
00158     this->writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
00159     // check CLKRDY bit to see if reset is complete
00160     /* Fix Errata */
00161     wait_ms(1);
00162     while(!(this->read(ESTAT) & ESTAT_CLKRDY));
00163 
00164     // do bank 0 stuff
00165     // initialize receive buffer
00166     // 16-bit transfers, must write low byte first
00167     // set receive buffer start address
00168     NextPacketPtr = RXSTART_INIT;
00169     this->write(ERXSTL, RXSTART_INIT&0xFF);
00170     this->write(ERXSTH, RXSTART_INIT>>8);
00171     // set read pointer address
00172     //this->write(ERDPTL, 0);
00173     //this->write(ERDPTH, 0);
00174     // set receive pointer address
00175     this->write(ERXRDPTL, RXSTART_INIT&0xFF);
00176     this->write(ERXRDPTH, RXSTART_INIT>>8);
00177     // set receive buffer end
00178     // ERXND defaults to 0x1FFF (end of ram)
00179     this->write(ERXNDL, RXSTOP_INIT&0xFF);
00180     this->write(ERXNDH, RXSTOP_INIT>>8);
00181     // set transmit buffer start
00182     // ETXST defaults to 0x0000 (beginnging of ram)
00183     this->write(ETXSTL, TXSTART_INIT&0xFF);
00184     this->write(ETXSTH, TXSTART_INIT>>8);
00185 
00186     // do bank 2 stuff
00187     // enable MAC receive
00188     this->write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
00189     // bring MAC out of reset
00190     this->write(MACON2, 0x00);
00191     // enable automatic padding and CRC operations
00192     this->writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
00193 //  this->write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
00194     // set inter-frame gap (non-back-to-back)
00195     this->write(MAIPGL, 0x12);
00196     this->write(MAIPGH, 0x0C);
00197     // set inter-frame gap (back-to-back)
00198     this->write(MABBIPG, 0x12);
00199     // Set the maximum packet size which the controller will accept
00200     this->write(MAMXFLL, MAX_FRAMELEN&0xFF);    
00201     this->write(MAMXFLH, MAX_FRAMELEN>>8);
00202 
00203     // do bank 3 stuff
00204     // write MAC address
00205     // NOTE: MAC address in ENC28J60 is byte-backward
00206     this->write(MAADR5, UIP_ETHADDR0);
00207     this->write(MAADR4, UIP_ETHADDR1);
00208     this->write(MAADR3, UIP_ETHADDR2);
00209     this->write(MAADR2, UIP_ETHADDR3);
00210     this->write(MAADR1, UIP_ETHADDR4);
00211     this->write(MAADR0, UIP_ETHADDR5);
00212 
00213     // no loopback of transmitted frames
00214     this->phyWrite(PHCON2, PHCON2_HDLDIS);
00215 
00216     // switch to bank 0
00217     this->setBank(ECON1);
00218     // enable interrutps
00219     this->writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
00220     // enable packet reception
00221     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00222 /*
00223     this->phyWrite(PHLCON, 0x0AA2);
00224 
00225     // setup duplex ----------------------
00226 
00227     // Disable receive logic and abort any packets currently being transmitted
00228     this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS|ECON1_RXEN);
00229     
00230     {
00231         u16 temp;
00232         // Set the PHY to the proper duplex mode
00233         temp = enc28j60PhyRead(PHCON1);
00234         temp &= ~PHCON1_PDPXMD;
00235         this->phyWrite(PHCON1, temp);
00236         // Set the MAC to the proper duplex mode
00237         temp = this->read(MACON3);
00238         temp &= ~MACON3_FULDPX;
00239         this->write(MACON3, temp);
00240     }
00241 
00242     // Set the back-to-back inter-packet gap time to IEEE specified 
00243     // requirements.  The meaning of the MABBIPG value changes with the duplex
00244     // state, so it must be updated in this function.
00245     // In full duplex, 0x15 represents 9.6us; 0x12 is 9.6us in half duplex
00246     //this->write(MABBIPG, DuplexState ? 0x15 : 0x12);  
00247     
00248     // Reenable receive logic
00249     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
00250 
00251     // setup duplex ----------------------
00252 */
00253 }
00254 
00255 void ENC28J60::packetSend(unsigned int len, unsigned char* packet)
00256 {
00257     //Errata: Transmit Logic reset
00258     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
00259     wait_us(10);
00260     this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
00261 
00262     // Set the write pointer to start of transmit buffer area
00263     this->write(EWRPTL, TXSTART_INIT);
00264     this->write(EWRPTH, TXSTART_INIT>>8);
00265     // Set the TXND pointer to correspond to the packet size given
00266     this->write(ETXNDL, (TXSTART_INIT+len));
00267     this->write(ETXNDH, (TXSTART_INIT+len)>>8);
00268 
00269     // write per-packet control byte
00270     this->writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
00271 
00272     // copy the packet into the transmit buffer
00273     this->writeBuffer(len, packet);
00274     
00275     // send the contents of the transmit buffer onto the network
00276     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
00277     
00278     while(this->readOp(ENC28J60_BIT_FIELD_SET, ECON1) & ECON1_TXRTS)
00279     {
00280         wait_us(10);
00281     }
00282 }
00283 
00284 void ENC28J60::packetSend2(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2)
00285 {
00286     //Errata: Transmit Logic reset
00287     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
00288     this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
00289 
00290     // Set the write pointer to start of transmit buffer area
00291     this->write(EWRPTL, TXSTART_INIT);
00292     this->write(EWRPTH, TXSTART_INIT>>8);
00293     // Set the TXND pointer to correspond to the packet size given
00294     this->write(ETXNDL, (TXSTART_INIT+len1+len2));
00295     this->write(ETXNDH, (TXSTART_INIT+len1+len2)>>8);
00296 
00297     // write per-packet control byte
00298     this->writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
00299 
00300     // copy the packet into the transmit buffer
00301     this->writeBuffer(len1, packet1);
00302     if(len2>0) this->writeBuffer(len2, packet2);
00303     
00304     // send the contents of the transmit buffer onto the network
00305     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
00306 }
00307 
00308 unsigned int ENC28J60::packetReceive(unsigned int maxlen, unsigned char* packet)
00309 {
00310     u16 rxstat;
00311     u16 len;
00312 
00313     // check if a packet has been received and buffered
00314     if( !(this->read(EIR) & EIR_PKTIF) )
00315     {
00316         if(this->read(EPKTCNT) == 0)
00317         {
00318             return 0;
00319         }
00320     }
00321     
00322     // Make absolutely certain that any previous packet was discarded   
00323     //if( WasDiscarded == FALSE)
00324     //  MACDiscardRx();
00325 
00326     // Set the read pointer to the start of the received packet
00327     this->write(ERDPTL, (NextPacketPtr));
00328     this->write(ERDPTH, (NextPacketPtr)>>8);
00329     // read the next packet pointer
00330     NextPacketPtr  = this->readOp(ENC28J60_READ_BUF_MEM, 0);
00331     NextPacketPtr |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8;
00332     // read the packet length
00333     len  = this->readOp(ENC28J60_READ_BUF_MEM, 0);
00334     len |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8;
00335     // read the receive status
00336     rxstat  = this->readOp(ENC28J60_READ_BUF_MEM, 0);
00337     rxstat |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8;
00338 
00339     // limit retrieve length
00340     // (we reduce the MAC-reported length by 4 to remove the CRC)
00341     if(len>maxlen){
00342         len=maxlen;
00343     }
00344 
00345     // copy the packet from the receive buffer
00346     this->readBuffer(len, packet);
00347 
00348     // Move the RX read pointer to the start of the next received packet
00349     // This frees the memory we just read out
00350     /* Fix Errata */
00351     if(NextPacketPtr == RXSTART_INIT)
00352     {
00353         this->write(ERXRDPTL, (RXSTOP_INIT));
00354         this->write(ERXRDPTH, (RXSTOP_INIT)>>8);
00355     }
00356     else
00357     {
00358         this->write(ERXRDPTL, (NextPacketPtr));
00359         this->write(ERXRDPTH, (NextPacketPtr)>>8);
00360     }
00361 
00362     // decrement the packet counter indicate we are done with this packet
00363     this->writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
00364     wait_us(11);
00365 
00366     return len;
00367 }
00368 
00369 void ENC28J60::receiveOverflowRecover(void)
00370 {
00371     // receive buffer overflow handling procedure
00372 
00373     // recovery completed
00374 }
00375 
00376 void ENC28J60::regDump(void)
00377 {
00378     printf("RevID: 0x%x\n", this->read(EREVID));
00379 
00380     printf("Ctrl: ");
00381     printf("ECON1=%x ",this->read(ECON1));
00382     printf("ECON2=%x ",this->read(ECON2));
00383     printf("ESTAT=%x ",this->read(ESTAT));
00384     printf("EIR=%x ",this->read(EIR));
00385     printf("EIE=%x\n",this->read(EIE));
00386 
00387     printf("MAC:  ");
00388     printf("MACON1=%x ",this->read(MACON1));
00389     printf("MACON2=%x ",this->read(MACON2));
00390     printf("MACON3=%x ",this->read(MACON3));
00391     printf("MACON4=%x ",this->read(MACON4));
00392     printf("MAD=%x%x\n",
00393         this->read(MAADR5)*0x1000000+this->read(MAADR4)*0x10000+this->read(MAADR3)*0x100+this->read(MAADR2),
00394         this->read(MAADR1)*0x1000000+this->read(MAADR0)*0x10000+0xffff);
00395 
00396     printf("Rx:   ");
00397     printf("ERXST=%04x ",this->read(ERXSTH)*0x100+this->read(ERXSTL));
00398     printf("ERXND=%04x ",this->read(ERXNDH)*0x100+this->read(ERXNDL));
00399     printf("ERXWRPT=%x ",this->read(ERXWRPTH)*0x100+this->read(ERXWRPTL));
00400     printf("ERXRDPT=%x ",this->read(ERXRDPTH)*0x100+this->read(ERXRDPTL));
00401     printf("ERXFCON=%x ",this->read(ERXFCON));
00402     printf("EPKTCNT=%x ",this->read(EPKTCNT));
00403     printf("MAMXFL=%x\n",this->read(MAMXFLH)*0x100+this->read(MAMXFLL));
00404 
00405     printf("Tx:   ");
00406     printf("ETXST=%04x ",this->read(ETXSTH)*0x100+this->read(ETXSTL));
00407     printf("ETXND=%04x ",this->read(ETXNDH)*0x100+this->read(ETXNDL));
00408     printf("MACLCON1=%x ",this->read(MACLCON1));
00409     printf("MACLCON2=%x ",this->read(MACLCON2));
00410     printf("MAPHSUP=%x\n",this->read(MAPHSUP));
00411 }