unsigned int MACRead(unsigned char* packet, unsigned int maxLen){ volatile unsigned int pckLen; static unsigned int nextpckptr = RXSTART; /*Check if Link is Up*/ if(IsLinkUp()==0){ return FALSE; } /*Read EPKTCNT to see if we have any packets in.*/ BankSel(1);//Select Bank 1. if(ReadETHReg(EPKTCNT) == 0){ return 0;//Report that No Proper Packets RX'd. } /*Setup memory pointers to Read in this RX'd packet.*/ BankSel(0); WriteCtrReg(ERDPTL,(unsigned char)( nextpckptr & 0x00ff)); WriteCtrReg(ERDPTH,(unsigned char)((nextpckptr & 0xff00)>>8)); /*Read in the Next Packet Pointer,and the following 32bit Status Vector. See FIGURE 7-3: SAMPLE RECEIVE PACKET LAYOUT on Page 45 of the datasheet.*/ ReadMacBuffer((unsigned char*)&ptrRxStatus.v[0],6); /*Because,Little Endian.*/ nextpckptr = CYSWAP_ENDIAN16(ptrRxStatus.bits.NextPacket); /*Compute actual length of the RX'd Packet.*/ pckLen=CYSWAP_ENDIAN16(ptrRxStatus.bits.ByteCount) - 4; //We take away 4 as that is the CRC if( pckLen > (maxLen-1) ){ pckLen = maxLen; } /*Read the packet only if it was RX'd Okay. We should be checking other flags too,like Length Out of Range, but that one doesnt seem reliable. We need more work and testing here.*/ if(ptrRxStatus.bits.RxOk==0x01){ ReadMacBuffer(packet,pckLen);//Read packet into buffer. } /*Ensure that ERXRDPT is Always ODD! Else Buffer gets corrupted. See No.5 in the Silicon Errata*/ BankSel(0); if ( ((nextpckptr - 1) < RXSTART) || ((nextpckptr-1) > RXEND) ) { /*Free up memory in that 8kb buffer by adjusting the RX Read pointer, since we are done with the packet.*/ WriteCtrReg(ERXRDPTL, (RXEND & 0x00ff)); WriteCtrReg(ERXRDPTH, ((RXEND & 0xff00) >> 8)); }else{
static u08 WritePhyReg(u08 address, u16 data) { if (address > 0x14) return FALSE; BankSel(2); WriteCtrReg(MIREGADR,address); // Write address of Phy reg WriteCtrReg(MIWRL,(u08)data); // lower phy data WriteCtrReg(MIWRH,((u08)(data >>8))); // Upper phydata return TRUE; }
u16 MACRead(u08 * ptrBuffer, u16 maxsize ) { static u16 nextpckptr = RXSTART; RXSTATUS ptrRxStatus; u08 bytPacket; u16 actsize; BankSel(1); bytPacket = ReadETHReg(EPKTCNT); // How many packets have been received if(bytPacket == 0) return bytPacket; // No full packets received BankSel(0); WriteCtrReg(ERDPTL,(u08)(nextpckptr & 0x00ff)); //write this value to read buffer ptr WriteCtrReg(ERDPTH,(u08)((nextpckptr & 0xff00)>>8)); ReadMacBuffer((u08*)&ptrRxStatus.v[0],6); // read next packet ptr + 4 status bytes nextpckptr = ptrRxStatus.bits.NextPacket; actsize = ptrRxStatus.bits.ByteCount; if( actsize > maxsize ) actsize = maxsize; ReadMacBuffer(ptrBuffer,actsize); // read packet into buffer // ptrBuffer should now contain a MAC packet BankSel(0); WriteCtrReg(ERXRDPTL,ptrRxStatus.v[0]); // free up ENC memory my adjustng the Rx Read ptr WriteCtrReg(ERXRDPTH,ptrRxStatus.v[1]); // decrement packet counter SetBitField(ECON2, ECON2_PKTDEC); return actsize; }
void testMe() { unsigned i; printf( "***********************\n" ); printf( "Clock: %u\n", theclock ); for( i = 0; i < 6; i ++ ) printf( "%02X ", pdata[ i ] ); printf( "\n" ); BankSel( 3 ); printf( "%02X %02X %02X %02X %02X %02X\n", ReadMacReg( MAADR1 ), ReadMacReg( MAADR2 ), ReadMacReg( MAADR3 ), ReadMacReg( MAADR4 ), ReadMacReg( MAADR5 ), ReadMacReg( MAADR6 ) ); printf( "\n" ); printf( "Rev=%d\n", ReadETHReg( EREVID ) ); printf( "***********************\n" ); }
static u16 ReadPhyReg(u08 address) { u16 uiData; u08 bytStat; BankSel(2); WriteCtrReg(MIREGADR,address); // Write address of phy register to read SetBitField(MICMD, MICMD_MIIRD); // Set rd bit do { bytStat = ReadMacReg(MISTAT); }while(bytStat & MISTAT_BUSY); ClrBitField(MICMD,MICMD_MIIRD); // Clear rd bit uiData = (u16)ReadMacReg(MIRDL); // Read low data byte uiData |=((u16)ReadMacReg(MIRDH)<<8); // Read high data byte return uiData; }
void initMAC( const u8* bytMacAddress ) { pdata = bytMacAddress; // Initialize the SPI and the CS pin theclock = platform_spi_setup( ENC28J60_SPI_ID, PLATFORM_SPI_MASTER, ENC28J60_SPI_CLOCK, 0, 0, 8 ); platform_pio_op( ENC28J60_CS_PORT, 1 << ENC28J60_CS_PIN, PLATFORM_IO_PIN_SET ); platform_pio_op( ENC28J60_CS_PORT, 1 << ENC28J60_CS_PIN, PLATFORM_IO_PIN_DIR_OUTPUT ); #if defined( ENC28J60_RESET_PORT ) && defined( ENC28J60_RESET_PIN ) platform_pio_op( ENC28J60_RESET_PORT, 1 << ENC28J60_RESET_PIN, PLATFORM_IO_PIN_CLEAR ); platform_pio_op( ENC28J60_RESET_PORT, 1 << ENC28J60_RESET_PIN, PLATFORM_IO_PIN_DIR_OUTPUT ); platform_timer_delay( 0, 30000 ); platform_pio_op( ENC28J60_RESET_PORT, 1 << ENC28J60_RESET_PIN, PLATFORM_IO_PIN_SET ); #endif ResetMac(); // erm. Resets the MAC. // setup memory by defining ERXST and ERXND platform_timer_delay( 0, 20000 ); BankSel(0); // select bank 0 WriteCtrReg(ERXSTL,(u08)( RXSTART & 0x00ff)); WriteCtrReg(ERXSTH,(u08)((RXSTART & 0xff00)>> 8)); WriteCtrReg(ERXNDL,(u08)( RXEND & 0x00ff)); WriteCtrReg(ERXNDH,(u08)((RXEND & 0xff00)>>8)); // Make sure Rx Read ptr is at the start of Rx segment WriteCtrReg(ERXRDPTL, (u08)( RXSTART & 0x00ff)); WriteCtrReg(ERXRDPTH, (u08)((RXSTART & 0xff00)>> 8)); BankSel(1); // select bank 1 WriteCtrReg(ERXFCON,( ERXFCON_UCEN + ERXFCON_CRCEN + ERXFCON_BCEN)); // Initialise the MAC registers BankSel(2); // select bank 2 SetBitField(MACON1, MACON1_MARXEN); // Enable reception of frames WriteCtrReg(MACLCON2, 63); WriteCtrReg(MACON3, MACON3_FRMLNEN + // Type / len field will be checked MACON3_TXCRCEN + // MAC will append valid CRC MACON3_PADCFG0); // All small packets will be padded SetBitField(MACON4, MACON4_DEFER); WriteCtrReg(MAMXFLL, (u08)( MAXFRAMELEN & 0x00ff)); // set max frame len WriteCtrReg(MAMXFLH, (u08)((MAXFRAMELEN & 0xff00)>>8)); WriteCtrReg(MABBIPG, 0x12); // back to back interpacket gap. set as per data sheet WriteCtrReg(MAIPGL , 0x12); // non back to back interpacket gap. set as per data sheet WriteCtrReg(MAIPGH , 0x0C); //Program our MAC address BankSel(3); WriteCtrReg(MAADR1,bytMacAddress[0]); WriteCtrReg(MAADR2,bytMacAddress[1]); WriteCtrReg(MAADR3,bytMacAddress[2]); WriteCtrReg(MAADR4,bytMacAddress[3]); WriteCtrReg(MAADR5,bytMacAddress[4]); WriteCtrReg(MAADR6,bytMacAddress[5]); // Initialise the PHY registes WritePhyReg(PHCON1, 0x00); WritePhyReg(PHCON2, PHCON2_HDLDIS); WriteCtrReg(ECON1, ECON1_RXEN); //Enable the chip for reception of packets SetBitField(EIE, EIE_INTIE); WritePhyReg(PHIE, PHIE_PGEIE|PHIE_PLNKIE); ReadPhyReg(PHIR); }
u16 MACWrite(u08 * ptrBuffer, u16 ui_Len) { volatile u16 address = TXSTART; u08 bytControl; bytControl = 0x00; BankSel(0); // select bank 0 WriteCtrReg(ETXSTL,(u08)( TXSTART & 0x00ff)); // write ptr to start of Tx packet WriteCtrReg(ETXSTH,(u08)((TXSTART & 0xff00)>>8)); WriteCtrReg(EWRPTL,(u08)( TXSTART & 0x00ff)); // Set write buffer to point to start of Tx Buffer WriteCtrReg(EWRPTH,(u08)((TXSTART & 0xff00)>>8)); WriteMacBuffer(&bytControl,1); // write per packet control byte address++; address+=WriteMacBuffer(ptrBuffer, ui_Len); // write packet. Assume correct formating src, dst, type + data WriteCtrReg(ETXNDL, (u08)( address & 0x00ff)); // Tell MAC when the end of the packet is WriteCtrReg(ETXNDH, (u08)((address & 0xff00)>>8)); ClrBitField(EIR,EIR_TXIF); //SetBitField(EIE, EIE_TXIE |EIE_INTIE); ERRATAFIX; SetBitField(ECON1, ECON1_TXRTS); // begin transmitting; do { // [TODO] add timers here or make packet sending completely asynchronous }while (!(ReadETHReg(EIR) & (EIR_TXIF))); // kill some time. Note: Nice place to block? ClrBitField(ECON1, ECON1_TXRTS); BankSel(0); //read tx status bytes address++; // increment ptr to address to start of status struc WriteCtrReg(ERDPTL, (u08)( address & 0x00ff)); // Setup the buffer read ptr to read status struc WriteCtrReg(ERDPTH, (u08)((address & 0xff00)>>8)); ReadMacBuffer(&TxStatus.v[0],7); if (ReadETHReg(ESTAT) & ESTAT_TXABRT) // did transmission get interrupted? { if (TxStatus.bits.LateCollision) { ClrBitField(ECON1, ECON1_TXRTS); SetBitField(ECON1, ECON1_TXRTS); ClrBitField(ESTAT,ESTAT_TXABRT | ESTAT_LATECOL); } ClrBitField(EIR, EIR_TXERIF | EIR_TXIF); ClrBitField(ESTAT,ESTAT_TXABRT); //printf( " NOT SENT for len=%d\n", ui_Len ); return FALSE; // packet transmit failed. Inform calling function } // calling function may inquire why packet failed by calling [TO DO] function else { //printf( "SENT\n" ); return TRUE; // all fan dabby dozy } }
void initMAC(unsigned char* deviceMAC) { /*Initialize the SPI Module*/ spiInit(); /*Execute a Soft Reset to the MAC*/ ResetMac(); /*Setup the 8kb Memory space on the ENC28J60 by defining ERXST and ERXND*/ BankSel(0);//Select Bank 0 WriteCtrReg(ERXSTL,(unsigned char)( RXSTART & 0x00ff)); WriteCtrReg(ERXSTH,(unsigned char)((RXSTART & 0xff00)>> 8)); WriteCtrReg(ERXNDL,(unsigned char)( RXEND & 0x00ff)); WriteCtrReg(ERXNDH,(unsigned char)((RXEND & 0xff00)>>8)); /*Set RX Read pointer to start of RX Buffer*/ WriteCtrReg(ERXRDPTL, (unsigned char)( RXSTART & 0x00ff)); WriteCtrReg(ERXRDPTH, (unsigned char)((RXSTART & 0xff00)>> 8)); /*Setup Transmit Buffer*/ WriteCtrReg(ETXSTL,(unsigned char)( TXSTART & 0x00ff));//Start of buffer WriteCtrReg(ETXSTH,(unsigned char)((TXSTART & 0xff00)>>8)); /*End of buffer will depend on packets,so no point hardcoding it*/ /*Set the RX Filters*/ BankSel(1);//Select Bank 1 /*REGISTER 8-1: ERXFCON: RECEIVE FILTER CONTROL REGISTER See Page 50 of the datasheet.*/ WriteCtrReg(ERXFCON,( ERXFCON_UCEN + ERXFCON_CRCEN + ERXFCON_PMEN)); //---Setup packet filter--- //This part is taken from Guido Socher's AVR enc28j60 driver.Great Work,that. //For broadcast packets we allow only ARP packtets //All other packets should be unicast only for our mac (MAADR) //The pattern to match on is therefore //Type ETH.DST //ARP BROADCAST //06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 //in binary these poitions are:11 0000 0011 1111 //This is hex 303F->EPMM0=0x3f,EPMM1=0x30 WriteCtrReg(EPMM0, 0x3f); WriteCtrReg(EPMM1, 0x30); WriteCtrReg(EPMCSL,0x39); WriteCtrReg(EPMCSH,0xf7); /*Initialize the MAC Registers*/ BankSel(2); // select bank 2 SetBitField(MACON1, MACON1_MARXEN);// Enable reception of frames WriteCtrReg(MACON3, MACON3_FRMLNEN + // Type / len field will be checked MACON3_TXCRCEN + // MAC will append valid CRC MACON3_PADCFG0); // All small packets will be padded WriteCtrReg(MAMXFLL, (unsigned char)( MAXFRAMELEN & 0x00ff));// set max frame len WriteCtrReg(MAMXFLH, (unsigned char)((MAXFRAMELEN & 0xff00)>>8)); WriteCtrReg(MABBIPG, 0x12);// back to back interpacket gap. set as per data sheet WriteCtrReg(MAIPGL , 0x12);// non back to back interpacket gap. set as per data sheet WriteCtrReg(MAIPGH , 0x0C); /*Assign the MAC Address to the chip.*/ BankSel(3);//Select Bank 3. WriteCtrReg(MAADR1,deviceMAC[0]); WriteCtrReg(MAADR2,deviceMAC[1]); WriteCtrReg(MAADR3,deviceMAC[2]); WriteCtrReg(MAADR4,deviceMAC[3]); WriteCtrReg(MAADR5,deviceMAC[4]); WriteCtrReg(MAADR6,deviceMAC[5]); /*Initialise the PHY registers REGISTER 11-3: PHCON1: PHY CONTROL REGISTER 1 See Page 65 of the Datasheet.*/ WritePhyReg(PHCON1, 0x000); /* "If using half duplex, the host controller may wish to set the PHCON2.HDLDIS bit to prevent automatic loopback of the data which is transmitted." See Section 6.6 on Page 40 */ WritePhyReg(PHCON2, PHCON2_HDLDIS); /*Enable reception of packets*/ WriteCtrReg(ECON1, ECON1_RXEN); }
unsigned char ReadChipRev(void) { BankSel(3); return(ReadETHReg(EREVID)); }
unsigned char MACWrite(unsigned char* packet, unsigned int len) { unsigned char bytControl=0x00; /*Configure TX Buffer Pointers*/ BankSel(0);// select bank 0 /*Buffer write ptr to start of Tx packet*/ WriteCtrReg(ETXSTL,(unsigned char)( TXSTART & 0x00ff)); WriteCtrReg(ETXSTH,(unsigned char)((TXSTART & 0xff00)>>8)); /*Set write buffer pointer to point to start of Tx Buffer*/ WriteCtrReg(EWRPTL,(unsigned char)( TXSTART & 0x00ff)); WriteCtrReg(EWRPTH,(unsigned char)((TXSTART & 0xff00)>>8)); /*Write the Per Packet Control Byte See FIGURE 7-1: FORMAT FOR PER PACKET CONTROL BYTES on Page 41 of the datasheet */ WriteMacBuffer(&bytControl,1); /*Write the packet into the ENC's buffer*/ WriteMacBuffer(packet, len); /*Tell MAC when the end of the packet is*/ WriteCtrReg(ETXNDL, (unsigned char)( (len+TXSTART+1) & 0x00ff)); WriteCtrReg(ETXNDH, (unsigned char)(((len+TXSTART+1) & 0xff00)>>8)); /*We would like to enable Interrupts on Packet TX complete.*/ ClrBitField(EIR,EIR_TXIF); SetBitField(EIE, EIE_TXIE |EIE_INTIE); /*Macro for Silicon Errata to do with Transmit Logic Reset. Silicon Errata No.12 as per Latest Errata doc for ENC28J60 See http://ww1.microchip.com/downloads/en/DeviceDoc/80349c.pdf */ ERRATAFIX; /*Send that Packet!*/ SetBitField(ECON1, ECON1_TXRTS); /*Wait for the Chip to finish the TX,and read the TX interrrupt bit to check the same.*/ do {} while (!(ReadETHReg(EIR) & (EIR_TXIF))); // kill some time. Note: Nice place to block? // kill some time. Note: Nice place to block? /*Clear TXRTS,since the packet has been TX'd.*/ ClrBitField(ECON1, ECON1_TXRTS); /*We will now attempt to read the TX Status Vectors. See TABLE 7-1: TRANSMIT STATUS VECTORS on Page 43 of the datasheet.*/ BankSel(0); /*Because,that control byte.*/ len++; /*Configure the buffer read ptr to read status structure*/ WriteCtrReg(ERDPTL, (unsigned char)( len & 0x00ff)); WriteCtrReg(ERDPTH, (unsigned char)((len & 0xff00)>>8)); /*Read In the TX Status Vectors*/ /*Note: Use these for debugging.Really useful.*/ ReadMacBuffer(&TxStatus.v[0],7); /*Read TX status vectors to see if TX was interrupted.*/ if (ReadETHReg(ESTAT) & ESTAT_TXABRT) { if (TxStatus.bits.LateCollision) { ClrBitField(ECON1, ECON1_TXRTS);//Toggle the TXRTS SetBitField(ECON1, ECON1_TXRTS); ClrBitField(ESTAT,ESTAT_TXABRT | ESTAT_LATECOL);//Clear the Late Collision Bit. } ClrBitField(EIR, EIR_TXERIF | EIR_TXIF);//Clear the Interrupt Flags. ClrBitField(ESTAT,ESTAT_TXABRT);//Clear the Abort Flag. return FALSE;//Report a Failed Packet TX. } else { return TRUE;//Packet Sent Okay! :-) } return TRUE; }