Wiznet W5500 support

Epyon

Well-known member
Does Teensyduino (with T3.1 as target board) natively support the W5500 chip? The W5500 is again a nice upgrade compared to the previous iteration of the Wiznet chip. More RAM available when using limited sockets, lower power consumption and it even makes the TX&RX RAM available to the mcu. It's also more suitable for 32bit mcu's, packing the addressing and control information into one 32 bit register. However the SPI protocol now omits frame length, indicating end of transmission by raising the CS line. Since I don't have my hands on a W5500 (yet), I'm not sure if this could be a problem.

Wiznet has an Arduino library, but maybe the W5500 support can be added to the Ethernet library?
 
*bump for great success*

I'm using the Adafruit Ethernet2 for W5500 chips now, but maybe this could be merged into the Ethernet lib that comes with Teensy, seeing how the 5500 performs somewhat better than the 5100/5200.
 
I recently bought a couple W5500s for testing. Probably won't integrate it into the library until late summer, but at least it's on the long-term plan.

How does W5500 perform better than W5200? It seems to be the same in every way, except an extra byte of protocol overhead, and lower physical power consumption.
 
It's a lot better than the W5100, and cheaper than the 5200 is what I meant :) .
 
Yeah, W5100 is really horrible over SPI, but it's actually pretty fast in 8 bit parallel bus mode, when used with a chip that does the chip selects and strobes and read/write in a single load/store instruction.

My guess is the original W5100 was probably designed by very good engineers a very long time ago with 8051 chips in mind, and a terrible SPI bus interface was bolted on by junior level people. The experts almost certainly wrote the original socket layer code with the parallel bus in mind. Since then, the microcontroller market moved away from memory buses, and Wiznet seems to have recycled the same basic design with the SPI interface. Judging by the chip's bugs with reset and MISO drive, I'm guessing these changes haven't been made by the highly skilled engineers who must have designed the original chip.

Since then, it seems nobody has really looked at the design decisions in that code in the context of slower SPI bus. It reads many registers for every operation, which makes sense if you can access a register with a single instruction. But with SPI bus, reading the registers takes many hundreds of cycles. Especially for TCP with simple code that moves 1 byte at a time (as pretty much all the Arduino examples do), there's massive register reading overhead for every single byte! This is true with W5200 & W5500. Wiznet's code doesn't even try to leverage the burst modes to read both bytes of 16 bit registers. It's pretty amazing they put so little work into the software side, which could vastly improve their product's performance.

A couple months ago, I did quite a bit of code restructuring and storing of the socket state on the Teensy side. That costs some extra RAM on the Teensy side, but it allows skipping many slow register reads, because their values are remembered in variables on Teensy. It make a pretty dramatic speedup for reading TCP data. UDP ends up about the same if you're reading the whole packet all at once, but it helps if you read the packet in small chunks. Unfortunately we don't yet have timer events from the Teensyduino core library, so transmitting TCP is harder to optimize, because I can't leave buffered data in place and have a reliable way to auto-flush it if the program doesn't keep calling the library's functions.

Eventually I'll put W5500 code into the lowest level and test with these boards. And someday in the more distant future, I'm going to add an event notification system to the core library. Then I'll be able to really optimize the TCP transmit. But that day is months, maybe even years away...
 
Another useful tweak could be to make the DHCP configuration non-blocking. The current Ethernet.begin() waits for, iirc, 60 seconds before timing out and letting the rest of the code run. It would be much better if this was non-blocking and you could poll the IP configuration status in the main() loop. This would prevent problems where a Teensy and a router are power cycled together, but the router isn't fully booted by the time the Ethernet.begin() times out. I have a lot of these problems unfortunately, and my current not-so-elegant solution is to put a delay of about 30s before begin(). I could use some of the non-blocking libs that are floating around the internet, but they are based on older iterations of the Arduino Ethernet lib and are not maintained :( .
 
The W5100 code I wrote a couple of years ago for an NXP LPC ARM 7 used a tight loop to read or write the data buffers on the 5100, via SPA. If I recall, that SPI was limited to 4Mbps; no DMA. Seemingly slow, but more than fast enough with the tight loop, for the application's needs - not streaming, just a few UDP packets for telemetry and an occasional TCP connection for FTP passive mode for firmware updates and transfer of small files.

