Adding a W5500 ethernet adapter to Zephyr (ESP32)

Introduction

The ESP32 family is a very popular platform for getting started with Zephyr. It is cheap, easy to obtain and offers integrated WiFi connectivity. It’s also the reference board for the Mender MCU client.

But there are times when WiFi doesn’t cut it, right? Sometimes you just want a plain old wired connection.

Good news is that Zephyr offers a rich variety of drivers for hardware support. Amongst these is the W5500, specifically as a shield such as ARCELI W5500 ETH — Zephyr Project Documentation.

We will use a slightly miniaturized variant, but as they all behave identical just pick whichever is easy to obtain for you.

Prerequisites

To follow this tutorial, you need a Zephyr workspace matching your board already set up. We will use the ESP32-S3-DevKitC, so you can just follow the Getting Started tutorial to prepare everything required.

Given this setup, we will build the mender-mcu-integration target. If you want to use a different one, please adapt the paths of the created files and build invocation accordingly.

Use ethernet instead of WiFi

Making the connection

The W5500 requires a number of connections. A power supply, SPI port and two GPIO lines for reset and interrupt. Below is a suggestion which is known to work as a starting point:

W5500 V -> J1-Pin 1 / 3.3V
W5500 RES -> J1-Pin 5 / GPIO5
W5500 MI -> J1-Pin 19 / GPIO13
W5500 INT -> J1-Pin 4 / GPIO4
W5500 CS -> J1-Pin 16 / GPIO10
W5500 SCK -> J1-Pin 18 / GPIO12
W5500 MO -> J1-Pin 17 / GPIO11
W5500 G -> J3-Pin 1 / G

An example setup might look like that:

Port configuration

In order to access the new peripheral from Zephyr, it must be configured accordingly in the so-called device tree. This is a build time mechanism to declare the available hardware, usually focused on the peripherals which extend a specific base board. We will only use the overlay mechanism, which is meant for exactly that use case.

Create a file called mender-mcu-integration/my_w5500.overlay with the following content:

&spi2 {
  status = "okay";
  eth_w5500: eth_w5500@0 {
    compatible = "wiznet,w5500";
    status = "okay";
    reg = <0x0>;
    spi-max-frequency = <8000000>;
    int-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
    reset-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
    /* *************************** */
    /* Write here your MAC address */
    /* *************************** */
    local-mac-address = [00 08 DC 01 02 03];
  };
};

Thats quite a mouthful, so lets break it down a bit.

First, the SPI port is enabled. Unless some other peripheral or overlay is already doing the same, the default for status is "disabled". Overlays are merged down, so the last one “wins”. Hence, a common practise is for the base device tree definition to only activate the absolute minimum of peripherals to boot and run a specific board. Overlays then only do enable the pieces they require. In our case for spi2 this is:

&spi2 {
  status = "okay";
  ...
}

Next we define the ethernet peripheral we want to use. The important parts here are first the compatible string, which defines the driver to be used. There is somewhat complex matching involved, but it shall suffice here to say that if a string here matches the string which a driver provides, then the driver is instantiated for this instance. And second, of course, is to enable the peripheral explicitly as we do want to use it.

eth_w5500: eth_w5500@0 {
  compatible = "wiznet,w5500";
  status = "okay";
  ...
};

There are a few more detailed settings which are required. The most important ones are:

int-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
local-mac-address = [00 08 DC 01 02 03];

Those configure the GPIO lines for the interrupt and reset lines, and provide the MAC address to be used.

After this, the Zephyr networking stack needs to be configured.

Enabling the driver

Zephyr uses the Kconfig configuration system which was originally created for the Linux kernel. It is based on configuration files which define all desired CONFIG_* statements and therefore reasonably convenient to read. However modifying them directly is not recommended unless you are very familiar with the inner folkings of the concerned subsystem because there are a lot of dependencies are mutual exclusions amongst options. Therefore, use the west -b menuconfig facility to this avail.

The resulting configuration files do not necessarily have to be full-featured and covering all possible options. Just like for the device tree, additional fragments are the equivalent of overlays here. Those can be used to add specific parts to a base configuration, and we will also use this.

Create a file mender-mcu-integration/my_w5500.conf with the following content:

CONFIG_WIFI=n
CONFIG_SPI=y
CONFIG_NET_MGMT=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_ETH_W5500=y
CONFIG_ETH_W5500_TIMEOUT=1000

This has a number of effects:

  • SPI support is added by enabling the corresponding subsystem

  • WiFI support is disabled. Technically you could have both at the same time, but for ease of use we “force” the network stack to ethernet in this tutorial

  • ethernet and the corresponding link management support are enabled

  • the W5500 driver is enabled and configured for a slightly longer timeout than default

Build and flash

The last thing remaining is to build. Being based on the mender-mcu-integration setup, the invocation could be this:

west build --sysbuild -board esp32s3_devkitc/esp32s3/procpu mender-mcu-integration -- \
-DEXTRA_CONF_FILE=mender.conf \
-DEXTRA_CONF_FILE=my_w5500.conf \
-DEXTRA_DTC_OVERLAY_FILE=my_w5500.overlay
-DCONFIG_MENDER_ARTIFACT_NAME=\"w5500\"

If you are using a different project, adjust board and target accordingly, and disregard the mender.conf fragment.

Flash the board, and watch it connect:

west flash && west espressif monitor

will print something similar to

[1970-01-01T00:00:01,714000Z] <inf> eth_w5500: eth_w5500@0: Link up
[1970-01-01T00:00:07,246000Z] <inf> net_dhcpv4: Received: 192.168.89.36

early during boot. Probably with a different IP address. :slight_smile:

Conclusion

Zephyr offers a number of building blocks which make it very easy to add new peripherals to an existing board:

  • the Kconfig configuration system and its fragments

  • device tree description of the hardware and its overlays

  • an extensive and growing ecosystem of subsystems and drivers

This tutorial can be used as a blueprint to connect and use a lot of other peripherals. So what will you build next? Let us know!

2 Likes