feat: add Ethernet OTA support for RP2350/W5500 boards#10136
feat: add Ethernet OTA support for RP2350/W5500 boards#10136cvaldess wants to merge 4 commits intomeshtastic:developfrom
Conversation
d9e465e to
89ff18a
Compare
There was a problem hiding this comment.
Pull request overview
Adds Ethernet-based OTA update support for RP2350 + W5500 boards in the Meshtastic firmware, integrating a new OTA TCP server into the existing Ethernet client flow and providing a companion upload tool and RP2350 variant configuration.
Changes:
- Introduces a new Ethernet OTA server (TCP/4243) using the MOTA protocol with PSK-based SHA256 auth and CRC32 verification.
- Adds a stdlib-only Python uploader that GZIP-compresses firmware before transfer.
- Adds/updates RP2350 Pico 2 + W5500 + E22-900M30S variant configs/docs and enables an RP2xxx watchdog loop.
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/mesh/eth/ethOTA.cpp |
Implements Ethernet OTA server, auth, transfer, CRC verification, and reboot staging. |
src/mesh/eth/ethOTA.h |
Declares OTA server init/loop API behind feature guards. |
bin/eth-ota-upload.py |
Implements client-side MOTA upload with GZIP + SHA256 challenge-response. |
src/mesh/eth/ethClient.cpp |
Hooks OTA init after Ethernet connect and polls OTA loop periodically; adds W5500 SPI0 init path. |
src/platform/rp2xx0/main-rp2xx0.cpp |
Enables and feeds an 8s watchdog in rp2040Loop(). |
src/platform/rp2xx0/architecture.h |
Maps WIZNET_5500_EVB_PICO2 builds to PRIVATE_HW vendor model. |
src/mesh/api/ethServerAPI.h |
Adds conditional include of Ethernet.h for the W5500/Pico2 path. |
src/DebugConfiguration.h |
Adds conditional include of Ethernet.h for the W5500/Pico2 path. |
variants/rp2350/pico2_w5500_e22/platformio.ini |
Adds new env with Ethernet OTA flag, bigger filesystem, and Ethernet library dependency. |
variants/rp2350/pico2_w5500_e22/variant.h |
Defines pins/capabilities for Pico2 + W5500 + E22 wiring. |
variants/rp2350/pico2_w5500_e22/README.md |
Documents wiring/build/network usage and technical notes for the variant. |
variants/rp2350/pico2_w5500_e22/wiring.svg |
Adds a wiring diagram for the Pico2/W5500/E22 setup. |
|
All four Copilot review items were addressed in e9ac820:
bfd2c94 follows up on the protocol-code change on the client side: bin/eth-ota-upload.py previously mapped 0x06 → Timeout, which stopped matching once 0x08 became the timeout code. The mapping is now aligned with the full OTAResponse enum (0x00–0x08) so every firmware response prints a human-readable message. Ready for maintainer review whenever you have a moment — happy to rebase again if needed. |
00e86e9 to
75a0f70
Compare
Adds community variant for Raspberry Pi Pico 2 (RP2350, 4 MB flash) with external WIZnet W5500 Ethernet module and EBYTE E22-900M30S LoRa module (SX1262, 30 dBm PA, 868/915 MHz). Key details: - LoRa on SPI1: GP10/11/12/13 (SCK/MOSI/MISO/CS), RST=GP15, DIO1=GP14, BUSY=GP2, RXEN=GP3 (held HIGH via SX126X_ANT_SW) - W5500 on SPI0: GP16/17/18/19/20 (MISO/CS/SCK/MOSI/RST) - SX126X_DIO2_AS_RF_SWITCH: DIO2→TXEN bridge on module handles PA - SX126X_DIO3_TCXO_VOLTAGE 1.8: TCXO support via EBYTE_E22 flags - DHCP timeout reduced to 10 s to avoid blocking LoRa startup - GPS on UART1/Serial2: GP8 TX, GP9 RX - Reuses WIZNET_5500_EVB_PICO2 code paths for Ethernet init Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds over-the-air firmware update capability for RP2350-based boards with a WIZnet W5500 Ethernet module (e.g. pico2_w5500_e22). Protocol (MOTA): - SHA256 challenge-response authentication with a configurable PSK (override via USERPREFS_OTA_PSK; default key ships in source) - 12-byte header: magic "MOTA" + firmware size + CRC32 - Firmware received in 1 KB chunks, verified with CRC32, written via Updater (picoOTA), then device reboots to apply - Constant-time hash comparison prevents timing attacks on auth - 30s inactivity timeout + 5s cooldown after failed auth Firmware side: - ethOTA.cpp / ethOTA.h: OTA TCP server on port 4243 - ethClient.cpp: calls initEthOTA() after Ethernet connects, ethOTALoop() polled every 5s - main-rp2xx0.cpp: enable watchdog (8s) so device recovers if OTA write stalls; log watchdog-caused reboots - pico2_w5500_e22: filesystem_size=0.75m (GZIP ~614KB fits), HAS_ETHERNET_OTA build flag Upload tool: - bin/eth-ota-upload.py: Python 3, stdlib-only, GZIP-compresses firmware before sending, shows progress bar + transfer speed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix OTA_ERR_TIMEOUT/OTA_ACK collision (0x06→0x08 for timeout) - Fix USERPREFS_OTA_PSK trailing NUL byte via char[]+sizeof-1 - Fix auth cooldown: close connection silently instead of sending OTA_ERR_AUTH before the nonce (prevents byte being mis-consumed) - Fix README TX_GAIN_LORA value: 10→7 for EBYTE_E22_900M30S - Fix Trunk Check: clang-format ethOTA.cpp/h + variant.h, prettier README.md (MD040 code fence langs, MD060 table style), svgo wiring.svg Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous commit moved OTA_ERR_TIMEOUT from 0x06 to 0x08 to free 0x06 for OTA_ACK, but bin/eth-ota-upload.py still mapped 0x06 to "Timeout" — so a real timeout from the device (0x08) was printed as "Unknown result 0x08" instead of being identified. Align the mapping with the full OTAResponse enum in ethOTA.cpp: keep 0x00–0x03, remove the stale 0x06, and add 0x04 (magic), 0x05 (begin), 0x07 (auth), 0x08 (timeout) so every firmware response prints a human-readable message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f7978d6 to
417cec2
Compare
Summary
bin/eth-ota-upload.py) — stdlib-only, auto GZIP-compresses firmware before uploadrp2040Loop()so the device recovers if an OTA write stallsProtocol
SHA256(nonce || PSK)— constant-time comparison on device side"MOTA"magic + firmware size (LE u32) + CRC32 (LE u32)Update.end()(picoOTA)The PSK defaults to
meshtastic_ota_default_psk_v1!!!and can be overridden per-build viaUSERPREFS_OTA_PSK.Files changed
src/mesh/eth/ethOTA.cppsrc/mesh/eth/ethOTA.hinitEthOTA(),ethOTALoop()bin/eth-ota-upload.pysrc/mesh/eth/ethClient.cppinitEthOTA()after connect,ethOTALoop()every 5ssrc/platform/rp2xx0/main-rp2xx0.cpprp2040Loop()variants/rp2350/pico2_w5500_e22/platformio.inifilesystem_size=0.75m,-D HAS_ETHERNET_OTAUsage
Test plan
HAS_ETHERNET_OTA(pio run -e pico2_w5500_e22)HAS_ETHERNET_OTA(other boards) unaffected — all code guarded🤖 Generated with Claude Code