Awesome
<img height="48px" src="/logo.png"> wasm2mpy
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.
Status
App \ Target | x86/x64 | armv6m | armv7m/+s/+d | esp82661 | esp32 | rv32imc |
---|---|---|---|---|---|---|
๐ TypeScript2 | โ โ | โ | โ โ โ | โ ๏ธ3 | โ | โ |
๐คฉ C++ | โ โ | โ | โ โ โ | ๐ก | โ | โ |
๐ฆ Rust | โ โ | โ | ๐ก๐กโ | โ ๏ธ3 | โ | โ |
๐ค TinyGo | โ โ | โ | ๐ก๐กโ | โ ๏ธ3 | โ | โ |
โก Zig | โ โ | โ | โ โ โ | โ ๏ธ3 | โ | โ |
โจ Virgil | โ โ | โ | โ โ โ | ๐ก | โ | โ |
โ WAT | โ โ | โ | โ โ โ | ๐ก | โ | โ |
๐จ Coremark | โ โ | ๐ง | โ โ โ | ๐ก | โ | โ |
โ
builds and runs OK
๐ก builds OK, doesn't run
๐ง work in progress
CoreMark results
- 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
Upload and Run
Follow the build instructions
mpremote cp zig.mpy :lib/
mpremote exec "import zig; zig.setup()"
โก Zig is running!
Run any exported function
[!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
Access WASM module memory
>>> 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
How It Works?
The idea is very similar to embedded-wasm-apps:
TODO
- 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: https://github.com/micropython/micropython/pull/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
Further reading
- 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