Hello,
I am developing managed drivers for the Whiznet W5500 and I am wondering if I fried my development board or I did something bad to my code. I was having great success and finished the DHCP functionality and was working on a FTP server when I started having problems with the Whiznet chip.
I am developing on the G30 development board (rev 1) using netmf 4.3 and vs2013. Everything has been working great so far, but in my code I cannot seem to communicate with the whizchip reliably any longer. I have create a very stripped down piece of code that shows my problem.
When I create the SPI port I just guessed at a clock of 5000 as I have seen this used before.
This code should build and run as is on the G30 board (with the appropriate assemblies referenced.)
If anyone can spot something I am doing wrong here I would greatly appreciate it.
thanks
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHI.Pins;
using System.Threading;
namespace testWhiznet
{
public class Program
{
private static byte[] buf4 = new byte[4];
private static byte[] buf3 = new byte[3];
private static SPI mSpi;
public static void Main()
{
Debug.Print(Resources.GetString(Resources.StringResources.String1));
OutputPort led = new OutputPort(G30.Gpio.PC7, false);
InputPort ldr0 = new InputPort(G30.Gpio.PA15, false, Port.ResistorMode.PullUp);
InputPort ldr1 = new InputPort(G30.Gpio.PC13, false, Port.ResistorMode.PullUp);
OutputPort reset;
waitForButtonPress(ldr0, led);
reset = new OutputPort(G30.Gpio.PB12, true);
reset.Write(false);
Thread.Sleep(100);
reset.Write(true);
mSpi = new SPI(new SPI.Configuration(G30.Gpio.PC1, false, 0, 0, false, true, 5000, G30.SpiBus.Spi2));
// set the COMMON Mode register reset bit
setMR(COMMON_MODE_REGISTER.Reset);
Thread.Sleep(1000); // and wait a bit ... (no nessecary I believe)
//create a temp mac address and program into the W5500 COMMON register SHAR0 ... SHAR5
byte[] addr = new byte[] { 0x00, 0x21, 0x03, 0x00, 0x00, 0x01 };
setSHAR(addr);
// read the MAC address in the COMMON registers SHAR0 ... SHAR5
var mac = getSHAR();
Debug.Print(Resources.GetString(Resources.StringResources.String2));
}
/// <summary>
/// wait for the given button to be pressed, blink the led while waiting
/// </summary>
/// <param name="button"></param>
/// <param name="led"></param>
private static void waitForButtonPress(InputPort button, OutputPort led)
{
bool ledState = false;
bool notpressed = button.Read();
while (notpressed)
{
ledState = !ledState;
led.Write(ledState);
notpressed = button.Read();
System.Threading.Thread.Sleep(100);
}
led.Write(false);
}
/// <summary>
/// COMMON register bits page 33 4.1 Common Registers (MR)
/// </summary>
[Flags]
public enum COMMON_MODE_REGISTER : byte
{
FARP = 0x01,
PPPoE = 0x08,
PB = 0x10,
WOL = 0x20,
Reset = 0x80,
}
/// <summary>
/// this function simply returns 0 as the COMMON registers start at offset 0.
/// </summary>
/// <returns></returns>
private static uint WIZCHIP_CREG_BLOCK() { return 0; }
/// <summary>
/// the MODE register in the COMMON block address is computed here and returned.
/// ZERO!
/// </summary>
/// <returns></returns>
private static uint MR() { return ((0x000 << 8) + (WIZCHIP_CREG_BLOCK() << 3)); }
/// <summary>
/// the start byte of the MACAddress is SHAR0 and is computed here
/// </summary>
/// <returns></returns>
private static uint SHAR() { return (uint)((0x0009 << 8) + (WIZCHIP_CREG_BLOCK() << 3)); }
/// <summary>
/// function to write the mode value to the COMMON Mode register
/// </summary>
/// <param name="mask"></param>
public static void setMR(COMMON_MODE_REGISTER mask) { WIZCHIP_WRITE_BYTE(MR(), (byte)mask); }
/// <summary>
/// writes a single byte to the whiznet chip via SPI
/// the 16 bit address is supplied and broken into the 3 address bytes required by the W5500
/// The 3rd byte has the "Write" bit set to indicate it is a write
/// </summary>
/// <param name="address"></param>
/// <param name="data"></param>
private static void WIZCHIP_WRITE_BYTE(uint address, byte data)
{
buf4[0] = (byte)((address & 0x00FF0000) >> 16);
buf4[1] = (byte)((address & 0x0000FF00) >> 8);
buf4[2] = (byte)(((address & 0x000000FF) >> 0) | 0x04);
buf4[3] = data;
mSpi.Write(buf4);
}
// Set the Mac Address of the whiznet chip
//2 versions here ... writing a single register at a time, or doiing all 6 bytes in one write
// the commmented out version seems to work ok
// the un commented one fails 100% time.
private static void setSHAR(byte[] mac)
{
//int ii = 0x0;
//foreach (byte b in mac)
//{
// WIZCHIP_WRITE_BYTE((ushort)(SHAR() + ii), b);
// ii += 0x100;
//}
WIZCHIP_WRITE_BUF(SHAR(), mac);
}//setSHAR
/// <summary>
/// write a stream of bytes to the Whiznet chip. Using VDM (variable data mode)
/// first a buffer is allocated for the 3 byye address, then the actual payload data.
/// Written via SPI in one call.
/// </summary>
/// <param name="address"></param>
/// <param name="data"></param>
/// <param name="len"></param>
private static void WIZCHIP_WRITE_BUF(uint address, byte[] data)
{
byte[] buffer = new byte[3 + data.Length]; // space for address(3 bytes) and the data
buffer[0] = (byte)((address & 0x00FF0000) >> 16); // fill in address bytes
buffer[1] = (byte)((address & 0x0000FF00) >> 8);
buffer[2] = (byte)(((address & 0x000000FF) >> 0) | 0x04);
Array.Copy(data, 0, buffer, 3, data.Length); //copy in dtaa payload
mSpi.Write(buffer);
}
/// <summary>
/// Read realLen bytes from SPI port at address
/// </summary>
/// <param name="address">address of register to read</param>
/// <param name="readLen">expected length</param>
/// <returns></returns>
private static byte[] WIZCHIP_READ_BUF(uint address, int readLen)
{
//allocate enough room for return data
byte[] tmp = new byte[readLen];
buf3[0] = (byte)((address & 0x00FF0000) >> 16); //setup the write buffer with address to read
buf3[1] = (byte)((address & 0x0000FF00) >> 8);
buf3[2] = (byte)((address & 0x000000FF) >> 0);
mSpi.WriteRead(buf3, tmp, 3); //write the address to the chip and clock response into tmp (offset 3 to skip first 3 bytes of response)
return tmp;
}
private static byte[] getSHAR() { return WIZCHIP_READ_BUF(SHAR(), 6); }
}
}