ban4jp -
/
uIP-1-0_webserver
uIP 1.0 based webserver for LPC1114 + ENC28J60
dev-enc28j60/enc28j60.cpp
- Committer:
- ban4jp
- Date:
- 2014-06-15
- Revision:
- 1:b4d28172cacd
- Parent:
- 0:685224d2f66d
- Child:
- 3:a2715e9c7737
File content as of revision 1:b4d28172cacd:
#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\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)); }