Wiznet makers

Grace_Koo

Published August 12, 2026 ©

104 UCC

25 WCC

11 VAR

0 Contests

0 Followers

0 Following

Original Link

AkiraOS

Zephyr + WAMR OS running sandboxed .wasm apps on MCUs. On STM32U585 the W5500 in MACRAW mode is the sole network path for app upload, OTA, WebSocket and mDNS.

COMPONENTS
PROJECT DESCRIPTION

AkiraOS — Ship the OS Once, Then Deploy Apps Over Ethernet Forever

#WebAssembly #WAMR #Zephyr #W5500 #MACRAW #OTA #STM32U5 #SandboxedApps #OpenSource #OSHWA

📚 Context: Open-source embedded OS (Apache 2.0), v1.5.8 released 2026-05-29. Reference hardware "AkiraConsole V3" is OSHWA-certified (UID MD000003). ✅ Verification status: The W5500 target (b_u585i_iot02a) is in the project's GitHub Actions build matrix, so the Ethernet configuration is compiled on every CI run.


01 — What is this project?

Firmware updates are the tax every connected device pays. Change one line of application logic and the whole image has to be rebuilt, re-signed, pushed through MCUboot, and swapped — with a reboot, a rollback slot, and a bricking risk attached to each cycle. The application and the operating system are welded together, so neither can move independently.

AkiraOS breaks that weld. It is a Zephyr-based embedded operating system that runs sandboxed WebAssembly applications on microcontrollers. The OS firmware is flashed once and stays put. Applications are .wasm binaries that are uploaded to a running device over the network, stored in the filesystem, and instantiated by the runtime — no reflash, no reboot, no MCUboot cycle.

Your App (C/C++) → compile → app.wasm → HTTP upload → runs on device, OS unchanged

Three consequences fall out of that design:

  • Field updates without a flash cycle. Push new application logic to a deployed device in seconds.
  • One binary, many MCUs. The same .wasm runs on ESP32-S3 (Xtensa LX7), nRF54L15 (Cortex-M33), and STM32 (Cortex-M) with no recompile.
  • A crashing app does not take the device down. WAMR catches the fault at the sandbox boundary; the OS keeps running.

The project is substantial rather than a proof of concept: version 1.5.x alone accounts for 125 commits, 350 files, and roughly 40,600 lines of change, and the repository ships a full SDK (AkiraSDK), a 32-widget UI framework, 18 API modules, and a documented architecture at docs.akiraos.dev.


02 — Why WebAssembly on a microcontroller?

🔷 A real isolation boundary, not a convention

Scripting runtimes on MCUs usually offer portability without protection — a misbehaving script can still reach whatever the interpreter can reach. WAMR gives AkiraOS a genuine memory-isolation boundary, and the project builds an explicit permission model on top of it.

Every application ships a manifest declaring exactly what it needs:

{
"name": "my_sensor_app",
"capabilities": ["gpio.read", "display.write", "sensor.read"]
}
 

Every native API call then passes through the Capability Guard, an inline permission check the project documents at roughly 60 ns of overhead. No declared capability means no access.

🔷 Portability that survives the toolchain

WASM's stable binary format is what makes "one binary, three architectures" possible. AkiraOS runs WAMR in interpreter mode (1× baseline) or AOT mode, which the project documents at 10–50× the interpreter's speed — the same module, recompiled ahead of time for the target when performance matters.

🔷 A budget that actually fits

Applications occupy 50–200 KB each, with up to 8 installed and 2 running concurrently. On the STM32U585 target that sits comfortably inside a 256 KB heap (CONFIG_HEAP_MEM_POOL_SIZE=262144) and a 904 KB primary image slot.


03 — System architecture

LayerContents

User space — WASM applications

[app1.wasm] [app2.wasm] [your_app.wasm] — 50–200 KB each, max 8 installed, 2 running concurrently

↓ capability-checked native calls

AKIRA_CHECK_CAP_OR_RETURN(..., -EACCES)

AkiraZ runtime