I used static LAN IP addresses due to the need for the router to port-forward to a specific IP address since there were incoming UDP packets (connection-less) - thus to use DHCP there'd have to be a fixed IP reservation in the DHCP server and that was not permitted by the LAN admin people. So they let me use a private VLAN off their switch so I could use a non-DHCP static IP.

Hard enough to get the port-forward setting established! Due to firewall policy, I later had to change from UDP to TCP and that was a lot more overhead - esp. since the WAN was 3G cellular with 600mSec latency in the busy hour. (far better now with 4G LTE but the carriers are now double-NATing so TCP is essential.) And the latency caused TCP ACK timeouts sometimes, due to TCP windowing. The only way I could deal with this was to disable windowing and use an ACK per packet which cost a lot in speed with the high latency. But most of my embedded work does not need high WAN speeds or packets/second rate; just telemetry.
 
Last edited:
Another useful tweak could be to make the DHCP configuration non-blocking. The current Ethernet.begin() waits for, iirc, 60 seconds before timing out and letting the rest of the code run. It would be much better if this was non-blocking and you could poll the IP configuration status in the main() loop. This would prevent problems where a Teensy and a router are power cycled together, but the router isn't fully booted by the time the Ethernet.begin() times out. I have a lot of these problems unfortunately, and my current not-so-elegant solution is to put a delay of about 30s before begin(). I could use some of the non-blocking libs that are floating around the internet, but they are based on older iterations of the Arduino Ethernet lib and are not maintained :( .

For a non-blocking ethernet library that works with Teensy and W5100/W5200 I'd like to refer you to this thread.
 
Oh yeah, I remembered i tried this library before, but I thought it was based on the older version by Davy Landman. Didn't see you converted it to using SPI transactions.

What's in your macaddress.h file?
 
It's the code posted by Gene_R in post #10 in this thread This basically reads out the unique ID of each Teensy board and uses it as the ethernet mac address.
 
Looks like the continuous polling of the DHCP lease breaks DNS resolving. When you have successfully acquired an IP and then start a client.connect(hostname, port), the library apparently fails to parse the UDP packets coming from DNS.
 
Okay, I was just trying to use client.connect(hostname, port) while this has been made non-blocking too. Apparently you have to use client.initConnection(hostname, port) first, but I'm at a loss of what has to be done after that. Check client.connected()? Would you have any pointers on this, Headroom? Thanks!
 
UDP of course is connection-less whereas TCP is connection based. A UDP session for the client is to create a socket and send a packet in UDP protocol to the agreed-to port number at the destination IP address.
DNS as I recall uses UDP and a non-trivial protocol of UDP packet exchanges. The DNS server listens on a well known port number. Practically speaking, one needs to start with source code for a DNS client and adapt to the ethernet or WiFi link in use.

So too, DHCP, and it can use a UDP broadcast into the subnet to try to discover the LAN IP address of a DHCP server, or presume that the gateway's LAN IP also has a DHCP server.

Microsoft has a semi-connection based UDP socket connection just so it can report that no server is listening on that IP/port. It's been confusing to me as it violates the intent of UDP.
 
Last edited:
Cool there is a active thread about the W5500.
Since i got my fist Teensy now and have 3 W5500 here since a view weeks i want to use them for the first time.
I did open a thread in the Arduino forum and made some power measurements: http://forum.arduino.cc/index.php?topic=367999.msg2595043#msg2595043
Nobody was interested...
W5100 unplugged = 186mA
W5100 @ 100M = 163mA
W5100 @ 10M = 153mA
W5500 unplugged = 74mA
W5500 @ 100M = 136mA
W5500 @ 10M = 81mA
Main reason for that thread was i did read the chip has WoL.

Back 2014 somebody did write about the SPI efficient of the W5500: http://forum.arduino.cc/index.php?topic=217183.0
Not much there since then. I wonder because if this chip is out there so long.
I'm no coding expert - but with the fast Teensy and a W5500 maybe it's possible to reach ludicrous speed: https://www.youtube.com/watch?v=mk7VWcuVOf0

