ESP32: Add Rust and TinyGO blink examples. Part of #57

extensions
Volodymyr Shymanskyy 5 years ago
parent cef2a38746
commit eb00d021f5

@ -3,11 +3,6 @@
This example was tested with ESP32.
ESP8266 is almost working (just needs a workaround for 64KiB wasm pages).
`./wasm_cpp` directory contains an example Arduino app (sketch) that is compiled to WebAssembly.
Compilation is performed using `wasicc` here, but `clang --target=wasm32` can be used as well.
The resulting `wasm` binary is then converted to a C header using `xxd`.
See `build.sh` for details.
`PlatformIO` is used to build the host interpreter.
You can change the LED pin number in `platformio.ini` with `-DLED_BUILTIN` option.
@ -17,3 +12,25 @@ To run the example on ESP32:
pio run -e esp32 -t upload && pio device monitor
```
## C++ app
`./wasm_cpp` directory contains an example Arduino app (sketch) that is compiled to WebAssembly.
Compilation is performed using `wasicc` here, but `clang --target=wasm32` can be used as well.
The resulting `wasm` binary is then converted to a C header using `xxd`.
See `wasm_cpp/build.sh` for details.
## Rust app
For Rust, the LED pin is currently hardcoded in the app.
Before building the app, please install the toolchain:
```sh
rustup target add wasm32-unknown-unknown
```
To rebuild, use `wasm_rust/build.sh`.
## TinyGO app
For TinyGO, the LED pin is currently hardcoded in the app.
To rebuild, use `wasm_tinygo/build.sh`.

@ -68,6 +68,11 @@ m3ApiRawFunction(m3_arduino_getPinLED)
m3ApiReturn(LED_BUILTIN);
}
// Dummy, for TinyGO
m3ApiRawFunction(m3_dummy)
{
m3ApiSuccess();
}
M3Result m3_LinkArduino (IM3Runtime runtime)
{
@ -81,6 +86,8 @@ M3Result m3_LinkArduino (IM3Runtime runtime)
m3_LinkRawFunction (module, arduino, "getPinLED", "i()", &m3_arduino_getPinLED);
m3_LinkRawFunction (module, "env", "io_get_stdout", "i()", &m3_dummy);
return m3Err_none;
}

@ -9,8 +9,15 @@
#include "m3/m3.h"
// C++ app
#include "../wasm_cpp/app.wasm.h"
// Rust app
//#include "../wasm_rust/app.wasm.h"
// TinyGO app. For this, change _start to cwa_main below
//#include "../wasm_tinygo/app.wasm.h"
M3Result m3_LinkArduino (IM3Runtime runtime);
#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; }

@ -6,7 +6,11 @@ wasicc -Os \
-o app.wasm app.cpp
# Optimize (optional)
wasm-opt -O3 app.wasm -o app.wasm
#wasm-opt -O3 app.wasm -o app.wasm
wasm-strip app.wasm
# Convert to header
# Convert to WAT
#wasm2wat app.wasm -o app.wat
# Convert to C header
xxd -i app.wasm > app.wasm.h

@ -0,0 +1,34 @@
#![no_std]
mod arduino_api;
use arduino_api::*;
static LED: u32 = 19;
fn setup() {
pin_mode(LED, OUTPUT);
}
fn run() {
digital_write(LED, HIGH);
delay(100);
digital_write(LED, LOW);
delay(900);
}
/*
* Entry point
*/
#[no_mangle]
pub extern fn _start() {
setup();
loop {
run();
}
}
#[panic_handler]
fn handle_panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}

@ -0,0 +1,20 @@
unsigned char app_wasm[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x03, 0x60,
0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x02,
0x3a, 0x03, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x05, 0x64,
0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69,
0x6e, 0x6f, 0x07, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x00, 0x00,
0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0c, 0x64, 0x69, 0x67,
0x69, 0x74, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x03,
0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x0d, 0x02, 0x7f,
0x00, 0x41, 0x80, 0x20, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x20, 0x0b, 0x07,
0x2e, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x0a,
0x5f, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x6e, 0x64, 0x03, 0x00,
0x0b, 0x5f, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x62, 0x61, 0x73, 0x65,
0x03, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x03, 0x0a,
0x26, 0x01, 0x24, 0x00, 0x41, 0x13, 0x41, 0x01, 0x10, 0x01, 0x03, 0x40,
0x41, 0x13, 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00, 0x10, 0x00, 0x41,
0x13, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10, 0x00, 0x0c, 0x00,
0x0b, 0x00, 0x0b
};
unsigned int app_wasm_len = 195;

@ -0,0 +1,25 @@
#![allow(dead_code)]
#[link(wasm_import_module = "arduino")]
extern {
#[link_name = "millis"] fn unsafe_millis() -> u32;
#[link_name = "delay"] fn unsafe_delay(ms: u32);
#[link_name = "pinMode"] fn unsafe_pinMode(pin:u32, mode:u32);
#[link_name = "digitalWrite"] fn unsafe_digitalWrite(pin:u32, value:u32);
#[link_name = "getPinLED"] fn unsafe_getPinLED() -> u32;
}
pub static LOW:u32 = 0;
pub static HIGH:u32 = 1;
pub static INPUT:u32 = 0x0;
pub static OUTPUT:u32 = 0x1;
pub static INPUT_PULLUP:u32 = 0x2;
pub fn millis () -> u32 { unsafe { unsafe_millis() } }
pub fn delay (ms: u32) { unsafe { unsafe_delay(ms); } }
pub fn pin_mode (pin:u32, mode:u32) { unsafe { unsafe_pinMode(pin, mode) } }
pub fn digital_write (pin:u32, value:u32) { unsafe { unsafe_digitalWrite(pin, value) } }
pub fn get_pin_led () -> u32 { unsafe { unsafe_getPinLED() } }

@ -0,0 +1,20 @@
# Prepare
#rustup target add wasm32-unknown-unknown
# Compile
rustc -O --crate-type=cdylib \
--target=wasm32-unknown-unknown \
-C link-arg=-zstack-size=4096 \
-C link-arg=-s \
-o app.wasm app.rs
# Optimize (optional)
#wasm-opt -O3 app.wasm -o app.wasm
wasm-strip app.wasm
# Convert to WAT
#wasm2wat app.wasm -o app.wat
# Convert to C header
xxd -i app.wasm > app.wasm.h

@ -0,0 +1,53 @@
package main
const LOW = 0
const HIGH = 1
const INPUT = 0
const OUTPUT = 1
const INPUT_PULLUP = 2
//go:wasm-module arduino
//go:export millis
func millis() uint
//go:wasm-module arduino
//go:export delay
func delay(ms uint)
//go:wasm-module arduino
//go:export pinMode
func pinMode(pin, mode uint)
//go:wasm-module arduino
//go:export digitalWrite
func digitalWrite(pin, value uint)
//go:wasm-module arduino
//go:export getPinLED
func getPinLED() uint
const LED uint = 19
func setup() {
pinMode(LED, 1)
}
func loop() {
digitalWrite(LED, HIGH)
delay(100)
digitalWrite(LED, LOW)
delay(900)
}
/*
* Entry point
*/
func main() {
setup()
for { loop() }
}

@ -0,0 +1,44 @@
unsigned char app_wasm[] = {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x05, 0x60,
0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60,
0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x02, 0x4e,
0x04, 0x03, 0x65, 0x6e, 0x76, 0x0d, 0x69, 0x6f, 0x5f, 0x67, 0x65, 0x74,
0x5f, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x00, 0x03, 0x07, 0x61, 0x72,
0x64, 0x75, 0x69, 0x6e, 0x6f, 0x07, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64,
0x65, 0x00, 0x01, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x0c,
0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65,
0x00, 0x01, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x05, 0x64,
0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03, 0x08, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x1c, 0x04,
0x7f, 0x00, 0x41, 0x80, 0x80, 0x04, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x80,
0x04, 0x0b, 0x7f, 0x00, 0x41, 0x80, 0x80, 0x04, 0x0b, 0x7f, 0x00, 0x41,
0x80, 0x08, 0x0b, 0x07, 0x7e, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
0x79, 0x02, 0x00, 0x11, 0x5f, 0x5f, 0x77, 0x61, 0x73, 0x6d, 0x5f, 0x63,
0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x00, 0x04, 0x06,
0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x05, 0x08, 0x63, 0x77, 0x61,
0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x07, 0x0b, 0x5f, 0x5f, 0x68, 0x65,
0x61, 0x70, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x03, 0x00, 0x06, 0x6d, 0x65,
0x6d, 0x73, 0x65, 0x74, 0x00, 0x09, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6d,
0x65, 0x00, 0x0a, 0x0c, 0x5f, 0x5f, 0x64, 0x73, 0x6f, 0x5f, 0x68, 0x61,
0x6e, 0x64, 0x6c, 0x65, 0x03, 0x01, 0x0a, 0x5f, 0x5f, 0x64, 0x61, 0x74,
0x61, 0x5f, 0x65, 0x6e, 0x64, 0x03, 0x02, 0x0d, 0x5f, 0x5f, 0x67, 0x6c,
0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0a,
0xc1, 0x01, 0x07, 0x03, 0x00, 0x01, 0x0b, 0x04, 0x00, 0x10, 0x06, 0x0b,
0x44, 0x01, 0x02, 0x7f, 0x3f, 0x00, 0x41, 0x10, 0x74, 0x41, 0x80, 0x80,
0x04, 0x6b, 0x41, 0x06, 0x76, 0x21, 0x01, 0x02, 0x40, 0x03, 0x40, 0x20,
0x00, 0x20, 0x01, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, 0x80, 0x80, 0x7c,
0x46, 0x0d, 0x02, 0x20, 0x00, 0x41, 0x80, 0x80, 0x04, 0x6a, 0x41, 0x00,
0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x0c, 0x01,
0x0b, 0x0b, 0x10, 0x00, 0x1a, 0x0f, 0x0b, 0x00, 0x0b, 0x07, 0x00, 0x10,
0x06, 0x10, 0x08, 0x00, 0x0b, 0x24, 0x00, 0x41, 0x13, 0x41, 0x01, 0x10,
0x01, 0x03, 0x40, 0x41, 0x13, 0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00,
0x10, 0x03, 0x41, 0x13, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10,
0x03, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x37, 0x01, 0x02, 0x7f, 0x41, 0x00,
0x20, 0x00, 0x6b, 0x21, 0x04, 0x02, 0x40, 0x03, 0x40, 0x20, 0x02, 0x20,
0x03, 0x47, 0x04, 0x40, 0x20, 0x03, 0x20, 0x04, 0x46, 0x0d, 0x02, 0x20,
0x00, 0x20, 0x03, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x41,
0x01, 0x6a, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x00, 0x0f, 0x0b,
0x00, 0x0b, 0x0c, 0x00, 0x41, 0xf8, 0xff, 0x03, 0x42, 0x00, 0x37, 0x03,
0x00, 0x00, 0x0b
};
unsigned int app_wasm_len = 483;

@ -0,0 +1,19 @@
# Prepare
export PATH=$PATH:/usr/local/tinygo/bin
export GOROOT=/opt/go
# Compile
tinygo build -target wasm \
-panic trap -wasm-abi generic \
-heap-size 2048 \
-o app.wasm app.go
# Optimize (optional)
#wasm-opt -O3 app.wasm -o app.wasm
wasm-strip app.wasm
# Convert to WAT
#wasm2wat app.wasm -o app.wat
# Convert to C header
xxd -i app.wasm > app.wasm.h

@ -21,5 +21,6 @@
#define m3ApiRawFunction(NAME) const void * NAME (IM3Runtime runtime, uint64_t * _sp, void * _mem)
#define m3ApiReturn(VALUE) { *raw_return = (VALUE); return m3Err_none; }
#define m3ApiTrap(VALUE) { return VALUE; }
#define m3ApiSuccess() { return m3Err_none; }
#endif // m3_api_defs_h

Loading…
Cancel
Save