After managing to get some basic communications working in part 3 I assumed that I was not having any sort of SPI issues. After some extensive testing involving sending packets to and from the enc28j60 I realised there was still some problems.  Data was becoming corrupted about 1 in every 3 reads. At first I thought it might be a faulty chip or a badly setup SPI. I started to do a bit of shotgun problem solving and by chance actually found the problem. Turns out the DCO settings were not quite right and my 8MHz was unstable. Luckily I also found out that since my enc28j60 is newer it was able to handle low speeds of 1MHz for SPI communication and therefore I need not have changed the DCO settings at all. Now finally I can say my SPI communications are working fine.

The next task was to create a driver for the enc28j60 so that packets could be sent and received. There was not much point reinventing the wheel here so I based the code heavily on work by Iain Derrington ( I’ve also started hosting my code on github. Now that a basic driver was working it was time to start trying to send and receive my first packets. To begin with I tried to send an ARP request to a router and also reply to any requests. ARPs have ethernet headers so first an ethernet header had to be produced.

typedef struct
 unsigned char DestAddrs[6];
 unsigned char SrcAddrs[6];
 unsigned int type;

Ethernet headers consist of the destination MAC address the source MAC address and the type. The type for ARP is 0x0806. We are trying to find out the router MAC and so therefore the destination address is set to Broadcast or 0xff,0xff,0xff,0xff,0xff,0xff. The source address has to be identical to the MAC address used when setting up the enc28j60.

The ARP header has the following structure:

typedef struct
 EtherNetII eth;
 unsigned int hardware;
 unsigned int protocol;
 unsigned char hardwareSize;
 unsigned char protocolSize;
 unsigned int opCode;
 unsigned char senderMAC[6];
 unsigned char senderIP[4];
 unsigned char targetMAC[6];
 unsigned char targetIP[4];

Eth was the ethernet header. Hardware type for ethernet is 0x0001. Protocol is IP which is 0x0800. Hardware size is the length in 8bits so in the case of normal MACs is 6. Protocol size is the length in 8bits of IPv4 address’ which is 4. The op Code is either a request or reply 0x1 or 0x2. The sender MAC is identical to the ethernet source address and the target MAC is left blank (0x0). Sender IP should be blank and the target ip should be the IP address you want.

With all of that it doesn’t take long to work out how to create an ARP request and reply.