ban4jp -
/
uIP-1-0_webserver
uIP 1.0 based webserver for LPC1114 + ENC28J60
Diff: dev-enc28j60/enc28j60.cpp
- Revision:
- 0:685224d2f66d
- Child:
- 1:b4d28172cacd
diff -r 000000000000 -r 685224d2f66d dev-enc28j60/enc28j60.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev-enc28j60/enc28j60.cpp Sat Jun 14 16:02:21 2014 +0000 @@ -0,0 +1,386 @@ +#include "mbed.h" + +#include "enc28j60.h" +#include "uip-conf.h" + +u8 Enc28j60Bank; +u16 NextPacketPtr; + +ENC28J60::ENC28J60(SPI* _spi, PinName _cs, PinName _int): + cs_pin(_cs), int_pin(_int) +{ + this->spi = _spi; + + this->spi->format(8,0); + this->spi->frequency(8000000); + + cs_pin = 1; +} + +u8 ENC28J60::readOp(u8 op, u8 address) +{ + u8 data; + + // assert CS + cs_pin = 0; + + // issue read command + spi->write(op | (address & ADDR_MASK)); + // read data + data = spi->write(0x00); + // do dummy read if needed + if(address & 0x80) + { + data = spi->write(0x00); + } + + // release CS + cs_pin = 1; + + return data; +} + +void ENC28J60::writeOp(u8 op, u8 address, u8 data) +{ + // assert CS + cs_pin = 0; + + // issue write command + spi->write(op | (address & ADDR_MASK)); + // write data + spi->write(data); + + // release CS + cs_pin = 1; +} + +void ENC28J60::readBuffer(u16 len, u8* data) +{ + // assert CS + cs_pin = 0; + + // issue read command + spi->write(ENC28J60_READ_BUF_MEM); + while(len--) + { + // read data + *data++ = spi->write(0x00); + } + + // release CS + cs_pin = 1; +} + +void ENC28J60::writeBuffer(u16 len, u8* data) +{ + // assert CS + cs_pin = 0; + + // issue write command + spi->write(ENC28J60_WRITE_BUF_MEM); + while(len--) + { + // write data + spi->write(*data++); + } + + // release CS + cs_pin = 1; +} + +void ENC28J60::setBank(u8 address) +{ + // set the bank (if needed) + if((address & BANK_MASK) != Enc28j60Bank) + { + // set the bank + this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); + Enc28j60Bank = (address & BANK_MASK); + } +} + +u8 ENC28J60::read(u8 address) +{ + // set the bank + this->setBank(address); + // do the read + return this->readOp(ENC28J60_READ_CTRL_REG, address); +} + +void ENC28J60::write(u8 address, u8 data) +{ + // set the bank + this->setBank(address); + // do the write + this->writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +u16 ENC28J60::phyRead(u8 address) +{ + u16 data; + + // Set the right address and start the register read operation + this->write(MIREGADR, address); + this->write(MICMD, MICMD_MIIRD); + + // wait until the PHY read completes + while(this->read(MISTAT) & MISTAT_BUSY); + + // quit reading + this->write(MICMD, 0x00); + + // get data value + data = this->read(MIRDL); + data |= this->read(MIRDH); + // return the data + return data; +} + +void ENC28J60::phyWrite(u8 address, u16 data) +{ + // set the PHY register address + this->write(MIREGADR, address); + + // write the PHY data + this->write(MIWRL, data); + this->write(MIWRH, data>>8); + + // wait until the PHY write completes + while(this->read(MISTAT) & MISTAT_BUSY); +} + +void ENC28J60::init(void) +{ + cs_pin = 1; //Disable CS + + // perform system reset + this->writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + // check CLKRDY bit to see if reset is complete + wait_us(50); + while(!(this->read(ESTAT) & ESTAT_CLKRDY)); + + // do bank 0 stuff + // initialize receive buffer + // 16-bit transfers, must write low byte first + // set receive buffer start address + NextPacketPtr = RXSTART_INIT; + this->write(ERXSTL, RXSTART_INIT&0xFF); + this->write(ERXSTH, RXSTART_INIT>>8); + // set receive pointer address + this->write(ERXRDPTL, RXSTART_INIT&0xFF); + this->write(ERXRDPTH, RXSTART_INIT>>8); + // set receive buffer end + // ERXND defaults to 0x1FFF (end of ram) + this->write(ERXNDL, RXSTOP_INIT&0xFF); + this->write(ERXNDH, RXSTOP_INIT>>8); + // set transmit buffer start + // ETXST defaults to 0x0000 (beginnging of ram) + this->write(ETXSTL, TXSTART_INIT&0xFF); + this->write(ETXSTH, TXSTART_INIT>>8); + + // do bank 2 stuff + // enable MAC receive + this->write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); + // bring MAC out of reset + this->write(MACON2, 0x00); + // enable automatic padding and CRC operations + this->writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); +// this->write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); + // set inter-frame gap (non-back-to-back) + this->write(MAIPGL, 0x12); + this->write(MAIPGH, 0x0C); + // set inter-frame gap (back-to-back) + this->write(MABBIPG, 0x12); + // Set the maximum packet size which the controller will accept + this->write(MAMXFLL, MAX_FRAMELEN&0xFF); + this->write(MAMXFLH, MAX_FRAMELEN>>8); + + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + this->write(MAADR5, UIP_ETHADDR0); + this->write(MAADR4, UIP_ETHADDR1); + this->write(MAADR3, UIP_ETHADDR2); + this->write(MAADR2, UIP_ETHADDR3); + this->write(MAADR1, UIP_ETHADDR4); + this->write(MAADR0, UIP_ETHADDR5); + + // no loopback of transmitted frames + this->phyWrite(PHCON2, PHCON2_HDLDIS); + + // switch to bank 0 + this->setBank(ECON1); + // enable interrutps + this->writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); + // enable packet reception + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); +/* + this->phyWrite(PHLCON, 0x0AA2); + + // setup duplex ---------------------- + + // Disable receive logic and abort any packets currently being transmitted + this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS|ECON1_RXEN); + + { + u16 temp; + // Set the PHY to the proper duplex mode + temp = enc28j60PhyRead(PHCON1); + temp &= ~PHCON1_PDPXMD; + this->phyWrite(PHCON1, temp); + // Set the MAC to the proper duplex mode + temp = this->read(MACON3); + temp &= ~MACON3_FULDPX; + this->write(MACON3, temp); + } + + // Set the back-to-back inter-packet gap time to IEEE specified + // requirements. The meaning of the MABBIPG value changes with the duplex + // state, so it must be updated in this function. + // In full duplex, 0x15 represents 9.6us; 0x12 is 9.6us in half duplex + //this->write(MABBIPG, DuplexState ? 0x15 : 0x12); + + // Reenable receive logic + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + + // setup duplex ---------------------- +*/ +} + +void ENC28J60::packetSend(unsigned int len, unsigned char* packet) +{ + //Errata: Transmit Logic reset + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); + this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + + // Set the write pointer to start of transmit buffer area + this->write(EWRPTL, TXSTART_INIT); + this->write(EWRPTH, TXSTART_INIT>>8); + // Set the TXND pointer to correspond to the packet size given + this->write(ETXNDL, (TXSTART_INIT+len)); + this->write(ETXNDH, (TXSTART_INIT+len)>>8); + + // write per-packet control byte + this->writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); + + // copy the packet into the transmit buffer + this->writeBuffer(len, packet); + + // send the contents of the transmit buffer onto the network + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); +} + +void ENC28J60::packetSend2(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2) +{ + //Errata: Transmit Logic reset + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); + this->writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + + // Set the write pointer to start of transmit buffer area + this->write(EWRPTL, TXSTART_INIT); + this->write(EWRPTH, TXSTART_INIT>>8); + // Set the TXND pointer to correspond to the packet size given + this->write(ETXNDL, (TXSTART_INIT+len1+len2)); + this->write(ETXNDH, (TXSTART_INIT+len1+len2)>>8); + + // write per-packet control byte + this->writeOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); + + // copy the packet into the transmit buffer + this->writeBuffer(len1, packet1); + if(len2>0) this->writeBuffer(len2, packet2); + + // send the contents of the transmit buffer onto the network + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); +} + +unsigned int ENC28J60::packetReceive(unsigned int maxlen, unsigned char* packet) +{ + u16 rxstat; + u16 len; + + // check if a packet has been received and buffered + if( !(this->read(EIR) & EIR_PKTIF) ) + return 0; + + // Make absolutely certain that any previous packet was discarded + //if( WasDiscarded == FALSE) + // MACDiscardRx(); + + // Set the read pointer to the start of the received packet + this->write(ERDPTL, (NextPacketPtr)); + this->write(ERDPTH, (NextPacketPtr)>>8); + // read the next packet pointer + NextPacketPtr = this->readOp(ENC28J60_READ_BUF_MEM, 0); + NextPacketPtr |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8; + // read the packet length + len = this->readOp(ENC28J60_READ_BUF_MEM, 0); + len |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8; + // read the receive status + rxstat = this->readOp(ENC28J60_READ_BUF_MEM, 0); + rxstat |= this->readOp(ENC28J60_READ_BUF_MEM, 0)<<8; + + // limit retrieve length + // (we reduce the MAC-reported length by 4 to remove the CRC) + if(len>maxlen){ + len=maxlen; + } + + // copy the packet from the receive buffer + this->readBuffer(len, packet); + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + this->write(ERXRDPTL, (NextPacketPtr)); + this->write(ERXRDPTH, (NextPacketPtr)>>8); + + // decrement the packet counter indicate we are done with this packet + this->writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + + return len; +} + +void ENC28J60::receiveOverflowRecover(void) +{ + // receive buffer overflow handling procedure + + // recovery completed +} + +void ENC28J60::regDump(void) +{ + printf("RevID: 0x%x\r\n", this->read(EREVID)); + + printf("Cntrl:\n"); + printf("ECON1=%x ",this->read(ECON1)); + printf("ECON2=%x ",this->read(ECON2)); + printf("ESTAT=%x ",this->read(ESTAT)); + printf("EIR=%x\n",this->read(EIR)); + printf("EIE=%x\n",this->read(EIE)); + + printf("MAC:\n"); + printf("MACON1=%x ",this->read(MACON1)); + printf("MACON2=%x ",this->read(MACON2)); + printf("MACON3=%x ",this->read(MACON3)); + printf("MACON4=%x\n",this->read(MACON4)); + printf("MAD=%x%x\n", + this->read(MAADR5)*0x1000000+this->read(MAADR4)*0x10000+this->read(MAADR3)*0x100+this->read(MAADR2), + this->read(MAADR1)*0x1000000+this->read(MAADR0)*0x10000+0xffff); + + printf("Rx:\n"); + printf("ERXST=%x ",this->read(ERXSTH)*0x100+this->read(ERXSTL)); + printf("ERXND=%x ",this->read(ERXNDH)*0x100+this->read(ERXNDL)); + printf("ERXWRPT=%x ",this->read(ERXWRPTH)*0x100+this->read(ERXWRPTL)); + printf("ERXRDPT=%x\n",this->read(ERXRDPTH)*0x100+this->read(ERXRDPTL)); + printf("ERXFCON=%x ",this->read(ERXFCON)); + printf("EPKTCNT=%x ",this->read(EPKTCNT)); + printf("MAMXFL=%x ",this->read(MAMXFLH)*0x100+this->read(MAMXFLL)); + + printf("Tx:\n"); + printf("ETXST=%x ",this->read(ETXSTH)*0x100+this->read(ETXSTL)); + printf("ETXND=%x ",this->read(ETXNDH)*0x100+this->read(ETXNDL)); + printf("MACLCON1=%x ",this->read(MACLCON1)); + printf("MACLCON2=%x\n",this->read(MACLCON2)); + printf("MAPHSUP=%x\n",this->read(MAPHSUP)); +}