EthernetENC28J60 & G80 & NETMF

Hi,
I have problem with EthernetENC28J60 driver with NETMF. I am using latest SDK 4.3.

Hardware:
_ 1 x G80
_ 1 x EN28J60
_ 1 x RS485
_ 3 x RS232
_ Some IO’s and Display

When I run test program with loopback for RS232 without instance of EthernetENC28J60 driver, everything is fine.

As soon as I create a instance like this…

EthernetENC28J60 eth = new EthernetENC28J60(SPI.SPI_module.SPI2, G80.Gpio.PE2, G80.Gpio.PE1, G80.Gpio.PC13);

… I have problems with loopback on all RS232 ports. Often not the same data received then expected.

This happens only when networkcable is connected and some traffic is on the network. But there is no communication from my program over the ethernet port.
Only an instance for the EthernetENC28J60 class and a physical connection to the network caused this kind of problems.

And additional after some hours the program freeze.

Any idea?

Sounds like the network is adding some load to the system causing it to miss some serial data. Three serial buffers on G80 are small.

So you use events for serial? Try to read serial in a loop in a thread. This may help.

Thank you for reply.
No I don’t use events for serial. Each serial port read in a loop in a seperate thread.

Are you using software or hardware flow control?

For RS232 loopback I have a hardware bridge between Tx and Rx.

Hi,
if you still have problems I think that you only will have a chance to get some help if you post a condensed part of your code that still produces the wrong behavior.
Kind regards
RoSchmi

2 Likes

I will try to reproduce the problem with the G80 developer board. I suspect a bug in EthernetENC28J60 driver. To whom could I send the code then?

BR Chris

You could post the code here in the forum or store it on e.g. Google Drive and post a link.

Thanks, I still waiting for my G80 developer board.
But I’ve found, that the problem only exist, if the board is connected to our company network where is some of traffic.
If I us a seperate network without other devices, everything works fine.

br chris

While on the surface serial communications under NETMF seems simple, there are right ways and wrong ways to implement it.

I normally would use serial events, since the limited sized serial buffers are emptied quickly, and the data is placed into the much larger event queue mechanism.

Without knowing anything about your aggregate data rate, and not seeing your code, I would guess that your code needs a bit of reorganization and optimization.

In the short term, if you need to be on your corporate network, you might want to put an smart ethernet switch between the NETMF board and the network. It should filter out most of the network traffic.

It is planned to install multiple devices on different customer network. So it’s not easy to install smart ethernet switches for all our customers network :confused:

This is my test code.
Without network connection it works fine. When I connect a network cable, I got often timeouts and the application feeze after some hours.

public class Programm
{
    private static SdCardController _sdCardReader;
    private static I2CDevice _i2C;
    private static SPI _spi1;
    private static EthernetENC28J60 _eth;
    private static SerialPort _serial;

    public static void Main()
    {
        Utility.SetLocalTime(RealTimeClock.GetDateTime());
        _i2C = new I2CDevice(new I2CDevice.Configuration(1, 100));
        _spi1 = new SPI(new SPI.Configuration(G80.Gpio.PD10, false, 0, 0, false, true, 10000, SPI.SPI_module.SPI1));
        var eeprom = new EeProm(_i2C, 81);
        var macAddress = eeprom.ReadMacAddress();

        _sdCardReader = new SdCardController();
        _sdCardReader.Init();

        var beeper = new OutputPort(G80.Gpio.PA15, false);

        // Ethernet - set physical address (MAC)
        _eth = new EthernetENC28J60(SPI.SPI_module.SPI2, G80.Gpio.PE2, G80.Gpio.PE1, G80.Gpio.PC13);
        _eth.PhysicalAddress = macAddress;

        _sdCardReader.Log("********************************");
        _sdCardReader.Log("*********** Start Up ***********");
        _sdCardReader.Log("********************************");

        StartTestSerialPort();

        while (true)
        {
            Thread.Sleep(1000);

#if !DEBUG
if (!GHI.Processor.Watchdog.Enabled)
{
GHI.Processor.Watchdog.Enable(5000);
}
GHI.Processor.Watchdog.ResetCounter();
#endif
}
}

    private static void StartTestSerialPort()
    {
        var _worker = new Thread(() =>
        {
            _serial = new SerialPort("COM2", 19200, (Parity)0, 8, (StopBits)1);
            _serial.DiscardInBuffer();
            _serial.DiscardOutBuffer();
            _serial.Open();

            while (true)
            {
                TestSerialPort();
                Thread.Sleep(2);
            }
        });
        _worker.Start();
    }


