Building MicroPython for the Raspberry Pi PICO with Ethernet and WebREPL support

WizNet is offering a low-cost Raspberry Pi PICO with Ethernet: the W5100S-EVB-Pico at about 9 dollars worldwide. For example, it can be purchased at Digikey here. There are firmwares ready to download and use based on MicroPython and CircuitPython. I used this one and it worked fine:

https://github.com/Wiznet/RP2040-HAT-MicroPython

However, some features I really wanted and needed were not available on this build. So let’s build ours.

Quick solution

This post discusses several issues and steps to compile and use Ethernet for Raspberry Pi Pico. For a ready-to-use quick solution, just go to:

Compiling MicroPython

Building MicroPython for the Raspberry Pi Pico is very easy and well documented. The best resource and guide I found is the official documentation from the Raspberry Pi Foundation using the document Raspberry Pi Pico Python SDK:

As explained in the above document, the commands to build Raspberry Pi Pico are:

mkdir pico
cd pico
git clone -b master https://github.com/micropython/micropython.git
cd micropython
git submodule update --init -- lib/pico-sdk lib/tinyusb
sudo apt update
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential
make -C mpy-cross
cd ports/rp2
make

After the build is done, the firmware built (firmware.uf2) will be available at the directory build-PICO.

Now we can install picotool to check the modules included as builtins in the firmware. picotool install is explained here:

mkdir pico
cd pico 
git clone -b master https://github.com/raspberrypi/pico-sdk.git
git clone -b master https://github.com/raspberrypi/picotool.git
cd picotool
sudo apt-get install libusb-1.0-0-dev
mkdir build
cd build
export PICO_SDK_PATH=~/pico/pico-sdk
cmake ../
make

Before running cmake ../, edit CMakeFiles.txt and add:

install(TARGETS picotool RUNTIME DESTINATION bin)

install(TARGETS picotool RUNTIME DESTINATION bin)

This solved a compilation bug for me, as reported here.

Now we can use picotool with the built firmware:

./picotool info /home/rafael/builds/pico/micropython/ports/rp2/build-PICO/firmware.uf2 
File /home/rafael/builds/pico/micropython/ports/rp2/build-PICO/firmware.uf2:

Program Information
 name:            MicroPython
 version:         v1.18-128-g2ea21abae
 features:        USB REPL
                  thread support
 frozen modules:  rp2, _boot, ds18x20, onewire, dht, uasyncio, uasyncio/core,
                  uasyncio/event, uasyncio/funcs, uasyncio/lock,
                  uasyncio/stream, neopixel

This default configuration lacks some important modules. MicroPython allows us to add other modules by editing the manifest file:

File vi rp2/boards/manifest.py original contents is:

freeze("$(PORT_DIR)/modules")
freeze("$(MPY_DIR)/drivers/onewire")
freeze("$(MPY_DIR)/drivers/dht", "dht.py")
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
include("$(MPY_DIR)/drivers/neopixel/manifest.py")

We have to edit it and add some lines, so manifest.py will have these contents:

freeze("$(PORT_DIR)/modules")
freeze("$(MPY_DIR)/drivers/onewire")
freeze("$(MPY_DIR)/drivers/dht", "dht.py")
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
include("$(MPY_DIR)/drivers/neopixel/manifest.py")

freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
include("$(MPY_DIR)/extmod/webrepl/manifest.py")

# Libraries from micropython-lib, include only if the library directory exists
if os.path.isdir(convert_path("$(MPY_LIB_DIR)")):
    # file utilities
    freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")

    # requests
    freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
    freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py")

    # umqtt
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")

Some of these libraries are on another github repository. So we need to cline micropython-lib repo to use umqtt, urlib and requests. This way:

git clone https://github.com/micropython/micropython-lib

Now we can build the firmware again:

make -C mpy-cross
cd ports/rp2
make

And the resulting firmware now has the modules we need:

./picotool info /home/rafael/builds/pico/micropython/ports/rp2/build-PICO/firmware.uf2 
File /home/rafael/builds/pico/micropython/ports/rp2/build-PICO/firmware.uf2:

Program Information
 name:            MicroPython
 version:         v1.18-128-g2ea21abae-dirty
 features:        USB REPL
                  thread support
 frozen modules:  rp2, _boot, ds18x20, onewire, dht, uasyncio, uasyncio/core,
                  uasyncio/event, uasyncio/funcs, uasyncio/lock,
                  uasyncio/stream, neopixel, upip, upip_utarfile, ssd1306,
                  webrepl, webrepl_setup, websocket_helper, upysh, 
                  urequests, urllib/urequest, umqtt/simple, umqtt/robust

Ethernet and Raspberry Pi Pico

Ok, now let’s add ethernet support! Consider that the last section was an exercise (at least it was for me). So, the next operations can be done independently from the ones already discussed. The firmware sources are based on https://github.com/Wiznet/RP2040-HAT-MicroPython.

git clone https://github.com/rafaelaroca/RP2040-HAT-MicroPython
cd RP2040-HAT-MicroPython
git submodule add https://github.com/micropython/micropython-lib/
cmake CMakeLists.txt
cd libraries
make -C mpy-cross
cd ports/rp2
make

The above commands will build a complete MicroPython firmware with Ethernet support for the Raspberry Pi Pico with WIZNET W5100S (W5100S-EVB-Pico). Copy firmware.uf2 to the board and test it.

But, as we just did, we can edit the manifest files and add more features, like this:

freeze("$(PORT_DIR)/modules")
freeze("$(MPY_DIR)/drivers/onewire")
freeze("$(MPY_DIR)/drivers/dht", "dht.py")
include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
include("$(MPY_DIR)/drivers/neopixel/manifest.py")

freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
include("$(MPY_DIR)/extmod/webrepl/manifest.py")

# Libraries from micropython-lib, include only if the library directory exists
if os.path.isdir(convert_path("$(MPY_LIB_DIR)")):
    # file utilities
    freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")

    # requests
    freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
    freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py")

    # umqtt
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
    freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")

After editing the manifest file, let’s build the firmware again by simply running make.

Well, after all that, I am having trouble having WebREPL running. Details here: https://forum.micropython.org/viewtopic.php?f=21&t=11996

Anyway, the binary and ready-to-use firmware is here. If you cannot build, just download and use it:

https://bipes.net.br/firmwares/firmware_rpi_pico_ethernet_13022022.uf2

I had problems with the requests module. The fix I did is explained here:

https://github.com/micropython/micropython/issues/8298

1 thought on “Building MicroPython for the Raspberry Pi PICO with Ethernet and WebREPL support

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s