unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet) { u16 rxstat; u16 len; uint8_t nPktCnt = enc28j60Read(EPKTCNT); // check if a packet has been received and buffered if( !(enc28j60Read(EIR) & EIR_PKTIF) ) { // ENC28J60 Rev. B7 Silicon Errata workaround #4, PKTIF is not reliable // double check by looking at EPKTCNT if (nPktCnt == 0) { return 0; } } // Set the read pointer to the start of the received packet enc28j60Write(ERDPTL, (NextPacketPtr)); enc28j60Write(ERDPTH, (NextPacketPtr)>>8); // read the next packet pointer NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; // read the packet length len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; // read the receive status rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; // limit retrieve length // When len bigger than maxlen, ignore the packet und read next packetptr if (len <= maxlen) { // buffer is big enough // copy the packet from the receive buffer enc28j60ReadBuffer(len, packet); } // copy the packet from the receive buffer enc28j60ReadBuffer(len, packet); // use defined values if (((NextPacketPtr - 1) < RXSTART_INIT) || ((NextPacketPtr - 1) > RXSTOP_INIT)) { enc28j60Write(ERXRDPTL, (RXSTOP_INIT)& 0xff ); enc28j60Write(ERXRDPTH, (RXSTOP_INIT)>>8); } else { enc28j60Write(ERXRDPTL, (NextPacketPtr-1)); enc28j60Write(ERXRDPTH, (NextPacketPtr-1)>>8); } // decrement the packet counter indicate we are done with this packet enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); return len; } void enc28j60Init(void) { // initialize I/O ENC28J60_CONTROL_DDR |= 1<>8); // set receive pointer address enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF); enc28j60Write(ERXRDPTH, RXSTART_INIT>>8); // set receive buffer end // ERXND defaults to 0x1FFF (end of ram) enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF); enc28j60Write(ERXNDH, RXSTOP_INIT>>8); // set transmit buffer start // ETXST defaults to 0x0000 (beginnging of ram) enc28j60Write(ETXSTL, TXSTART_INIT&0xFF); enc28j60Write(ETXSTH, TXSTART_INIT>>8); // do bank 2 stuff // enable MAC receive enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); // bring MAC out of reset enc28j60Write(MACON2, 0x00); // enable automatic padding and CRC operations enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); // set inter-frame gap (non-back-to-back) enc28j60Write(MAIPGL, 0x12); enc28j60Write(MAIPGH, 0x0C); // set inter-frame gap (back-to-back) enc28j60Write(MABBIPG, 0x12); // Set the maximum packet size which the controller will accept enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF); enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8); // do bank 3 stuff // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward enc28j60Write(MAADR5, ENC28J60_MAC0); enc28j60Write(MAADR4, ENC28J60_MAC1); enc28j60Write(MAADR3, ENC28J60_MAC2); enc28j60Write(MAADR2, ENC28J60_MAC3); enc28j60Write(MAADR1, ENC28J60_MAC4); enc28j60Write(MAADR0, ENC28J60_MAC5); // no loopback of transmitted frames enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); // switch to bank 0 enc28j60SetBank(ECON1); // enable interrutps enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); //Enable autoinc of buffer enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_AUTOINC); // enable packet reception enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); }