2
\$\begingroup\$

For starters: Yes I know I'm about to reinvent the wheel with the following task ahead.

I want to create my own library for the ENC28J60 for an AVR (ATMEGA1284P).

So I've been browsing the net for months now made fairly good progress, but now I'm hitting walls to often.

This is my network layout. For the first step I'm only atempting to communicate uC1 with PC1 over Router1.

The final step would be to have communication between PC1 and uC2.

My Netwrok Layout

Tobby Jaffey in his answer here has broken down the steps to how to get the chip to work.

Now with the help of his list I'll show you all where I'm at right now.

If I were undertaking this project, I'd break it down like this:

  1. Write a program to blink an LED
  2. Extend it to send and receive bytes on the UART (this will be invaluable for debugging)
  3. Extend it to use the SPI interface, verifying the waveforms with a scope/logic analyser
  4. Wire up the ENC28J60 to the SPI interface, not forgetting chip select (I'd leave the interrupt line unconnected for now)
  5. Extend the software to read from the chip id/version register and verify the result
  6. Extend the software to write to a register and read it back
  7. Plug in an ethernet cable, verify that the ethernet link status is changing in the ENC28J60s registers
  8. Wire up the ENC28J60 interrupt line to an input on my microcontroller and test (enabling interrupts on link state changes would seem a good test)

Now, I'm confident that my hardware works.

  1. Bring the ethernet driver functions (accesses to 16 bit registers, fifo access, etc) into my project and verify them by accessing registers
  2. Configure the ENC28J60 for promiscuous mode and dump incoming packets to the UART, verify by comparing with Wireshark/tcpdump
  3. Look at how the original author managed time, in particular how regularly they poll the IP stack and the ethernet driver. Implement a main loop to service these routines
  4. Pull the rest of the IP stack on top of my driver layer
  5. Configure the IP stack for my network (starting with a static IP)
  6. Ping it
  7. Pull the rest of the application code (web server/etc.) into my project.

Blinking a LED is no problem. I'm using logic XOR for it. Works for me.

Communication over UART is only one way from uC to PC. I'm displaing data in HyperTerminal. For every new untested code fragment/part I'm sending a UART text line like to PC.

void ENC28J60_SRC(void)             // System Reset Command (Soft Reset) 
{
    ENC28J60_CS();                  // Enable
    SPIWR(0xFF);
    ENC28J60_DS();                  // Disable
    _delay_ms(50);

while(!(ENC28J60_RD(ESTAT) & CLKRDY))
{
    USART0_TX_String("waiting for CLKRDY");
}
USART0_TX_String("CLKRDY is Ready");
}

SPI communication works, but wasn't tested with scope or logis analyser. I've been sending and receiving data form the ENC28J60 without a problem. So we can check the reading and writing registers part as well as the reading chip/id that has the value of 6 so the chip is Rev.:B7

After setting up the PHY registers and pluging the cable in, LEDs are blinking, but still no data is accepted. I've been also checking the packet counter. It's always 0.

Interrupt is enabled only for packet receive. Never goes to logic LOW level.

Hardware, as in the ENC28J60, is from shop, so it's not self built, connection errors are less likely. The ATMEGA1284P test panel is self made, connections tested.

My ENC28J60 Initialization looks like this:

void ENC28J60_Init(void)
{
    USART0_TX_String("ENC28J60 Reset");
    USART0_TXD(13);
    USART0_TXD(10);
    ENC28J60_SRC();

    USART0_TX_String("RX Buffer Init");
    USART0_TXD(13);
    USART0_TXD(10);

    /*
    #define RXSTART         0x0000      0x0000      0   0       0   
    #define RXEND           4095        0x0FFF      15 255      4095
    #define TXSTART         (RXEND+1)   0x1000      16  0       4096
    #define TXEND           0x1FFF      0x1FFF      31 255      8191
    */

    // Init TX/RX Buffer    Datasheet Section 6.1
    ENC28J60_BANK_SEL(BANK0);
    ENC28J60_CS();
    SPIWR(WCR|ERDPTL);          //  
    SPIWR(RXSTART&0xFF);        //  ERDPTL      Buffer Read Pointer Low
    SPIWR(RXSTART>>8);          //  ERDPTH      Buffer Read Pointer High
    SPIWR(TXSTART&0xFF);        //  EWRPTL      Buffer Write Pointer Low
    SPIWR(TXSTART>>8);          //  EWRPTH      Buffer Write Pointer High
    SPIWR(TXSTART&0xFF);        //  ETXSTL      Transmit Buffer Start Low
    SPIWR(TXSTART>>8);          //  ETXSTH      Transmit Buffer Start High
    SPIWR(TXEND&0xFF);          //  ETXNDL      Transmit Buffer End Low
    SPIWR(TXEND>>8);            //  ETXNDH      Transmit Buffer High
    SPIWR(RXSTART&0xFF);        //  ERXSTL      Recive Buffer Start Low
    SPIWR(RXSTART>>8);          //  ERXSTH      Recive Buffer Start High
    SPIWR(RXEND&0xFF);          //  ERXNDL      Recive Buffer End Low
    SPIWR(RXEND>>8);            //  ERXNDH      Recive Buffer End High
    SPIWR(RXSTART&0xFF);        //  ERXRDPTL    Recive Buffer Read Pointer Low
    SPIWR(RXSTART>>8);          //  ERXRDPTH    Recive Buffer Read Pointer High
    SPIWR(RXSTART&0xFF);        //  ERXWRPTL    Recive Buffer Write Pointer Low
    SPIWR(RXSTART>>8);          //  ERXWRPTH    Recive Buffer Write Pointer High
    SPIWR(0x00);                //  EDMASTL     DMA Start Low
    SPIWR(0x00);                //  EDMASTH     DMA Start High
    SPIWR(0x00);                //  EDMANDL     DMA End Low
    SPIWR(0x00);                //  EDMANDH     DMA End High
    SPIWR(0x00);                //  EDMADSTL    DMA Destination Low
    SPIWR(0x00);                //  EDMADSTH    DMA Destination High
    SPIWR(0x00);                //  EDMACSL     DMA Checksum Low
    SPIWR(0x00);                //  EDMACSH     DMA Checksum High
    ENC28J60_DS();

    USART0_TX_String("BANK1");
    USART0_TXD(13);
    USART0_TXD(10);

    /*
    USART0_TX_String("BANK1 EPMM Init");
    USART0_TXD(13);
    USART0_TXD(10);

    ENC28J60_BANK_SEL(BANK1);
    ENC28J60_CS();
    SPIWR(WCR|EPMM0);
    SPIWR(0x00);                    //  EPMM0
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  
    SPIWR(0x00);                    //  EPMM7
    SPIWR(0x00);                    //  EPMCSL
    SPIWR(0x00);                    //  EPMCSH
    SPIWR(DUMMY);
    SPIWR(DUMMY);
    SPIWR(0x00);                    //  EPMOL
    SPIWR(0x00);                    //  EPMOH
    ENC28J60_DS();

    ENC28J60_BANK_SEL(BANK1);
    ENC28J60_CS();
    SPIWR(WCR|ERXFCON);
    SPIWR(0xA3);                    //  ERXFCON
    ENC28J60_DS();
    */

    USART0_TX_String("MAC Init");
    USART0_TXD(13);
    USART0_TXD(10);

    ENC28J60_BANK_SEL(BANK2);
    ENC28J60_CS();
    SPIWR(WCR|MACON1);
    SPIWR(MARXEN|TXPAUS|RXPAUS);            //  MACON1
    SPIWR(DUMMY);                           //  MACON2?
    SPIWR(PADCFG0|FRMLNEN|TXCRCEN|FULDPX);  //  MACON3
    SPIWR(DEFER);                           //  MACON4
    SPIWR(0x15);                            //  MABBIPG
    SPIWR(DUMMY);                           //  
    SPIWR(0x12);                            //  MAIPGL
    SPIWR(0x00);                            //  MAIPGH
    SPIWR(0x00);                            //  MACLCON1
    SPIWR(0x00);                            //  MACLCON2
    SPIWR(0xEE);                            //  MAMXFLL     MAC MaXimum Frame Length is set to 0x0500 or 1280byte (0x05EE 1518byte)
    SPIWR(0x05);                            //  MAMXFLH
    ENC28J60_DS();

    USART0_TX_String("BANK3");
    USART0_TXD(13);
    USART0_TXD(10);

    // MAC Init         Datasheet Section 6.5
    ENC28J60_BANK_SEL(BANK3);
    ENC28J60_CS();
    SPIWR(WCR|MAADR5);
    SPIWR(myMAC[4]);                        //  MAC address 5
    SPIWR(myMAC[5]);                        //  MAC address 6
    SPIWR(myMAC[2]);                        //  MAC address 3
    SPIWR(myMAC[3]);                        //  MAC address 4
    SPIWR(myMAC[0]);                        //  MAC address 1
    SPIWR(myMAC[1]);                        //  MAC address 2
    ENC28J60_DS();

    USART0_TX_String("PHY Init");
    USART0_TXD(13);
    USART0_TXD(10);

    //  PHY Init            Datasheet Section 6.6
    ENC28J60_PHYWR(PHCON1,PDPXMD,0);                //  PHY in Full-Duplex Mode
    ENC28J60_PHYWR(PHLCON,0b00000010,0b00010010);   //  LED Init

    USART0_TX_String("Int Init");
    USART0_TXD(13);
    USART0_TXD(10);
    ENC28J60_BANK_SEL(BANK0);
    ENC28J60_CS();
    SPIWR(BFS|EIE);                 //  
    SPIWR(INTIE|PKTIE);             //  EIE
    ENC28J60_DS();

    USART0_TX_String("ECON1.RXEN Enabled");
    ENC28J60_CS();
    SPIWR(BFS|ECON1);   
    SPIWR(RXEN);                    //  ECON1
    ENC28J60_DS();
}

Problems sofar:

Could not get the ECON1.RXEN bit to set. Somehow it fixed it self, don't know what did. Not getting any data in the recive buffer. LED blinks on RX activity.

Maybe dropping the CRC check in the filter will help?

Update: 2014.08.16 23:25

Yes! Dropping the CRC check helped. Now I'm able to receive packets.

\$\endgroup\$
  • \$\begingroup\$ Have you seen this ? This can help you in quickly testing your hardware setup. \$\endgroup\$ – vvy Aug 26 '14 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.