    private static void TestSerialPort()
    {
        try
        {
            byte[] sendData = new byte[10] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };

            var result = SendReceive(sendData, 1000, 10);

            if (result == null)
            {
                _sdCardReader.Log("Serial timeout");
                return;
            }

            // check result
            if (result.Length != sendData.Length)
            {
                _sdCardReader.Log("Serial data invalid length");
                return;
            }

            for (int i = 0; i < sendData.Length; i++)
            {
                if (sendData[i] != result[i])
                {
                    _sdCardReader.Log("Serial data invalid result");
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            _sdCardReader.LogException(ex);
        }
    }

    private static byte[] SendReceive(byte[] writeBuffer, int timeout, int readLength)
    {
        var result = new byte[readLength];

        _serial.DiscardInBuffer();
        _serial.DiscardOutBuffer();
        _serial.Write(writeBuffer, 0, writeBuffer.Length);

        var end = DateTime.Now.AddMilliseconds(timeout);
        var idx = 0;
        while (_serial.BytesToRead > 0 || DateTime.Now <= end)
        {
            if (_serial.BytesToRead > 0)
            {
                var b = (byte)_serial.ReadByte();

                if (idx < result.Length)
                {
                    result[idx] = b;
                    idx++;
                }

                if (idx == readLength)
                {
                    return result;
                }
            }
            Thread.Sleep(1);
        }
        return null;
    }
}

Here my code again with better formating :wink:

public class Programm
{
    private static SdCardController _sdCardReader;
    private static I2CDevice _i2C;
    private static SPI _spi1;
    private static EthernetENC28J60 _eth;
    private static SerialPort _serial;

    public static void Main()
    {
        Utility.SetLocalTime(RealTimeClock.GetDateTime());
        _i2C = new I2CDevice(new I2CDevice.Configuration(1, 100));
        _spi1 = new SPI(new SPI.Configuration(G80.Gpio.PD10, false, 0, 0, false, true, 10000, SPI.SPI_module.SPI1));
        var eeprom = new EeProm(_i2C, 81);
        var macAddress = eeprom.ReadMacAddress();

        _sdCardReader = new SdCardController();
        _sdCardReader.Init();

        var beeper = new OutputPort(G80.Gpio.PA15, false);

        // Ethernet - set physical address (MAC)
        _eth = new EthernetENC28J60(SPI.SPI_module.SPI2, G80.Gpio.PE2, G80.Gpio.PE1, G80.Gpio.PC13);
        _eth.PhysicalAddress = macAddress;

        _sdCardReader.Log("********************************");
        _sdCardReader.Log("*********** Start Up ***********");
        _sdCardReader.Log("********************************");

        StartTestSerialPort();

        while (true)
        {
            Thread.Sleep(1000);
            if (!GHI.Processor.Watchdog.Enabled)
            {
                GHI.Processor.Watchdog.Enable(5000);
            }
            GHI.Processor.Watchdog.ResetCounter();
        }
    }

    private static void StartTestSerialPort()
    {
        var _worker = new Thread(() =>
        {
            _serial = new SerialPort("COM2", 19200, (Parity)0, 8, (StopBits)1);
            _serial.DiscardInBuffer();
            _serial.DiscardOutBuffer();
            _serial.Open();

            while (true)
            {
                TestSerialPort();
                Thread.Sleep(2);
            }
        });
        _worker.Start();
    }


    private static void TestSerialPort()
    {
        try
        {
            byte[] sendData = new byte[10] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };

            var result = SendReceive(sendData, 1000, 10);

            if (result == null)
            {
                _sdCardReader.Log("Serial timeout");
                return;
            }

            // check result
            if (result.Length != sendData.Length)
            {
                _sdCardReader.Log("Serial data invalid length");
                return;
            }

            for (int i = 0; i < sendData.Length; i++)
            {
                if (sendData[i] != result[i])
                {
                    _sdCardReader.Log("Serial data invalid result");
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            _sdCardReader.LogException(ex);
        }
    }

    private static byte[] SendReceive(byte[] writeBuffer, int timeout, int readLength)
    {
        var result = new byte[readLength];

        _serial.DiscardInBuffer();
        _serial.DiscardOutBuffer();
        _serial.Write(writeBuffer, 0, writeBuffer.Length);

        var end = DateTime.Now.AddMilliseconds(timeout);
        var idx = 0;
        while (_serial.BytesToRead > 0 || DateTime.Now <= end)
        {
            if (_serial.BytesToRead > 0)
            {
                var b = (byte)_serial.ReadByte();

                if (idx < result.Length)
                {
                    result[idx] = b;
                    idx++;
                }

                if (idx == readLength)
                {
                    return result;
                }
            }
            Thread.Sleep(1);
        }
        return null;
    }
}

You have defined an ethernet interface but have not completed initialization. What happens if you do not define the ethernet interface and connect to network?

Hello Mike,
in this case everything is fine.

Try completing the initialization and see what happens.

I did already the ethernet initialization. UDP connection and/or TCP connection works fine. But it’s the same Problem :confused:

In your original post, you described your problem as not the same data. Could you be more specific?

Are you losing data? Is the data out of sequence? Is the data garbled?

I would try to do writing to and reading from the serial port in different threads.

It is different. The most time I losing data. For example: I send 10 bytes and I receive only 9 bytes. One byte is missing.
e.g:
Send: 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09.
Recieve: 0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09.
In this example the 3rd byte is missing.

I can validate the result, but the bigger problem is the freeze (reboot about watchdog) after some hours.

Does your end application need to send and receive serial data? If you only need to recieve data, or more data is recieved that sent them you may not have any problems.

Obviously there is a problem in your test but this send and receive could by showing a problem that may not appear in your end application.

What I suggest is that we chat directly about your application and see if we together can come up with an ideal solution. Contact Us – GHI Electronics

1 Like