App Manager · Capability Guard (~60 ns) · Native Bridge · akira_net_api : open / connect / bind / listen / tx_bind / rx_bind · WAMR 2.x, interpreter (1×) or AOT (10–50×)
↓ Zephyr L2 Ethernet

CONFIG_NET_L2_ETHERNET=yeth_w5500 driver, Socket 0 in MACRAW

WIZnet W5500

SPI1 @ 32 MHz · INT → PD15 · MAC 00:80:00:01:02:03 · DHCPv4 — host STM32U585AIIx (Cortex-M33), B-U585I-IOT02A

The runtime sits on two supporting layers:

ConnectivityZephyr RTOS 4.3.0

http_server.c on port 8080

Scheduler · Network stack
WebSocket on port 8081LittleFS · MCUboot
OTA transports: ota_http, ota_ble, ota_usb, ota_cloudDHCPv4 · IPv4 (IPv6 disabled)

Application deployment path, as documented in docs/architecture/data-flow.md:

  1. POST /upload (multipart)
  2. HTTP server parses the boundary
  3. transport_notify(TRANSPORT_DATA_WASM_APP, data, len)
  4. App Loader callback
  5. fs_write("/apps/new_app.wasm") — LittleFS
  6. 200 OK
  7. Runtime reads back in 16 KB chunks, feeds WAMR
  8. Parse, validate, instantiate with declared capabilities
  9. App ready

Two data copies, ~22 KB peak memory: a 1.5 KB HTTP buffer, a 4 KB filesystem write buffer, and a 16 KB temporary runtime chunk. Every byte of that flow crosses the W5500.


04 — Why WIZnet W5500? ⭐

🔷 On this board, the W5500 is the only way in

The STM32U585 target is configured as an Ethernet-only device. boards/b_u585i_iot02a.conf sets:

CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_SOCKETS_OFFLOAD=n
CONFIG_WIFI=n
CONFIG_AKIRA_OTA_USB=n # OTA over USB not yet supported on this board
CONFIG_SHELL_BACKEND_TELNET=y
CONFIG_NET_SOCKETS_SERVICE_STACK_SIZE=4096
 

Wi-Fi off. USB OTA off. What remains is a single W5500 on SPI. That means the entire value proposition of AkiraOS — uploading applications to a live device without reflashing — physically depends on the W5500 on this platform. Application upload, OTA firmware delivery, the /status endpoint, the WebSocket channel on port 8081, mDNS discovery, and the Telnet shell backend all ride the same chip.

This is an unusually strong position for an Ethernet controller. It is not a secondary telemetry port bolted onto a device that already has Wi-Fi. It is the device's only door.

🔷 The mode is MACRAW — because that is how Zephyr drives the chip

AkiraOS declares the chip through Zephyr's upstream wiznet,w5500 binding in boards/b_u585i_iot02a.overlay:

&spi1 {
eth0: ethernet@0 {
status = "okay";
reg = <0>;
compatible = "wiznet,w5500";
int-gpios = <&gpiod 15 GPIO_ACTIVE_LOW>;
spi-max-frequency = <32000000>;
local-mac-address = [ 00 80 00 01 02 03 ];
};
};
 

Zephyr's drivers/ethernet/eth_w5500.c configures the chip accordingly:

/* configure Socket 0 with MACRAW mode and MAC filtering enabled */
uint8_t mode = S0_MR_MACRAW | BIT(W5500_S0_MR_MF);
w5500_spi_write(dev, W5500_S0_MR, &mode, 1);
 

So the W5500 runs Socket 0 in MACRAW mode (Sn_MR = 0x04) with the MAC filter enabled (S0_MR_MF = 0x40) — raw Ethernet frames in and out, with Zephyr's software TCP/IP stack sitting on top. The chip's hardwired TCP/IP offload engine is intentionally not used here.

This is not a decision AkiraOS made. Zephyr's networking model has no hardwired-TCP/IP path: the RTOS brings its own IP stack, and eth_w5500 exists to feed that stack raw frames. Choosing Zephyr chooses MACRAW.

