Status of Ethernet library

304 views
Skip to first unread message

Osqui LittleRiver

unread,
Nov 30, 2016, 7:30:28 AM11/30/16
to Arduino Developers
Hello.

Now it seems Arduino Ethernet 2 shield (based on W5500) has arrived to .cc stock, it is clear official Ethernet library should be updated to recognize new Wiznet chips. There are many forks (or new developments) around the world able to do this, already. My question is: which will be the path choosen by Arduino team?

In this sense, there's an very interesting discussion (which links to other parallel worth-reading discussions) here : https://github.com/arduino-libraries/Ethernet/issues/37 (disclaimer, I'm the original poster) Anyway, the most exciting of that thread (for the impatients) is at the end, where Paul Stoffregenś suggests a really sensible proposal .I've thought it's a good idea publish his ideas and advices here to agree a -really important- decision involving more people. What do you think?

Thanks!

Dieter.Burandt

unread,
Dec 1, 2016, 3:44:02 AM12/1/16
to devel...@arduino.cc

Hello,

The mail from Paul Stoffregen is a very interesting for me. Thanks!

Here he wrote, that he is thinking about rising buffer size. Yes, it is clear that this can enhance the speed, but may have drawbacks in respect with boards that have very few memory. But depending on the internal code, it can also result into a longer interrupt disable state and rise other problems.

For my Arduino Due project, I significantly rised buffer sizes and/or the speed for: Ethernet/W5100, SD-card, RingBuffer(Serial), Wire(I2C)

I patched the sources from the Arduino group, but that gives problems on updates.

A very simple solution would be, if the sources of theese parameters are inclosed in "#ifndef" ... "#endif" and if it would be possible to overwrite these few parameters by the proper definitions before including Arduino.h in the header of the main program source.

The expirenced programmer can do this and the novice user will still have a well working system with traditional values.

Thanks!
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Paul Stoffregen

unread,
Dec 1, 2016, 7:41:46 AM12/1/16
to devel...@arduino.cc
On 12/01/2016 12:43 AM, Dieter.Burandt wrote:

Hello,

The mail from Paul Stoffregen is a very interesting for me. Thanks!

Here he wrote, that he is thinking about rising buffer size. Yes, it is clear that this can enhance the speed, but may have drawbacks in respect with boards that have very few memory. But depending on the internal code, it can also result into a longer interrupt disable state and rise other problems.

For my Arduino Due project, I significantly rised buffer sizes and/or the speed for: Ethernet/W5100,


Have you published or shared your modified Ethernet W5100 code?  If so, I'll take a look and run some benchmarks.

You can find everything I've done (so far) on my github account, which is linked from issue #37 mentioned below.

Today this is still a work-in-progress.  I feel it's premature to discuss here.  When this code is ready for a wider audience, I intend to publish as a distinctly named library available via the Library Manager.  Only after a lengthy period usage by many people across several boards should this be considered as a possible replacement for the aging but stable Arduino Ethernet library.

Dieter.Burandt

unread,
Dec 1, 2016, 12:24:44 PM12/1/16
to devel...@arduino.cc

High Paul,

No I didn't publish my changes. After the Arduino Due was officially retired, I decide  to freeze the software still using 1.6.9. For this version I can give you the changes:

===========================================================================================================
W5100 1.6.9 - Using 14MHz SPI-clock for the W5100
W5100.h:  #define SPI_ETHERNET_SETTINGS ETHERNET_SHIELD_SPI_CS,SPISettings(14000000, MSBFIRST, SPI_MODE0)
w5100.cpp  SPI.setClockDivider(ETHERNET_SHIELD_SPI_CS, 6);
.................................................
Remark: The maximum SPI-speed for the W5500 is 33.3Mhz  (see remark 4 on chapter "5.5.4 SPI Timing" in
the datasheet version 1.0.2), that is 28MHz for the Arduino Due and NOT more.
===========================================================================================================

Sd2Card 1.6.9 - Using SPI speed of 42MHz! (It does realy work with the Arduino Due!):
SD.cpp
// On card.init in SD.cpp set the speed to SPI_FULL_SPEED, that is 42MHz =>
boolean SDClass::begin(uint8_t csPin) {
  ...
  return card.init(SPI_FULL_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);
}
-----------------------------------------------------------------------------------------------------------
The application is using a 24kB buffer for reading from the SD-card.
After reading one block of data of the fle, the handle closed and reopend to read the next block of the file.
After reading a 24kB block the data are send calling:
"void WebServer::writeP(const unsigned char *data, size_t length)".
===========================================================================================================

My benchmarks with the above settings downloading a 8361kB-file from the SD-card to my PC using the "Arduino Ethernet Shield R3" with the Arduino Due did show:  79.6kB/s to 82.3kB/s.

That is a test not only of the Ethernet but the complete system from SD-card to the Arduino Due and via the Ethernet interface to my PC.


As a side info (nothing regarding speed:)

I added to missing functions in the Ethernet driver to get all info's from  the interface:

===========================================================================================================
Ethernet 1.6.9 - Missing funtionality: Get MacAddr and the current DHCP-IP from the W5100:
.................................................
Ethernet.h -> Definition added:
  IPAddress dhcpServerIP();
  uint8_t * MacAddr();
.................................................
Ethernet.cpp -> Code added:
//
IPAddress EthernetClass::dhcpServerIP() { return _dhcp->getDhcpServerIp(); }
//
uint8_t * EthernetClass::MacAddr()
{
  static uint8_t Mac[6]={0,0,0,0,0,0};
  SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
  W5100.getMACAddress(Mac);
  SPI.endTransaction();
  return Mac;
}
===========================================================================================================

It is time for me to change to the current release of the software, after it is clear that the Arduino Due is still supported.

I will do it this weekend and I will look, if I can test your driver and send benchmarks about the W5500.

Thanks Paul

Cristian Maglie

unread,
Dec 1, 2016, 2:54:35 PM12/1/16
to devel...@arduino.cc

I've rebased the PR #2325 on top of the current master (it required a
bit of fiddling with git because it was very old).

The performance with a Leonardo + W5100 are aligned to Paul and Dieter
(I see around 100KB/sec with a tight sending loop). This version should
also auto-detect all W5x00 chips and work without any extra configuration.

