A TLS 1.2 HTTPS server runs on one chip — the W55RP20 (RP2040 + W5500) — and you control GPIO, PWM, ADC, I2C, and SPI in real time just by clicking the board's pinout in your browser. No cloud, no gateway, no companion app.
A TLS 1.2 HTTPS server runs on one chip — the W55RP20 (RP2040 + W5500) — and you control GPIO, PWM, ADC, I2C, and SPI in real time just by clicking the board's pinout in your browser. No cloud, no gateway, no companion app.
It Started With a Simple Question
"On a $2 chip that already has Ethernet built in, can I just poke the board straight from a browser — with no cloud — and do it over HTTPS?"
The usual way to control something over the web in embedded looks like this: device → gateway → cloud (MQTT/REST) → mobile app. Lots of hops, you have to provision accounts, and the moment your internet drops, you can't even touch the board sitting on your own desk.
I wanted to cut that whole chain. The device becomes its own server, and a browser on the same network connects directly to https://<device-ip>/ to toggle pins. Zero data leaving the network. Zero external services to depend on.
The trouble begins the instant you insist on HTTPS instead of plain HTTP.
So What Is the W55RP20?
The W55RP20 is a WIZnet chip that packs the Raspberry Pi RP2040 (dual-core Arm Cortex-M0+, 264 KB SRAM) and WIZnet's hardwired TCP/IP Ethernet controller W5500 into a single package (SiP).
The W5500 is the key. Normally, to do Ethernet on an MCU you run a software TCP/IP stack like lwIP. The W5500 instead handles TCP/UDP/IP/Ethernet directly in hardware logic inside the chip (hardwired TCP/IP). The MCU just reads and writes data to sockets over SPI — that's it. That keeps the code simple and removes the RAM and compute burden a software stack would eat up — which matters quite a bit on a RAM-tight TLS workload like this one.
Because both sit on one chip, MCU + Ethernet + secure web server effectively collapses into a single part. That's why this project can claim "one ~$2 chip."
The board I used: W55RP20-EVB-Pico
The firmware actually runs on WIZnet's eval board, the W55RP20-EVB-Pico. It puts the W55RP20 in a Raspberry Pi Pico form factor and adds an RJ45 Ethernet jack, so you flash firmware over USB, plug in a LAN cable, and you're on the network. No separate Ethernet PHY or module to wire up.
What I BuiltA login-protected HTTPS server running on the W55RP20-EVB-Pico. When you connect, the board's pinout is drawn as an SVG; click a pin and you choose what to use it for.
- Interactive pinout UI — click a pin on the board drawing → a config panel opens. Inputs and ADC values poll automatically, so the pin map doubles as a live status display.
Per-pin peripherals
- Digital input (pull-up / pull-down) / output (HIGH · LOW)
- PWM (frequency + duty)
- ADC (raw value + voltage + bar), GP26–28
- I2C (bus scan / register read · write)
- SPI (hex transfer)
- Controllable pins: GP0–GP15, GP26–GP28
- Login authentication — passwords stored as SHA-256 hashes in flash, session cookies (
HttpOnly+Secure+SameSite), 30-minute timeout, up to 5 accounts
Set GPIO2 as an output, then change its value.
Drop mbedTLS onto the RP2040 and write a naive HTTPS server, and — it works. It's just too slow to use.
The problem is the handshake. Browsers default to cipher suites like ECDHE-RSA, but the RP2040 has no hardware accelerator for EC (elliptic curve) math. It's all done in software. That makes a single handshake take several seconds. Imagine stalling for seconds every time you open a page or press a pin — it doesn't even demo.
So I cut the handshake cost three ways.
1. Static-RSA cipher suites onlyI restricted the server's negotiable cipher suites to the TLS_RSA_WITH_AES_128_GCM_SHA256 family. By taking EC key exchange off the table entirely, I removed the most expensive item — software EC math.
2. HTTP keep-aliveEven so, the first handshake costs ~2.2 s. That's effectively the floor for software RSA-2048 at 200 MHz. So I pay for the first connection once and then reuse it. Every page load, pin toggle, and status poll afterward runs over the same connection with no re-handshake. The felt speed changes completely.
3. Tuned TLS record buffersWith three sockets in flight, RAM is tight. I set the TLS record buffers to IN 2 KB / OUT 8 KB, keeping responses within a few records while saving RAM.
To put it plainly: it's not that "HTTPS on an MCU is slow" — it's that "a naive implementation is slow." Control the negotiation and reuse the connection, and you get usable HTTPS even on a $2 chip.
To put it plainly: it's not that "HTTPS on an MCU is slow" — it's that "a naive implementation is slow." Control the negotiation and reuse the connection, and you get usable HTTPS even on a $2 chip.
Here's how it actually feels: there's a ~2-second pause on the very first connection (that's the handshake), and after that, everything — page switches, pin operations — responds instantly. The only slowness the user ever feels is that one time at the start.
Next step: I'm looking at adding an ECDSA P-256 certificate to bring the first handshake down from ~2.2 s to a few hundred ms.
How It WorksBrowser ──HTTPS(443)──▶ mbedTLS handshake
└─ session-cookie auth
├─ GET / → board UI (HTML embedded in firmware)
├─ GET /api/pins → pin-state JSON (polled)
├─ POST /api/pin → set pin mode / value
└─ POST /api/i2c|spi → bus transactionsThe web page is written as an ordinary board.html, then a CMake build step converts it to a C byte array (board_page.h) and compiles it into the firmware. In other words, there's no filesystem — the page is part of the firmware itself.
The firmware runs on FreeRTOS, with one task driving the HTTPS server across three W5500 sockets (up to three concurrent connections).
Pages and the First LoginThe server is split into a handful of pages (routes) by purpose.
A freshly flashed board has no registered accounts at all, so the first-connection flow goes like this:
- When you first hit the board (
/), there are no accounts, so you're taken to/setup(first account creation). - There you set the ID and password for the first admin account yourself.
- To stop just anyone from creating accounts, you also have to enter a creation password. The demo default is
w55rp20, and you must change it for real use (see the security section below). - Once the account exists, you log in at
/loginwith that ID/PW, and from then on control the board at/. - Adding or removing more accounts during operation is done at
/account(up to 5).
The password you enter is hashed with SHA-256 immediately and stored in flash; the plaintext is never kept anywhere.
How Far Does the Security GoIt's a demo, but I didn't want it to end as a toy, so the basics are in place.
- Passwords are never stored in plaintext — kept as SHA-256 hashes in flash
- Session cookies use
HttpOnly+Secure+SameSite, with a 30-minute timeout - Creating an account requires a separate creation password (demo default
w55rp20). To change it, edit a single string —HTTPS_CREATION_PASSWORDinhttpsAuth.h— and rebuild. It's hashed with SHA-256 at runtime, so there's no precomputed hash to swap out.
To be straight about it, though — the current version uses a self-signed demo certificate, so the browser shows a security warning on first access (that's expected). Private keys are never committed. For real use you need to generate and embed your own cert/key; the how-to is in cert_work/README.md.
⚠️ This is a development project, so some features may be incomplete or unstable. I wouldn't put it on a publicly exposed network as-is.
⚠️ This is a development project, so some features may be incomplete or unstable. I wouldn't put it on a publicly exposed network as-is.Try It Yourself
It's a Raspberry Pi Pico SDK (CMake) project.
bash
git clone --recurse-submodules https://github.com/seok930927/W55RP20-Web-Board-Control.git
cd W55RP20-Web-Board-Control
cmake -B build
cmake --build buildFlash the resulting UF2/ELF to the W55RP20-EVB-Pico, connect Ethernet, and open https://<device-ip>/ in a browser.
Hardware
- W55RP20-EVB-Pico (RP2040 + W5500 single SiP)
- Ethernet connection
- Any I2C / SPI peripheral you want to drive (optional)
Software / Frameworks
- Raspberry Pi Pico SDK (CMake)
- FreeRTOS
- mbedTLS (TLS 1.2)
- WIZnet ioLibrary
Repository
Where This Can Grow From HereSince this project is a base of "a secure web + pin control on the W55RP20, " the same skeleton branches in several directions.
- Sensor gateway — instead of controlling pins, read sensors like temperature/humidity/current and push them out over the web/network. (A work-plan draft,
SENSOR_GATEWAY_WORK_PLAN.md, is in the repo.) - SNMP agent — put SNMP on the same board and a standard NMS (network management system) can monitor this device as-is. (The repo includes
SNMP_AGENT_WORK_PLAN.mdand an ioLibrary SNMP patch.) - Industrial remote I/O panel — inspect and control field equipment's digital/analog I/O safely (HTTPS + login) from an in-house-network browser.
- S2E config web UI — expose a serial-to-Ethernet converter's settings through the same secure web interface.
The point is: build the TLS optimization and the auth skeleton once, and whatever you stack on top reuses it directly.
Wrapping UpIf there's one thing this project shows, it's this: a "full HTTPS server" is no longer the exclusive domain of Raspberry-Pi-class Linux boards. Even on a ~$2 MCU with integrated Ethernet, a few decisions — controlling the negotiation and reusing the connection — get you a usable, secure web interface. Without a single line of cloud.
Next up: shortening the first handshake with an ECDSA certificate, and adding more peripheral types.




Comments