What is worth noting is how well the arrangement fits this particular project. AkiraOS needs more sockets and more protocols than a fixed offload engine exposes. prj.conf sets CONFIG_NET_MAX_CONN=16 and enables DHCPv4; the HTTP server accepts 5 concurrent connections; there is a WebSocket channel, an mDNS responder, a Telnet shell, and a CoAP client — and, most importantly, WASM applications get their own general-purpose socket API:

int akira_native_net_open (wasm_exec_env_t exec_env, int32_t type);
int akira_native_net_connect(wasm_exec_env_t exec_env, int32_t handle, ...);
int akira_native_net_bind (wasm_exec_env_t exec_env, int32_t handle, ...);
int akira_native_net_listen (wasm_exec_env_t exec_env, int32_t handle, ...);
int akira_native_net_tx_bind(wasm_exec_env_t exec_env, int32_t handle, ...);
int akira_native_net_rx_bind(wasm_exec_env_t exec_env, int32_t handle, ...);
int akira_native_net_get_ip (wasm_exec_env_t exec_env, ...);
 

A sandboxed application is allowed to open arbitrary TCP/UDP sockets — gated by the AKIRA_CAP_NETWORK capability (1U << 8), enforced by AKIRA_CHECK_CAP_OR_RETURN(exec_env, AKIRA_CAP_NETWORK, -EACCES) at eleven separate call sites in src/api/akira_net_api.c, and mapped from the manifest strings network.use / network.* in src/runtime/security.c.

The lesson here is about fit, not about a tradeoff the author weighed. A WebAssembly application platform cannot know in advance which protocols its future applications will speak, so it needs a general-purpose socket API — and a software IP stack over a raw MAC is what provides one. On this platform the W5500 earns its place by being a well-driven MAC with a mainline driver, not by its offload engine.

🔷 Why not the alternatives?

OptionProblem for AkiraOS
STM32U585 internal MAC + external PHYThe STM32U5 line has no integrated Ethernet MAC. A PHY alone is not an option.
ENC28J6010 Mbps half/full duplex only. AkiraOS's docs put HTTP upload throughput at roughly 1.1–1.3 MB/s, which leaves little headroom at 10 Mbps.
Wi-Fi moduleExplicitly disabled on this target (CONFIG_WIFI=n); adds RF certification, provisioning UX, and power cost to a device that sits on a desk beside a switch.

W5500 via SPI

10/100 Mbps, one 4-wire SPI bus at 32 MHz plus one interrupt line, a mainline Zephyr driver, and no board respin required.

The decisive practical factor is the last one: because wiznet,w5500 is an upstream Zephyr driver, adding Ethernet to a new AkiraOS board is a 12-line devicetree overlay and five Kconfig lines. No vendor SDK, no custom port layer, no driver maintenance burden on the project.

🔷 Verified evidence ✅

  • ✅ W5500 declared in boards/b_u585i_iot02a.overlay with a complete pin/bus configuration — SPI1, reg = <0>, INT on gpiod 15 active-low, 32 MHz, MAC 00:80:00:01:02:03.
  • b_u585i_iot02a appears in the GitHub Actions build matrix (.github/workflows), so the Ethernet path is compiled on every CI run.
  • ✅ Board support landed in the commit "added B-U585I-IOT02A Board support and fixed networking issues" (2025-12-11); the overlay was last revised 2026-03-08.
  • ✅ MACRAW mode is verifiable in Zephyr upstream at drivers/ethernet/eth_w5500.c — the driver AkiraOS binds to.
  • ✅ Network buffer budget is explicit in prj.conf: NET_BUF_RX_COUNT=24, NET_BUF_TX_COUNT=20, NET_PKT_RX/TX_COUNT=12, NET_BUF_DATA_SIZE=128, TCP send/receive windows 2048 bytes each.
  • ✅ v1.5.8 hardened the network path specifically: "Watchdog hardening, HTTP upload auth, signing enforcement; drop legacy local web UI."

Where the repository is inconsistent or silent: its own documents disagree on upload throughput — docs/architecture/connectivity.md and docs/resources/performance.md give ~1.3 MB/s, while src/connectivity/README.md gives ~1.1 MB/s. Neither figure is broken out per board, so neither is necessarily the STM32U585 number. The repository also publishes no photographs of the W5500 target and no measured results from hardware, only build coverage in CI.