I'd like to merge #2325 after another round of testing.

Paul, Dieter, is this version too far from what you are working on?

C



Il 01/12/2016 18:24, Dieter.Burandt ha scritto:
> High Paul,
>
> No I didn't publish my changes. After the Arduino Due was officially
> retired, I decide to freeze the software still using 1.6.9. For this
> version I can give you the changes:
>
> ===========================================================================================================
> *W5100 1.6.9 - Using 14MHz SPI-clock for the W5100*
> W5100.h: #define SPI_ETHERNET_SETTINGS
> ETHERNET_SHIELD_SPI_CS,SPISettings(*14000000*, MSBFIRST, SPI_MODE0)
> w5100.cpp SPI.setClockDivider(ETHERNET_SHIELD_SPI_CS, 6);
> .................................................
> *Remark:* The maximum SPI-speed for the W5500 is 33.3Mhz (see remark 4
> on chapter "5.5.4 SPI Timing" in
> the datasheet version 1.0.2), that is 28MHz for the Arduino Due and NOT
> more.
> ===========================================================================================================
>
> *Sd2Card 1.6.9 - Using SPI speed of 42MHz!* (It does realy work with the
> Arduino Due!):
> SD.cpp
> // On card.init in SD.cpp set the speed to SPI_FULL_SPEED, that is 42MHz =>
> boolean SDClass::begin(uint8_t csPin) {
> ...
> return card.init(*SPI_FULL_SPEED*, csPin) &&
>>>> **suggests a really sensible proposal .I've thought it's a good idea
>>>> publish his ideas and advices here to agree a -really important-
>>>> decision involving more people. What do you think?
>>>>
>>>> Thanks!
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Developers" group.
>>>> To unsubscribe from this group and stop receiving emails from it,
>>>> send an email to developers+...@arduino.cc
>>>> <mailto:developers+...@arduino.cc>.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Developers" group.
>>> To unsubscribe from this group and stop receiving emails from it,
>>> send an email to developers+...@arduino.cc
>>> <mailto:developers+...@arduino.cc>.
>>
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Developers" group.
>> To unsubscribe from this group and stop receiving emails from it, send
>> an email to developers+...@arduino.cc
>> <mailto:developers+...@arduino.cc>.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to developers+...@arduino.cc
> <mailto:developers+...@arduino.cc>.


--
Cristian Maglie <c.ma...@arduino.cc>

Paul Stoffregen

unread,
Dec 1, 2016, 3:04:50 PM12/1/16
to devel...@arduino.cc
On 12/01/2016 11:54 AM, Cristian Maglie wrote:
> I'd like to merge #2325 after another round of testing.
>
> Paul, Dieter, is this version too far from what you are working on?
>

Please hold off merging #2325.

I'm working on a much more optimization and many small improvements.
Even for cases where the bandwidth to a remote site (with network
latency) isn't improvement, these changes dramatically reduce the amount
of CPU time consumed by the Ethernet library. For real applications,
that will turn into more CPU time to actually use the incoming data or
generate the outgoing data, allowing more of them to actually achieve
those speeds.

William Westfield

unread,
Dec 1, 2016, 9:43:38 PM12/1/16
to devel...@arduino.cc
SPI really needs write-only functions :-(

I can’t quite tell if Paul’s SPIFIFO does this, or whether it’s just using features present in the chip :-(

The big problem is that mixing receive and transmit into the same transfer() call means that you can’t overlap any code with the SPI transmission time.

Recent analysis (on Due): http://forum.arduino.cc/index.php?topic=437243

DMA might be good, although I’m not sure how quickly it would get complicated.

BillW

Dieter.Burandt

unread,
Dec 4, 2016, 3:29:19 PM12/4/16
to devel...@arduino.cc

Hi Cristian, hi Paul,

No, I am not working on a driver with the W5500 chip. But when the Aduino team stopped supporting the Arduino Due and the Arduino Ethernet R3 I had to look what to do to still maintain the boards for myself to be sure to keep my Gardenwatering System running over  years and bought two W5500-boards and it was clear for me, that I must adapt the W5100 driver. But the world is changing as I see.

For your information I tested my system more precise:

Arduino Due + Arduino Ethernet Shield R3 running on 14MHz SPI-speed:
(SPI-Clock for SD-Card-i/o: 42MHz)
24kB   user buffer: DefaultCmd: 8561653 byte read from SD in  25809 ms and send to the web in  85885 ms, total=111694 ms
12kB   user buffer: DefaultCmd: 8561653 byte read from SD in  29025 ms and send to the web in  85879 ms, total=114904 ms
 6kB   user buffer: DefaultCmd: 8561653 byte read from SD in  35385 ms and send to the web in  85881 ms, total=121266 ms
 3kB   user buffer: DefaultCmd: 8561653 byte read from SD in  48149 ms and send to the web in  85684 ms, total=133833 ms
 2kB   user buffer: DefaultCmd: 8561653 byte read from SD in  60892 ms and send to the web in  85669 ms, total=146561 ms
 1.5kB user buffer: DefaultCmd: 8561653 byte read from SD in  73414 ms and send to the web in  85766 ms, total=159180 ms
  768B user buffer: DefaultCmd: 8561653 byte read from SD in 132406 ms and send to the web in  85702 ms, total=218108 ms
  256B user buffer: DefaultCmd: 8561653 byte read from SD in 351243 ms and send to the web in  85727 ms, total=436970 ms
 
Arduino Due + Arduino Ethernet Shield R3 running on 4MHz SPI-speed:
(SPI-Clock for SD-Card-i/o: 42MHz)
24kB   user buffer: DefaultCmd: 8561653 byte read from SD in  25837 ms and send to the web in 156533 ms, total=182370 ms
12kB   user buffer: DefaultCmd: 8561653 byte read from SD in  29013 ms and send to the web in 156488 ms, total=185501 ms
 6kB   user buffer: DefaultCmd: 8561653 byte read from SD in  35465 ms and send to the web in 156422 ms, total=191887 ms
 3kB   user buffer: DefaultCmd: 8561653 byte read from SD in  48129 ms and send to the web in 156328 ms, total=204457 ms
 2kB   user buffer: DefaultCmd: 8561653 byte read from SD in  60842 ms and send to the web in 156354 ms, total=217196 ms
 
 Arduino Due + Arduino Ethernet Shield R3 running on 14MHz SPI-speed:
(SPI-Clock for SD-Card-i/o: 21MHz)
 24kB  user buffer: DefaultCmd: 8561653 byte read from SD in  42813 ms and send to the web in  85901 ms, total=128714 ms
 12kB  user buffer: DefaultCmd: 8561653 byte read from SD in  48067 ms and send to the web in  85854 ms, total=133921 ms
  6kB  user buffer: DefaultCmd: 8561653 byte read from SD in  58487 ms and send to the web in  85879 ms, total=144366 ms
  3kB  user buffer: DefaultCmd: 8561653 byte read from SD in  79389 ms and send to the web in  85660 ms, total=165049 ms
  2kB  user buffer: DefaultCmd: 8561653 byte read from SD in 100216 ms and send to the web in  85677 ms, total=185893 ms

It see that the change of the SPI speed for the SD-card from 42MHz to 21MHz results in a speed reduction of around 60% and is somehow as expected also when using a smaller buffer.

The speed of Ethernet when changing the SPI speed for the W5500 from 14MHz to 4MHz is more difficult to understand. A reduction of the SPI speed by a factor of 3.5 results only in a speed reduction of only 55%. The size of the buffer has no effect. May be that the W5500 chip is working better and that shows the test from Paul or may be that there are problems with the SPI driver. I am shure you will find it. Good luck!

Using 14Mhz the speed is 97kB/s. Also with standard 4Mhz, I get a speed of 45kB/s using "void WebServer::writeP(const unsigned char *data, size_t length)" of Arduino 1.6.13.

Best Regards

Dieter

Andrew Kroll

unread,
Dec 4, 2016, 8:03:37 PM12/4/16
to devel...@arduino.cc
The explanation for the strange speed reduction is simple.
You need to account for the overhead of accessing the SD card...

 (disclaimer,
I'm the original poster) Anyway, the most exciting of that thread
(for the impatients) is at the end, where Paul Stoffregenś
**suggests a really sensible proposal .I've thought it's a good idea
publish his ideas and advices here to agree a -really important-
decision involving more people. What do you think?

Thanks!
-- 
You received this message because you are subscribed to the Google
Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to developers+unsubscribe@arduino.cc
<mailto:developers+unsub...@arduino.cc>.
-- 
You received this message because you are subscribed to the Google
Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to developers+unsubscribe@arduino.cc
<mailto:developers+unsub...@arduino.cc>.
-- 
You received this message because you are subscribed to the Google
Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to developers+unsubscribe@arduino.cc
<mailto:developers+unsub...@arduino.cc>.
-- 
You received this message because you are subscribed to the Google
Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to developers+unsubscribe@arduino.cc
<mailto:developers+unsub...@arduino.cc>.

    

--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.



--
Visit my github for awesome Arduino code @ https://github.com/xxxajk

Dieter.Burandt

unread,
Dec 5, 2016, 4:13:23 AM12/5/16
to devel...@arduino.cc

Hi Andrew,

for the SD-card access it is clear, but the speed is okay.

I looked into the Ethernet and Socket driver. The call of "void WebServer::writeP(const unsigned char *data, size_t length)" results in a multiple byte copy and that is the reason for the bad speed. This call should directly call the socket function and use data pointers and should not move any data.

Best Regards,

Dieter

-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Paul Stoffregen

unread,
Dec 5, 2016, 2:40:40 PM12/5/16
to devel...@arduino.cc
TL;DR = I'm working on greatly optimizing the Ethernet library at all levels.  It's still very much a work-in-progress.

The Ethernet library is built in several layers.  I've been working on optimizations at all of them.  Here are some details...

SPI read/write operations are the lowest & simplest layer where most people have tried to optimize.  Faster SPI clocks and reducing dead time between bytes are the main optimizations at this level.  I've optimized this for Teensy's FIFO-based SPI, so I can test a "best case" scenario.  Later I'll make more optimizations at this level for other boards (but some boards could really do with having their SPI libraries improved).  Except for very low latency local subnet networking, optimizations at this level reduce CPU usage but make the least real-world performance improvement for connections to remote sites, due to the inefficiency at all the higher levels!

I've also adopted Adafruit's extension to allow any pin for chip select, and I've optimized that for direct register access on most widely used boards.  Hopefully there isn't much controversy about this extension?

W5x00 register read/write is a very thin layer using C preprocessor macros.  I've changed these to take advantage of the block read/write capability of the newer chips, rather than doing separate access for multi-bytes registers.  This cuts most non-data register access overhead almost in half.

The socket layer manages access to the buffer memory within the W5x00 chip.  Traditionally, this layer has tremendous overhead, making several non-data register accesses for each read/write from your Arduino sketch.  Probably the most controversial optimization I've made uses 32 bytes of RAM (or 64 bytes if 8 sockets are supported) to retain of state information, but it provides an incredible reduction in SPI communication overhead.  This change allows nearly all SPI communication to be for actual data.

The TCP layer occurs entirely within the W5x00 chip, and is responsible for the much of the poor performance.  By default, TCP ACKs are delayed.  This limits TCP receive speed, depending on network latency.  The chip also has an option to turn off this delay, which would result in a flood of ACK packets without the socket layer optimization.  The size of buffer memory allocated within the W5x00 chip and the maximum packet size matter.  I'm still experimenting and capturing tcpdump packet logs, and finding ways to influence how the chip really does things.  Another controversial design choice is whether to support all 8 sockets of the newer chips, or restrict them to only 4 sockets (same as the original W5100) using larger buffers to (perhaps) improve performance.  So far I've been supporting only 4 of the 8 sockets in the newer chips.

The C++ Arduino API layer just calls the socket functions.  It doesn't offer much optimization potential.  However, TCP transmission is particularly inefficient when each individual (small) write becomes as separate ethernet packet.  Without a timer mechanism for auto-flushing, I really don't see much option.  Long term, libraries like Ethernet really need an Arduino API to provide (non-ISR context) timers... but that's a huge topic for another day!

The Arduino sketch itself isn't technically a layer within the library, but how it accesses data makes a tremendous difference.  All the examples and much of the code published on the internet accesses data 1 byte at a time, usually calling client.available() and then client.read().  I've been focusing on this case, and also the case of reading 80 bytes at a time.  So far I've mostly been testing with the WebClient example, accessing various internet sites and also a local Apache2 server.  I still need to expand my testing to other applications, something that's primarily TCP transmitting, and UDP protocols like Artnet (typically large block) and Open Sound Control (small chunk access).

My hope is to greatly improve the Ethernet library performance for use with all boards.  It's turning out to a huge project with very substantial changes at all levels.  Whether such a massive redesign can be accepted as Arduino's officially published Ethernet library is a good question.... but I'm hopeful this work can eventually benefit everyone.
-- You received this message because you are subscribed to the Google Groups "Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Dieter.Burandt

unread,
Dec 6, 2016, 3:55:51 AM12/6/16
to devel...@arduino.cc

This is for information only:

I corrected my user code for the the Ethernet transfer. When calling "void WebServer::writeP(const unsigned char *data, size_t length)" of the WebDuino package the data are internally moved bytewise and a buffer of 32 bytes is used slowing down the Ethernet transfer.

Now I use the call "server.write(pBuf,DataSize);" that nearly directly calls the socket without any byte move. I recalculate the pointer into my 24kB buffer on each call and also the data size limmiting to 1024 byte that the socket use to write to the Ethernet interface. (Using 2kB is a little bit slower for the W5100.)

Now I get the maximum speed achievable with the W5100 under Arduino 1.6.13 for the Arduino Due:

Enhanced version calling "server.write(pBuf,SizeToWrite);" from Webduino without byte move and 1kB blocks writting via Socket call:

Arduino Due + Arduino Ethernet Shield R3 running on 14MHz SPI-speed:
(SPI-Clock for SD-Card-i/o: 42MHz)
24kB user buffer: DefaultCmd: 8561653 Byte read from SD in 25.042s into a 24576 Byte buffer and send to the web in 56.030s, total= 81.872s  (ETH: 153kB/s)
12kB user buffer: DefaultCmd: 8561653 Byte read from SD in 29.006s into a 12288 Byte buffer and send to the web in 56.007s, total= 85.013s
 6kB user buffer: DefaultCmd: 8561653 Byte read from SD in 35.050s into a  6144 Byte buffer and send to the web in 56.007s, total= 91.357s
 3kB user buffer: DefaultCmd: 8561653 Byte read from SD in 47.054s into a  3072 Byte buffer and send to the web in 56.045s, total=103.999s
 1kB user buffer: DefaultCmd: 8561653 Byte read from SD in 98.000s into a  1024 Byte buffer and send to the web in 56.015s, total=154.415s

 
Arduino Due + Arduino Ethernet Shield R3 running on 4MHz SPI-speed:
(SPI-Clock for SD-Card-i/o: 42MHz)
24kB user buffer: DefaultCmd: 8561653 Byte read from SD in 25.028s into a 24576 Byte buffer and send to the web in 106.662s, total=132.490s (ETH: 80kB/s)
12kB user buffer: DefaultCmd: 8561653 Byte read from SD in 28.075s into a 12288 Byte buffer and send to the web in 106.628s, total=135.603s
 6kB user buffer: DefaultCmd: 8561653 Byte read from SD in 35.053s into a  6144 Byte buffer and send to the web in 106.625s, total=141.978s
 3kB user buffer: DefaultCmd: 8561653 Byte read from SD in 47.079s into a  3072 Byte buffer and send to the web in 106.643s, total=154.622s
 1kB user buffer: DefaultCmd: 8561653 Byte read from SD in 98.085s into a  1024 Byte buffer and send to the web in 106.669s, total=205.054s

(I used a 42MHz Spi-clock for the SD-card. With my hardware it works very well. The official settings should not exceed 28MHz. The capacity of the SPI data lines will be too high using the prototyp boards.)

Best Regards,

Dieter

Paul Stoffregen

unread,
Dec 6, 2016, 7:02:55 AM12/6/16
to devel...@arduino.cc
Any chance you might publish this as a benchmark program, perhaps with some guidance on what server setup (remote on the internet vs local on your ethernet subnet) you're using to receive the data?

Sounds like you're mostly testing TCP transmit performance here, right?

Dieter.Burandt

unread,
Dec 6, 2016, 9:08:40 AM12/6/16
to devel...@arduino.cc

Hi Paul,

Yes, that's right, I am testing only the transmitt performance.

The code is only part of a really big programm, around 256kB self written code and special hardware deveoped. That is a already mentioned garden watering unit, not available at the market today. May be that I try to sell it next year.

Here I had to check also the speed under some circiumctances and also the speed for download logs and files, but id does give no upload.

I use the  WebDuino library for the lot of web pages and I also integrated some file downloads.

My original code did call "server.writeP(MyBuf, BytesReadChunk);" which results in internal byte transfer into a 32 byte buffer that is finally written to the socket via "send(_sock, buf, size);" where size can up to 2kB for the W5100 but used in this call are only 32 byte.

I changed my code now  and calling "server.write(pBuf,WriteDataChunkToEth);". Finally also "send(_sock, buf, size);" is called but now the pointer to the buffer and the size is not altered. This gives the full speed.

As I understand, the socket code uses the hardware support of the CPU and so in running with full speed.

If you have some code that uses WebDuino to download a file, you can integrate the following code and test:

//----------------------------------------------------------------------------------
// Is using the server instance of WebDuino =>
// the following code is fast version of: "server.writeP(MyBuf, BytesReadChunk);"
//
inline void WriteDataToEth(WebServer &server, unsigned char * MyBuf, int DataSize)
{
    unsigned short ChunkSize;
    unsigned char * pBuf;
    int StillToWrite=DataSize;
    if(StillToWrite>0)
    {
        pBuf=MyBuf;
        while(StillToWrite)
        {
            ChunkSize=StillToWrite;
            if(ChunkSize>0)
            {
                if(ChunkSize>1024) ChunkSize=1024;
                server.write(pBuf,ChunkSize);
                StillToWrite-=ChunkSize;
                pBuf+=ChunkSize;
            }
        }
    }
}
//----------------------------------------------------------------------------------

In affect, you can use any code that you have as long as you don't do any byte move for data or deep nested calls and call quickly "send(_sock, buf, size);"

You will get the same results as long as your client PC ist very powerfull too. (I am using a i7-6700K with the ASUS Z170-A.)

Best Regards,

Dieter

Paul Stoffregen

unread,
Dec 7, 2016, 8:25:56 AM12/7/16
to devel...@arduino.cc
It's great that you're sharing the insights you've gained from your own project, but as a benchmark it doesn't do me or anyone else much good if we can't run it.

Especially with these Wiznet chips, round trip latency and packet loss are a huge issue.  I've been testing TCP receive on my local ethernet and getting 1.1 MByte/sec speeds, communicating with an Apache2 server running on a Linux desktop, with the library running on a fast board using 12 MHz SPI.  You can find the benchmark code in the WebClient example on my github repository.

But the same benchmark achieves only about 95 or 200 kbytes/sec speed fetching from google.com, depending on whether delayed ACK and 2K or 4K buffers are used (you can find that alternate buffer code in a branch on my github repository).  So far I haven't set up any local tests with well controlled latency and packet loss, but that's something I intend to do soon.  The 1.1 MByte/sec tests show it's possible to achieve nearly the theoretical SPI throughput under ideal local ethernet conditions.  The buffer sizes and TCP ACK delay makes almost no difference.  But when used across the internet, those settings (at least as far as I've experimented so far) make at least a 2-to-1 performance change, and even the faster results aren't anywhere close to the performance seen on local ethernet with very low packet latency.

I understand why you can't share your code.  I do hope your project works out well, and even though it sounds like you've already found ways to achieve the performance you need (at least under the test conditions you're using), I hope my work here will help raise the performance even higher for you.

I hope you can understand why results from unpublished code without test conditions involving network latency are less than ideal for optimizing the library for general widespread usage.

Dieter.Burandt

unread,
Dec 8, 2016, 12:47:59 PM12/8/16
to devel...@arduino.cc
Hi Paul,

I took a half day to write an test application, that you can use. Ypu need a web client that understand HTML 5 download format like Firefox.

Keep in mind that time measure starts already before the last download page is displayed. So the speed is higher. For this use larger files, to get quite correct values.

I wrote this using the Arduino IDE. Normally I use the Visual Micro IDE with VS2015 that also uses limited code optimisation. I don’t know how to compile the Arduino libraries with the Arduino IDE. So I used Visual Micro to compile the Arduino libraries after changing the SPI speed for the Ethernet.

This software example is of course complete free.

 
In my fist mail I complained that it is not possible to alter e.g. the SPI speed and buffer sizes within the Arduino libraries from outside, e.g. by definitions in the header of the INO files. Okay, I can alter it, but if you use different boards with different settings it is not really possible. But the biggest problems are updates from Arduino, where I must be highly pay attention to integrate all patches. Here is my problem.

Best Regards,

Dieter

FileServer.zip

William Westfield

unread,
Dec 8, 2016, 9:14:24 PM12/8/16
to devel...@arduino.cc

> But the same benchmark achieves only about 95 or 200 kbytes/sec speed fetching from google.com, depending on whether delayed ACK and 2K or 4K buffers are used … when used across the internet, [buffer size and delayed ack setting] make at least a 2-to-1 performance change

Everyone understands that TCP has an inherent speed limit of one “window size” per “round-trip-time”, right? (where round-trip-time is time from packet sent until the transmitter gets a window update saying that the packet has been processed (which is NOT quite the same as an ack. But certainly the physical round-trip-time gives it a lower bound.))
So if it takes 100ms to do both the physical transmission/delay in each direction and there are 4kbytes of buffering that translates directly into the TCP window, you shouldn’t expect to get more than 40kbytes/s.

There are lots of things to play with, if you can diddle the internals of the TCP implementation. (“Optimistic windows”, modified delayed ACK, Silly-window-sydrome avoidance, Nagle and modified Nagle algorithms, tuning packet size vs buffer size, etc.) Unfortunately, I don’t think one has access to enough of the internals of the WizNet TCP implementation to experiment with these. Also unfortunately, most of the research and commercial attention that has been applied to TCP/IP over the years has been aimed at large-ish systems with gobs of memory. :-( (SOOOOO Frustrating. And I use it all as an excuse for not doing any networking in the microcontroller arena, even though that’s where by pre-retirement expertise lay.)

BillW/WestfW

Matthew Ford

unread,
Dec 8, 2016, 9:49:43 PM12/8/16
to devel...@arduino.cc, William "Chops" Westfield
As an aside, Adafruit's WICED arduino with integrated wifi can take an AtoD reading and sending it with the timestampe (uS) to TeraTerm on a PC  at  114K bytes/sec

Using buffered Adafruit WICED 1000 loops in:120mS -> Sample rate:8.33k samples/sec
Example data record:
29786629,1.25


On 9/12/2016 1:14 PM, William Westfield wrote:

William Westfield

unread,
Dec 8, 2016, 11:35:17 PM12/8/16
to devel...@arduino.cc
> Adafruit's WICED arduino with integrated wifi … 114K bytes/sec

I would hope that the Adafruit WICED, which has 128k of RAM, would have much larger TCP windows than a WizNet chip with only 32k…

Hmm. Now that there are all these “IoT” chipsets out there with built-in not-very-well-documented TCP implementations, it ought to be possible to “study” them using assorted probing techniques and packet traces and such Hasn’t anyone done this? (Shucks, I used to have to go through *every* checklist item in RCF1122/RFC1123 and say we supported it, planned to support it, didn’t think it was relevant (and why), or didn’t support it. REQUIREMENTS, after all! I don’t think I’ve seen anything like that for ANY of the embedded TCP processors. Why do modern implementors have it so easy? (Whine, Whine.))

BillW/WestfW

Adrian McEwen

unread,
Dec 9, 2016, 6:13:35 AM12/9/16
to devel...@arduino.cc
Ah, back when those of us writing IP stacks quoted the RFCs they
implemented. I remember those days :-)

I haven't seen any such docs for the WizNet chips, but I can tell you
the W5100 doesn't implement the Nagle algorithm :-( (as I found out
from poring over packet traces a few years back in a previous discussion
about the library - it's in this list's archives somewhere)

It's good to see such interest in moving the Ethernet library forward.
Sadly I don't have enough time to volunteer to help, and my paid
projects haven't taken me into Ethernet for a while (mostly WiFi and
mobile it seems these days). I'm still lurking though and will try to
chip in where I can...

Cheers,

Adrian.

>
> BillW/WestfW
>

William Westfield

unread,
Dec 9, 2016, 7:05:58 AM12/9/16
to devel...@arduino.cc

> back when those of us writing IP stacks quoted the RFCs they implemented

A former co-worker recently pointed out that there are now over 8000 RFCs !!!


> I can tell you the W5100 doesn't implement the Nagle algorithm

Nagle is somewhat deprecated, wasn’t particularly relevant on Ethernet, reacts really strangely with delayed ack if you’re not careful, and is sort-of subsumed by slow-start anyway. I don’t know if you could tell whether a chip with 4k of buffering is supporting slow-start or not :-(

(The “Nagle Algorithm” was for preventing a slow data source (ie Telnet, with a user) from sending large numbers of minimum-sized TCP packets (41 bytes) on slow connections (because using 40 bytes of your bandwidth to send 1 byte of data is … not good.
“delayed ack” is similar - when you receive a byte of data, you can theoretically ACK that right away (40 bytes.) And then when the application reads it, you can update the window (another 40 bytes.) And then if there’s data in the other direction (like echoing your type-in on a telnet connection) you can do it all again in the other direction. But if you are just a bit more patient, you can delay sending the ACK until the echo is sent, and you only have to send one 41 byte packet instead of of three.
“slow start” is mostly for avoiding network congestion. It seems that if you’re on a fast ethernet and a connection has opened to a host far away, and it has advertised a big (say, 64k) window, it is a BAD idea to immediately send 64k worth of data in that direction. Because even though you’re on an ethernet, there might be slower links in between you and the other host. Instead, you start sending packets slowly, and use the round-trip times to help estimate the bandwidth that is actually available. (The original paper on this was brilliant!)
The point is that TCP/IP isn’t just ~35years old. It has 35years of REFINEMENTS, and they’re mostly backward compatible and it can be hard to detect whether an implementation is up-to-date.)

WICED/Wifi apparently uses FreeRTOS and lwIP, which is open source and pretty popular, so hopefully it’s relatively up to date. The Wiznet chips are really opaque, though, and I have no idea about ESP8266/etc.

BillW

Adrian McEwen

unread,
Dec 9, 2016, 7:53:59 AM12/9/16
to devel...@arduino.cc
On 09/12/16 12:05, William Westfield wrote:

[snipping stuff to try not to derail this thread too much from the good
perf discussion that was happening earlier :-)]
>> I can tell you the W5100 doesn't implement the Nagle algorithm
> Nagle is somewhat deprecated, wasn’t particularly relevant on Ethernet, reacts really strangely with delayed ack if you’re not careful, and is sort-of subsumed by slow-start anyway. I don’t know if you could tell whether a chip with 4k of buffering is supporting slow-start or not :-(
>
> (The “Nagle Algorithm” was for preventing a slow data source (ie Telnet, with a user) from sending large numbers of minimum-sized TCP packets (41 bytes) on slow connections (because using 40 bytes of your bandwidth to send 1 byte of data is … not good.
Indeed. That was the exact criticism being levelled at the Ethernet
library, and I'd assumed Nagle would prevent it; did some tests (I can't
remember details of exactly what, would have to dig out the old thread),
and found that it didn't.

[snip]
> WICED/Wifi apparently uses FreeRTOS and lwIP, which is open source and pretty popular, so hopefully it’s relatively up to date. The Wiznet chips are really opaque, though, and I have no idea about ESP8266/etc.
I haven't needed to dig that far yet, but did spot some traces of lwIP
in the Arduino ESP8266 port, so hopefully that's a good sign.

Cheers,

Adrian.

Dieter.Burandt

unread,
Dec 9, 2016, 10:22:27 AM12/9/16
to devel...@arduino.cc
Let's find back to the original discussion:

Originally we talk about an interface with the Wiznet W5100 and an
potentially upcoming W5500 and the Arduino libraries.

The current mails run a discussion about typically PC like configuration
running a highly optimised CPU with one or more kernels running at 3GHz
and even more and consuming something like a 100W. That is all true what
you say, but it is has nothing to do with the world of microcontrollers
and Ethernet chip with a fixed firmware.

Let tell me about the trouble and fixes that I had and so give me an
idea where are the problems of an Ardino user:

1. When I started with my project with an Arduino Due and an Ethernet
R3 board, I run into trouble to understand the CS-pin settings on
initialisation: There was no hint, that the Arduino Due is using a
second CS-pin for SD-card and the Ethernet and was initialised false.

2. I decided to use the WebDuino library. I run directly into trouble
because of incomplete examples and missing hints how to handle multiple
calls more than a very few pages. Very interesting features are not or
nearly not documented.

3. I tested the speed, the web pages are transferred. It was too
slow. I changed the SPI speed from 4MHz to 14MHz. I changed my code not
to sprint() if there are data only copied from the flash to the buffer.
Now the speed was okay.

4. Adding of logging to the SD-card I implemented a battery buffered
SDRAM to cache the log data on write. The data are written normally only
once a day after a reboot to the SD-card. One file per day in a path
structure YYYY/MONTH/DAY/fd.ext.

5. Reading the 356 files of a year to send it as one file was too
slow (some Minutes). I changed the Arduino- SD-library running with an
SPI-speed of 42MHz. The speed is now aceptable.

6. With the current discussion I looked again into the code and found
bad written code. In WebDuino I used a call that moves the data byte by
byte from my big buffer to a 32 byte buffer and writes it to the W5100.
Changing the code using a 1kB-buffer without an intermediate byte move
give again a speed upgrade of around 30%.

Ethernet and SD-card is definitely okay now. To be faster on download
would be nice to have. Updating complex web pages is no problem in
second intervals. The download could be a bit faster.
The small benchmarks and code shows where the problems are.

In addition to the above patches to the Arduino library, I had to patch
the size of the Ring buffer (UART) and the I2C-speed to my EEPROM. (None
standard devices needs special settings and patches to the library.)

The main problem is that the most Arduino libraries are designed for
8-bit CPUs with low speed and low memory. A 32-bit ARM-CPU and
user-hardware requires patches to the Arduino library. If you have
various projects with different hardware and you get updates to the
Arduino libraries, it is not only a lot of work to add the patches again
and again, it is also very prone to errors.

It would be great, if the user can overwrite the speed settings and
buffer sizes in the libraries from within the ino file.

Best Regards,

Dieter

Cristian Maglie

unread,
Jan 27, 2017, 6:06:29 AM1/27/17
to devel...@arduino.cc
Il 01/12/2016 21:04, Paul Stoffregen ha scritto:
> Please hold off merging #2325.
>
> I'm working on a much more optimization and many small improvements.
> Even for cases where the bandwidth to a remote site (with network
> latency) isn't improvement, these changes dramatically reduce the amount
> of CPU time consumed by the Ethernet library. For real applications,
> that will turn into more CPU time to actually use the incoming data or
> generate the outgoing data, allowing more of them to actually achieve
> those speeds.

Hi Paul,

how are going the experiments?

There is too much confusion around the many Ethernet libraries available
now and I need to solve this problem ASAP (currently I'm leaning toward
merging #2325).

C


--
Cristian Maglie <c.ma...@arduino.cc>

Phillip Stevens

unread,
Jan 27, 2017, 6:50:57 AM1/27/17
to Developers
On Friday, 27 January 2017 22:06:29 UTC+11, Cristian Maglie wrote:
> Please hold off merging #2325.

Poking around in the #2325 code, and the master Ethernet repository, I can't find any handling of the Wiznet Errata #2 and #3 in the W5100 and W5200 chips.
Or, have I over looked the resolution?

Both of these devices need the programmer to provide an off-chip Subnet mask address, otherwise their ARP functionality doesn't work.
This is noted in Wiznet Errata v2.3 Items 2 & 3 from March 2012, and code examples are provided to provide the repair.

This ARP subnet mask issue is finally resolved, and is not present in the W5500.
I confirmed this in conversation with Wiznet staff in 2014, and by testing.

Phillip



Paul Stoffregen

unread,
Jan 27, 2017, 3:56:25 PM1/27/17
to devel...@arduino.cc
Cristian,

I wish I could say I'm completely finished with Ethernet, but like all
substantial software, the reality is one of ongoing maintenance and a
list of desired features that seems to grow about as fast as things are
implemented. My redesign is at a pretty usable state. It's been
published to all Teensy users for months and so far all feedback is
good. I haven't done anything more on it for the last several weeks.

I've heard from several people who've used it successfully on non-Teensy
boards, where it gives about a 6X performance improvement with the
regular W5100-based Arduino Ethernet shields. Of course, with the newer
W5200 & W5500 chips the performance is *much* better. While there's
plenty of things left to do, including the Wiznet errata Phillip
mentioned, I believe it's as good as the existing version. It has the
features of #2325, except for the getMaxSockets(), which would be
trivial to add. Here's the code:

https://github.com/PaulStoffregen/Ethernet

However, my work on Ethernet is a major redesign. If you adopt this for
the official Arduino software, perhaps we should call this version
2.0.0? I should probably get more directly involved in its ongoing
maintenance. While I'm currently preoccupied with USB host on EHCI
(which is turning out to be very difficult), I do intend to get back to
Ethernet in a month or two, to work on several long-requested features.

If you'd prefer a more incremental approach that doesn't substantially
change the Ethernet library design, then merge #2325. I totally
understand how risky a massive redesign can seem, so really it's
perfectly fine if you choose #2325. My version will remain on github
when/if you or anyone else wants it.

Sorry I can't do more at this very moment. This EHCI stuff really is
consuming all my spare cycles right now. If you do decide to adopt my
redesign, I'll try to help a bit now, and in a couple months I'll work
on that Wiznet ARP errata and a few of the long-requested features.


-Paul

Phillip Stevens

unread,
Jan 27, 2017, 10:20:16 PM1/27/17
to Developers
If you'd prefer a more incremental approach that doesn't substantially
change the Ethernet library design, then merge #2325.

WRT, the Wiznet Errata #2 & #3, and also #1 for that matter, I have code derived from their BSD sockets style example code in 'C'.

 * 03/13/2012 1.6.1 Added clearSUBR(), applySUBR() and modified setSUBR() functions
 
*                  because of the ARP errata.
 
*                  Keep SUBR 0.0.0.0 unless using TCP connect() or UDP sendto()
 
*                  Use the SUBN_VAR variable to read the real subnet.

These new functions maintain an off-chip Subnet mask, which is only applied as noted above.

// the ARP errata fix, only relevant to W5100, W5200
static un_l2cval SUBN_VAR; // off-chip subnet mask address - solve Errata 2 & 3 v1.6 - March 2012

I'd prepare a pull request, but I'd write non-optimal 'C++' code. Better to leave it to experts.

In 'C' it looks like this in w5100.c

void saveSUBR(
 un_l2cval
* addr /**< a pointer to a 4 -byte array responsible to set the SubnetMask address */
 
)
{
 
// write to off-chip subnet mask address - solve Errata 2 & 3 v1.6
 
// Basically the hardware ARP engine is broken, unless it is set to 0.0.0.0
 
// so we have to keep it so, unless we're using TCP connect() or UDP sendto()
 SUBN_VAR
.lVal = addr->lVal;
}

void setSUBR(void)
{
 
// apply off-chip subnet mask address - solve Errata 2 & 3 v1.6
    WIZCHIP_write_buf
(SUBR0, SUBN_VAR.cVal, 4);
}

void clearSUBR(void)
{
 
// clear on-chip subnet mask address - solve Errata 2 & 3 v1.6
    WIZCHIP_write_buf
(SUBR0, 0x00, 4);
}

void getSUBR(un_l2cval *addr)
{
 
// get off-chip subnet mask address - solve Errata 2 & 3 v1.6
 addr
->lVal = SUBN_VAR.lVal;
}

and in socket_util.c the request is faked (inefficiently, but works for all hardware versions) like this.

/**
@brief Get Subnet mask of W5100/W5200.
@return Subnet Mask(32bit Address-Host Ordering)
*/

uint32_t
GetSubMask(void)
{
 uint32_t ip
= 0;

#if   (_WIZCHIP_ <= 5200)
 setSUBR
(); // apply subnet mask address - solve Errata 2 & 3 v1.6
#endif

 ip
=             WIZCHIP_read(SUBR0);
 ip
= (ip << 8) + WIZCHIP_read(SUBR1);
 ip
= (ip << 8) + WIZCHIP_read(SUBR2);
 ip
= (ip << 8) + WIZCHIP_read(SUBR3);

#if   (_WIZCHIP_ <= 5200)
 clearSUBR
(); // clear subnet mask address - solve Errata 2 & 3 v1.6
#endif

 
return ip;
}

Perhaps, that's a start.

Paul Stoffregen

unread,
Jan 30, 2017, 7:00:11 AM1/30/17
to devel...@arduino.cc
Has anyone created a test sketch for this Wiznet errata?

I think I understand the errata and what I should do in the code.  Before patching the library, I'd really like to reproduce the actual problem, so I can test whether the fix is truly effective.

If anyone has created a program that reliably reproduces the problem, that could save me some time.  If not, I guess I'll have to do it myself, or decide to blindly apply the patch without testing.  I really don't like the idea of not testing.
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.


Andrew Kroll

unread,
Jan 30, 2017, 8:15:22 AM1/30/17
to devel...@arduino.cc
(off topic)
@Paul: If I dual license my USB work, are you willing to collaborate?
I already have much of the EHCI bits, and perhaps you could also help out with a few other issues I am encountering on your products.
I've already granted one dual license to BSD type license.
The driver collection will be very extensive too, everything that is in UHS2.0
Don't hesitate to contact me with a private email or on your forum.



--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Paul Stoffregen

unread,
Mar 19, 2017, 5:47:50 PM3/19/17
to devel...@arduino.cc
Phillip,

Sorry about the really long delay.  I finally got around to implementing this Wiznet ARP subnet mask errata in the Ethernet library.

I have 2 quick questions.

#1 - I couldn't get TCP or UDP clients to work with zeroing the subnet mask immediately after the socket CR register confirms the last command, as Wiznet's instructions and pseudo-code says.  I tested on both W5100 & W5200.  It simply doesn't seem to work.  I had to delay this until after the socket status actually updates.

Here's what I wrote that seems to work.  See the comments I added about the possible places to re-zero the subnet mask.  Any thoughts?

https://github.com/PaulStoffregen/Ethernet/commit/e99bc404d30d67a1b0e7941ba1a1ec4b43597bbb

#2 - Can you recommend a way to actually test for this ARP errata?  I would really like to be able to reproduce the problem with the old code, and then see the fix work.  Would also really like to confirm W5500 works.

How are you testing this?  Do you have any sketch to share?  Or maybe scripts to run on a server to do the ARP queries?  Or anything to save me a little time trying to figure out how to test for this bug and make sure the fix truly is effective?


Thanks,
-Paul
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.


Phillip Stevens

unread,
Mar 19, 2017, 6:23:38 PM3/19/17
to devel...@arduino.cc
Paul,

My implementation was quite simple, written in C and derived from the Wiznet drivers. Once it was working for UDP and TCP, on both W5100 and W5200, I didn't test any further.

I'll connect you to the Wiznet engineer directly, because they would have done the testing, and would be able to comment more intelligently.

Cheers, Phillip

___________________________________________
Phillip Stevens
GSM: +61 4 3322 0688
mailto:phillip...@GMail.com
Key: E0E09601
___________________________________________

To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.


--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Paul Stoffregen

unread,
Mar 20, 2017, 1:10:50 AM3/20/17
to devel...@arduino.cc, wiznetian
On 03/19/2017 03:23 PM, Phillip Stevens wrote:
Paul,

My implementation was quite simple, written in C and derived from the Wiznet drivers. Once it was working for UDP and TCP, on both W5100 and W5200, I didn't test any further.

I see your code also waits to zero the subnet mask.  According to the Wiznet errata, you'd zero it right after SnCR reads zero/false, which would be at line 224:

https://github.com/feilipu/avrfreertos/blob/master/freeRTOS9xx/lib_iinchip/socket.c#L224

But you've got the subnet clear down at line 238, after waiting for the socket status to change.

Before publishing this on the main branch of my copy of Ethernet, which may or may not someday be adopted as Arduino's official library, I'd really like to create a test which actually reproduces this problem with the old code and confirms the fix is effective.


To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.


Phillip Stevens

unread,
Mar 20, 2017, 1:38:15 AM3/20/17
to devel...@arduino.cc, wiznetian

My implementation was quite simple, written in C and derived from the BSD Wiznet drivers. Once it was working for UDP and TCP, on both W5100 and W5200, I didn't test any further.
I see your code also waits to zero the subnet mask.  According to the Wiznet errata, you'd zero it right after SnCR reads zero/false, which would be at line 224:

https://github.com/feilipu/avrfreertos/blob/master/freeRTOS9xx/lib_iinchip/socket.c#L224

But you've got the subnet clear down at line 238, after waiting for the socket status to change.

Before publishing this on the main branch of my copy of Ethernet, which may or may not someday be adopted as Arduino's official library, I'd really like to create a test which actually reproduces this problem with the old code and confirms the fix is effective.

I followed along with the implementation provided by Wiznet in their BSD socket driver examples.

If that's the way they've implemented it there, there's a good chance that they did it right.
There is a more modern example of the solution in their V3.0 code here:

I suggest the person mentioned, who's email address I've provided off forum, could provide further test examples.

Cheers, Phillip


Reply all
Reply to author
Forward
0 new messages