wasm2mpy
enables developers to write code in statically compiled languages and run it on MicroPython-based embedded systems (such as ESP32, Raspberry Pi Pico, STM32, and nRF52) with near-native performance. Since MicroPython is relatively slow for computationally intensive applications, wasm2mpy
provides the tools necessary to run demanding software, such as AI models and signal processing algorithms, more efficiently.
App \ Target | x86/x64 | armv6m | armv7m/+s/+d | esp82661 | esp32 | rv32imc |
---|---|---|---|---|---|---|
🚀 TypeScript2 | ✅✅ | ✅ | ✅✅✅ | ✅ | ✅ | |
🤩 C++ | ✅✅ | ✅ | ✅✅✅ | 🟡 | ✅ | ✅ |
🦀 Rust | ✅✅ | ✅ | 🟡🟡✅ | ✅ | ✅ | |
🤖 TinyGo | ✅✅ | ✅ | 🟡🟡✅ | ✅ | ✅ | |
⚡ Zig | ✅✅ | ✅ | ✅✅✅ | ✅ | ✅ | |
✨ Virgil | ✅✅ | ✅ | ✅✅✅ | 🟡 | ✅ | ✅ |
⚙ WAT | ✅✅ | ✅ | ✅✅✅ | 🟡 | ✅ | ✅ |
🇨 Coremark | ✅✅ | 🚧 | ✅✅✅ | 🟡 | ✅ | ✅ |
✅ builds and runs OK
🟡 builds OK, doesn't run
🚧 work in progress
- ESP32-C3 160MHz:
179.791
- STM32F405 168MHz:
233.918
- ESP32 240MHz:
228.363
- ESP32-S3 240MHz:
271.573
- BL616 320MHz:
344.293
- iMXRT1062 600MHz:
1911.437
- i5-8250U 1.6GHz:
18696.248
Follow the build instructions
mpremote cp zig.mpy :lib/
mpremote exec "import zig; zig.setup()"
⚡ Zig is running!
Note
This requires adding some glue code to the runtime.
Glue code can be auto-generated, but for now it's a manual process.
For example, test/simple.wasm
just adds 2 numbers:
(module
(func (export "add") (param i32 i32) (result i32)
(i32.add (local.get 0) (local.get 1))
)
)
MicroPython v1.24.0-preview.224.g6c3dc0c0b on 2024-08-22; Raspberry Pi Pico W with RP2040
Type "help()" for more information.
>>> import simple
>>> simple.add(3, 4)
7
>>> simple.add(10, 6)
16
>>> import cpp
>>> cpp.setup()
🤩 C++ is running!
>>> cpp._memory[4096:4096+32]
bytearray(b' Blink\x00\xf0\x9f\xa4\xa9 C++ is running!\x00\n\x00\x00\x00')
>>> new_data = b"Hello C++ world"
>>> cpp._memory[4096+12:4096+12+len(new_data)] = new_data
>>> cpp.setup()
🤩 Hello C++ world
The idea is very similar to embedded-wasm-apps:
- Support exports
- Auto-generate exports bindings
- Support imports
- Support memory
- Support
.a
inputs formpy_ld
- XIP for native modules
- TBD: Support globals
- Add RISC-V support: micropython/micropython#15603
- Optimize codegen
- Use
u32
instead ofu64
for mem addresses - Use a directly addressable
.bss
section as memory (skip indirection)
- Use
- Implement WASM Custom Page Sizes
- Implement WASM Exceptions
- Implement WASM Stack Switching
- Discussions: GitHub, Hacker News
- wasm2c, w2c2
- MicroPython Native Modules
- Feasibility of WASM for MicroPython
Footnotes
-
esp8266
requires the use ofesp.set_native_code_location
, and settingWASM_PAGE_SIZE
to8192
(or need to wait forWASM Custom Page Sizes
) ↩ -
not enough memory to run, need to wait for
WASM Custom Page Sizes
↩ ↩2 ↩3 ↩4