05 — Key components

🌐 WIZnet W5500 — MACRAW mode (Sn_MR = 0x04), Socket 0, MAC filter enabled

10/100 Mbps hardwired TCP/IP Ethernet controller on SPI. In AkiraOS it operates as a raw L2 MAC beneath Zephyr's native IPv4 stack, carrying every byte of application upload, OTA firmware, WebSocket, mDNS, and Telnet traffic on the STM32U585 target. Bus: SPI1 at 32 MHz, interrupt on PD15 (active low), static MAC 00:80:00:01:02:03, DHCPv4 for addressing.

🧠 STM32U585AIIx — Arm Cortex-M33

The B-U585I-IOT02A Discovery Kit. 2 MB flash partitioned as MCUboot (64 KB) / image-0 (904 KB) / image-1 (896 KB) / storage (128 KB) / settings NVS (32 KB), with a 256 KB runtime heap, 8 KB main stack, and 4 KB ISR stack. An external MX25LM51245 octal-SPI flash carries a 64 MB user_data partition for .wasm application storage.

⚙️ WAMR 2.x (WebAssembly Micro Runtime)

Bytecode Alliance runtime, interpreter or AOT. Modules are fed in 16 KB chunks so a large application never needs to be resident in RAM in full.

🛡️ Capability Guard

Inline permission check on every native call, ~60 ns overhead. AKIRA_CAP_NETWORK (1U << 8) gates the entire socket API; capability strings are resolved in src/runtime/security.c.

🌉 Connectivity layer

http_server.c / http_routes.c (HTTP/1.1, port 8080, 5 concurrent connections, 1.5 KB shared buffer, 8 KB thread stack, ~1.3 MB/s documented upload throughput), WebSocket on 8081, mDNS responder, CoAP client, and a four-transport OTA abstraction — ota_http.c, ota_ble.c, ota_usb.c, ota_cloud.c — behind a single OTA manager.

💾 Zephyr RTOS 4.3.0 + LittleFS + MCUboot

Dual-slot A/B firmware update with RSA-2048 image signing (bootloader/mcuboot/root-rsa-2048.pem), LittleFS on the internal storage partition.


06 — Application scenarios

01. Field-updatable industrial edge nodes

A controller in a cabinet needs its processing logic changed after commissioning. Instead of scheduling a firmware flash with an on-site engineer, an operator pushes a 120 KB .wasm over the plant's wired network. The OS, the bootloader, and the network configuration never change — so the update cannot brick the node.

02. Multi-tenant sensor gateways

Several teams share one gateway. Each ships its own .wasm with a manifest declaring only the sensors and network access it needs. The Capability Guard enforces the boundary at runtime, so team A's application cannot read team B's I²C sensor or open a socket it never declared.

03. Hardware-in-the-loop and CI test rigs

A test fixture must run a different test program for every build under test. The W5500 gives the rig a stable, deterministic wired address that a CI runner can target; each test is a .wasm uploaded via POST /upload, executed, and discarded — no flash-wear, no reboot between test cases.

04. Long-lived building and access infrastructure

Panels installed behind walls for a decade need logic changes but must not be reflashed casually. Ethernet gives them PoE-friendly single-cable installation and an addressing model that outlives Wi-Fi credential rotations; WASM gives them a safe update path with a runtime that catches faults instead of resetting.


Conclusion

AkiraOS is a reminder that a hardwired TCP/IP chip is often bought for something other than its offload engine. Under an RTOS that brings its own IP stack, the W5500 earns its keep as a well-supported MAC and PHY on a single SPI bus.

  • ✅ A genuine WebAssembly application platform on Cortex-M-class hardware, not a demo — v1.5.8, 125 commits and ~40,600 changed lines in the 1.5.x series alone
  • ✅ On the STM32U585 target, the W5500 is the device's sole network interface: application upload, OTA, WebSocket, mDNS, and Telnet all traverse it
  • ✅ Socket 0 in MACRAW mode with MAC filtering, verifiable in the mainline Zephyr driver the project binds to
  • ✅ Sandboxed applications reach the network through a capability-gated socket API enforced at eleven call sites
  • ✅ Adding Ethernet to a new board costs a 12-line devicetree overlay — the payoff of an upstream Zephyr driver
  • ✅ The W5500 configuration is compiled in CI on every push, not left to rot in an unbuilt branch
  • ✅ Apache 2.0, with OSHWA-certified reference hardware (UID MD000003) and published architecture documentation
  • ✅ Demonstrates a WIZnet chip in a role our ecosystem rarely showcases — carrying a general-purpose OS's software IP stack rather than terminating a single fixed protocol

