This repository showcases small Rust embedded virtual machines, encapsuled and bolted on Ariel OS. Open source examples of code are given which you can run on a variety of Cortex-M and RISC-V boards (see below).
Currently, the only type of VM that has been tested with Ariel OS is WebAssembly. Currently, Wasmtime is the only WebAssembly runtime that is supported. See this for an overview of how other runtimes compare in terms of code size and features. Note: Support for this is experimental and the implementation is subject to change.
Your system and toolchain should be set up for Ariel OS. To learn more about the OS check out the Ariel OS repo and follow the guide for getting started.
On top of the requirements for basic Ariel OS usage, to turn rust code into components the wasm32v1-none target should be installed for your toolchain using rustup <toolchain> target add wawm32v1-none and so should the wasm-tools CLI utility. Ariel OS works on stable and so does the rust to wasm compilation workflow but we advocate the use of a (recent) nightly compiler for two reasons:
- Compiling the wasm payloads is a three step process. We provide a rust script that does those steps in sequence and running scripts requires nightly.
- Wasm binaries have by default a memory page size of 65536 bytes. It is possible to go below but support for this was only added in LLVM 21 which is only used by fairly recent nightly
rustc.nightly-2025-09-01is known to work and is the nightly version that was used when developing this. Also, if you choose to use the provided script you will also need to download therust-srctarget for thenightlytoolchain withrustup +nightly target add rust-srcto use the-Z build-stdoptimizations that the script uses.
The bindings can be found in src/ariel-os-bindings/src/wasm. They are taylored for Wasmtime and will not work with another runtime. The bindings are partially auto-generated by the use of the WebAssembly component model. The WIT interfaces that are made available to wams components are defined in wit/deps/ariel.
Examples are in the examples/ directory. They can be run using the laze build system. Capsules work by embarking their payload at compile time. Changing the payload requires to go through the following steps:
- Compiling some code to a wasm module
- Turning the wasm module into a wasm component
- Precompiling this component to make it usable by wasmtime in
no_stdcontexts. Theprecompile_wasm.rsscript takes in a path to rust manifest (Cargo.toml) and outputs a precompiled component to make this process less time consuming. The source code for the payload used in the examples in thepayloadsdirectory. After modifying the code in for examplepayloads/async-bindings/src/lib.rs, the corresponding example's payload can be changed by using the script in the following way
# nightly is required to use -Z script
cargo +nightly -Z script precompile_wasm.rs --path payloads/async-bindings/Cargo.toml --config payloads/.cargo/config.toml -o examples/async-bindings/payload.cwasm
cargo +nightly -Z script precompile_wasm.rs --path payloads/async-bindings/Cargo.toml --config payloads/.cargo/config.toml -o examples/async-bindings/payload.pulley64f.cwasm --target pulley64 --fuel(The 64bit version is only needed when running with Ariel's native target, which is currently only practical with the async-bindings example).
The various parameters used for initial compilation and precompilation have been chosen to optimize the resulting code size and nothing else. See this document for a more detailled breakdown of the process. In the most recent nightly compilers, the -Zbuild-std-features option panic_immediate_abort was turned into an unstable panic strategy. The payloads/.cargo/config.toml config file reflects this change. The old version is still present but commented out.
- Async Bindings for RNG, Timer, Log: This example shows how Ariel OS can asynchronously run wasm components that yield regularly and that call asynchronous host functions. Recommended boards for this example: nrf52840dk, rpi-pico2-w
- UDP Bindings: This example showcases how a wasm capsule can receive and send UDP packets by using the approriate functions. Recommended boards for this example: nrf52840dk, rpi-pico2-w, espressif-esp32-c6-devkitc-1
- CoAP Server Bindings: This example shows how to run a coap-server through a wasm capsule by deferring the processing of selects message to the wasm capsule. Recommended boards for this example: nrf52840dk, rpi-pico2-w, espressif-esp32-c6-devkitc-1
- GPIO through Wasm: This example showcases a simple blinky running through a wasm capsule. Recommanded boards for this example: nrf52840dk, nrf9160dk