Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 12:52:12 by
1.7.2