07 — Similar Projects on WIZnet Makers

  • VovkPLCRuntime is the closest related Maker post because it also puts a portable virtual machine on an MCU and lets user programs reach the network through a W5500. The difference is that VovkPLCRuntime executes a custom PLC bytecode over raw TCP/UDP sockets, while AkiraOS runs standard WebAssembly modules under a capability sandbox with the W5500 driven as a MACRAW L2 MAC beneath a full Zephyr IP stack.
  • Device firmware update (DFU) using Golioth is closely related because it also delivers software to a Zephyr device over WIZnet Ethernet with MCUboot handling the image swap. The difference is that Golioth DFU updates the firmware image itself, whereas AkiraOS keeps the firmware fixed and ships only the application layer — so the OTA path is used for .wasm modules rather than for the OS.
  • Oro Link is related because it is likewise an operating-system project that leans on W5500 Ethernet as its control path, in its case for hardware-in-the-loop CI/CD. The difference is that Oro Link uses dual W5500 paths on an STM32 to test an OS from the outside, while AkiraOS embeds the W5500 as the internal deployment channel of the OS itself.

Q&A

Q. Does AkiraOS use the W5500's hardwired TCP/IP offload (TOE)? No. Zephyr's networking model does not offer that path at all — the RTOS supplies its own IP stack, and the eth_w5500 driver puts Socket 0 into MACRAW mode with MAC filtering so raw Ethernet frames reach it. Any Zephyr application using this driver runs the chip the same way; it is not a per-project decision. It does suit AkiraOS well, which needs 16 concurrent connections, DHCPv4, mDNS, WebSocket, CoAP, and an arbitrary socket API exposed to third-party WASM applications.

Q. Could AkiraOS use TOE mode instead? Not without leaving Zephyr's socket API behind and driving the chip directly through WIZnet's ioLibrary. That would buy lower CPU load and smaller RAM buffers for a small number of fixed connections — a good trade for a dedicated Modbus TCP or MQTT node, and a poor one for a platform that must expose arbitrary sockets to third-party applications it has never seen.

Q. How is the W5500 wired on the reference target? SPI1 with chip select reg = <0> at 32 MHz, interrupt on gpiod pin 15 active-low, static MAC 00:80:00:01:02:03, DHCPv4 for address assignment. The full declaration is twelve lines of devicetree in boards/b_u585i_iot02a.overlay.

Q. Can a WASM application open its own network sockets? Yes, through akira_native_net_open / connect / bind / listen and the bound TX/RX buffer calls — but only if its manifest declares network.use or network.*. Without the AKIRA_CAP_NETWORK bit the call returns -EACCES before touching the stack.

Q. Is the Ethernet path actually built and tested? The b_u585i_iot02a board is in the project's GitHub Actions matrix, so the W5500 configuration compiles on every CI run. The board landed in a commit explicitly titled "added B-U585I-IOT02A Board support and fixed networking issues", and v1.5.8 added HTTP upload authentication and signing enforcement to the same path.

Q. Which other WIZnet parts would suit this architecture? Any part with a mainline Zephyr driver drops in the same way. W5100S offers a lower-cost path at the same 10/100 Mbps class; W6100 adds IPv6, which would pair well should AkiraOS re-enable CONFIG_NET_IPV6; and W55RP20 would collapse the MCU and Ethernet controller into one package for a purpose-built AkiraOS node.


Original Link: https://github.com/ArturR0k3r/AkiraOS

Documents
Comments Write