Stream: SIG-Embedded

Topic: Running Wasmtime on Pico 2: Overcoming Memory issues


view this post on Zulip Lukas Barragan Torres (Mar 14 2026 at 20:10):

Hi everyone!

I'm currently working on running Wasmtime using the new Pulley bytecode interpreter on a Raspberry Pi Pico 2.
I've successfully built a no_std host that runs a component precompiled to pulley32. The guest uses a custom SPI WIT to read a BME280 sensor and display data on an OLED screen. (https://github.com/idlab-discover/masters-wasi-spi)

While I've got a single component running successfully, I'm hitting a hard wall regarding linear memory management and the strict constraints of an MMU-less device. After digging into the memory behavior these are the memory roadblocks i came across:

This is my first project with wasmtime and embedded systems so I'd appreciate any insights, workarounds, or pointers to Wasmtime configuration flags I might have missed! Thanks! :D

view this post on Zulip Ralph (Mar 15 2026 at 19:15):

this is a GREAT project, @Lukas Barragan Torres, and we're thrilled you're chewing on it. I'll leave these questions to the engineers here, but I note about the "wac multiplier": yes, that's a feature -- unless you do not want it.

view this post on Zulip Ralph (Mar 15 2026 at 19:17):

for the seriously embedded use case, you'd only want a new sandbox to encapsulate code you do not want the entire component to access freely. If you're going to make the assumption that the component boundary -- that is, the parent component that wasmtime started -- is the boundary, then you would have the ability to compile all code together.

view this post on Zulip Ralph (Mar 15 2026 at 19:18):

if there's a situation in which you MUST use different languages, for example, then the sandbox between those two things are going to be there, regardless whether they're components or modules.

view this post on Zulip Ralph (Mar 15 2026 at 19:19):

so that one's a choice to make. If you trust your parent sandbox boundary as THE boundary, then just compile all the code together. The only issue is if for some reason you cannot.

view this post on Zulip Ralph (Mar 15 2026 at 19:20):

I would imagine that typically in a pico sized scenario, you'd control the components executing, right? If you're not, then you'd need the security boundary in any case.....

view this post on Zulip Christof Petig (Mar 16 2026 at 21:58):

Ralph said:

if there's a situation in which you MUST use different languages, for example, then the sandbox between those two things are going to be there, regardless whether they're components or modules.

I have developed a way to mix languages inside the same sandbox using WIT between the boundaries. See https://github.com/cpetig/wit-bindgen and https://wasmcon24.sched.com/event/1qvIG/component-model-in-software-defined-vehicles-christof-petig-aptiv , I should really make it an official variant (mostly documentation is missing) and support more languages, but it works well and can be exchanged for the canonical ABI without changing the source code.

view this post on Zulip Ralph (Mar 16 2026 at 22:41):

there you go: a solution that casts all code into one sandbox -- which implies all code is trusted within that sandbox. @Christof Petig you really should make that official.

view this post on Zulip Lukas Barragan Torres (Mar 19 2026 at 11:18):

Thanks Ralph and Christof!

@Ralph I'm compiling everything together right now, which works okay for my current setup. However, it still feels a bit suboptimal compared to the broader Wasm philosophy, where you should be able to just plug and play with pre-compiled driver Wasm blobs using WIT.

@Christof Petig Just to make sure I understand: does your fork essentially generate standard, statically linkable bindings from the WIT file instead of the usual Component Model Canonical ABI bindings? Meaning it lets us use WIT purely as an interface design tool, but under the hood, everything still compiles down into one single Wasm module with a shared memory?

For now I'll stick to keeping it all compiled together until I can find a way to keep the memory overhead and individual component usage down on the Pulley/Wasmtime side. Thanks again for the pointers!

view this post on Zulip Christof Petig (Mar 22 2026 at 04:45):

Lukas Barragan Torres said:

Christof Petig Just to make sure I understand: does your fork essentially generate standard, statically linkable bindings from the WIT file instead of the usual Component Model Canonical ABI bindings? Meaning it lets us use WIT purely as an interface design tool, but under the hood, everything still compiles down into one single Wasm module with a shared memory?

Yes, exactly. We use it to compile native applications with a single memory instance, thus no sandbox between components.


Last updated: Mar 23 2026 at 16:19 UTC