uIP 1.0 based webserver for LPC1114 + ENC28J60

Dependencies:   mbed TMP102

Revision:
0:685224d2f66d
Child:
1:b4d28172cacd
--- /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));
+}