EDIT
Wow! MQTT works right out the box with the Adafruit lib.
Now i have to check this "unique ID of each Teensy board and uses it as the ethernet mac address" thing - because i was using the Dallas DS18B20 the whole time for generating the mac address.

I have an INT Pin on my NICs. Somebody knows what it is?
 
Last edited:
Wiznet has long used an old 8051 power hog (they told me long ago). Apparently even the latest W5500 still uses that. Wish they'd go to an ARM Cortex.

I had a project with 100+ boards in the field in several continents, linking back on cellular. Ethernet connected to a small router. These just ran and ran. I admire the stability of the Wiznet stack.
 
Last edited:
What do you guys do to check the physical connection? Cable not plugged in or damaged?
What i did was soldering a cable to that 100M indication LED on the Arduino Ethernet shield and connected it to a digital pin.
Problem is that it does not work if you want to switch to 10M (for power saving).
 
On the WIZ820io, just plugging the ethernet cable in causes the link active LED to come on. I haven't used the W5500 yet, but I assume it does the same? That's a good first sanity check.

These Wiznet chips use a couple hundred mA of current. If Teensy is running by normal USB power, it should work fine. But if running from an unpowered hub, you might not have enough power. I'd suggest checking the 3.3V power, both on Teensy and on the module.

Also, pay close attention to the messages Arduino prints. Turn on verbose info in File > Prefs if needed. You want to make sure Arduino really is using the copy of the library you've installed for the W5500. If Arduino uses the regular library, your code might compile but can't work because it tries to use the W5100 or W5200 only.

You might also consider the reset signal. For troubleshooting, run a wire from a pin and add code to pulse the pin low briefly, and then wait 500 ms after the reset is high before you try to initialize the W5500. All these Wiznet chips need a reset. On Arduino Uno, the USB chip pulses the reset. On other Arduino boards, lack of a proper reset is a real problem! On the adaptor PJRC sells, pin 9 is used. If your W5500 isn't being reset properly, it might not work, even if you're doing everything else correctly.
 
Yeah, W5100 is really horrible over SPI, but it's actually pretty fast in 8 bit parallel bus mode, when used with a chip that does the chip selects and strobes and read/write in a single load/store instruction.
<snip>
Eventually I'll put W5500 code into the lowest level and test with these boards. And someday in the more distant future, I'm going to add an event notification system to the core library. Then I'll be able to really optimize the TCP transmit. But that day is months, maybe even years away...

Thanks for that detailed analysis. I am finally at the point where I need to write code to support a Teensy 3.2 system connecting to a PC which keeps a SQLite database of environment settings, configurations, trouble logs, etc, so I have been looking around among the myriad of W5500 and WIZ850io libraries (our board accepts that module) and came back to this thread. What is the status of W5500 support in the Teensy core libs? Thanks, and it was great to finally meet you (Paul) at the OSHWA summit earlier this month in Portland!

Update: Adafruit Ethernet2 library from Github seems to be working well, I am running DhcpStressTest with library changed to Ethernet2, ran all night.

W5500 test code is here: https://github.com/systronix/W5500_Test
 
Last edited:
I've started working on W5500 support. Here are files to use with TD 1.31-beta3. They go into hardware/teensy/avr/libraries/Ethernet.

If you try these with a W5500 chip, please let me know how they work for you?
 

Attachments

  • w5100.cpp
    13 KB · Views: 495
  • w5100.h
    11.3 KB · Views: 432
Excellent! I just finished some devices that use a Wiz5550io, I'll try it as soon as I'm back from holiday this weekend.

PS: is this still a blocking version (see post #7)?
 
I didn't change DHCP or any other protocol-level stuff. This only adds W5500 support at the lowest level, so the library can auto-detect and use and of the 3 wiznet SPI chips.
 
@forum-readers, I'm curious and want to learn... I've used the WIZ820io only. What are you using that needs W5500 support? Should I consider that for new designs?
 
Back
Top