forked from Mirrors/wasm3
parent
d26aa6183d
commit
b97ef7794e
@ -0,0 +1 @@
|
||||
.pio
|
@ -0,0 +1,19 @@
|
||||
## Arduino blink example
|
||||
|
||||
This example was tested with ESP32.
|
||||
ESP8266 is almost working (just needs a workaround for 64KiB wasm pages).
|
||||
|
||||
`./wasm` 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.
|
||||
|
||||
To run the example on ESP32:
|
||||
|
||||
```sh
|
||||
pio run -e esp32 -t upload && pio device monitor
|
||||
```
|
||||
|
@ -0,0 +1,38 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
board_build.f_cpu = 240000000L
|
||||
|
||||
monitor_speed = 115200
|
||||
|
||||
src_build_flags =
|
||||
-DLED_BUILTIN=19
|
||||
-DESP32 -Dd_m3LogOutput=false
|
||||
-O3 -flto
|
||||
-Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
framework = arduino
|
||||
board_build.f_cpu = 160000000L
|
||||
|
||||
monitor_speed = 115200
|
||||
upload_speed = 460800
|
||||
|
||||
src_build_flags =
|
||||
-DLED_BUILTIN=13
|
||||
-DESP8266 -Dd_m3FixedHeap=0x6000 -Dd_m3LinearMemLimit=2048 -Dd_m3LogOutput=false
|
||||
-O3 -flto
|
||||
-Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
|
@ -0,0 +1,86 @@
|
||||
#include "m3/m3_api_defs.h"
|
||||
#include "m3/m3_env.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
* Note: each RawFunction should complete with one of these calls:
|
||||
* m3ApiReturn(val) - Returns a value
|
||||
* m3ApiSuccess() - Returns void (and no traps)
|
||||
* m3ApiTrap(trap) - Returns a trap
|
||||
*/
|
||||
|
||||
m3ApiRawFunction(m3_arduino_millis)
|
||||
{
|
||||
m3ApiReturnType (uint32_t)
|
||||
|
||||
m3ApiReturn(millis());
|
||||
}
|
||||
|
||||
m3ApiRawFunction(m3_arduino_delay)
|
||||
{
|
||||
m3ApiGetArg (uint32_t, ms)
|
||||
|
||||
//printf("api: delay %d\n", ms); // you can also trace API calls
|
||||
|
||||
delay(ms);
|
||||
|
||||
m3ApiSuccess();
|
||||
}
|
||||
|
||||
// This maps pin modes from arduino_wasm_api.h
|
||||
// to actual platform-specific values
|
||||
uint8_t mapPinMode(uint8_t mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case (0): return INPUT;
|
||||
case (1): return OUTPUT;
|
||||
case (2): return INPUT_PULLUP;
|
||||
}
|
||||
return INPUT;
|
||||
}
|
||||
|
||||
m3ApiRawFunction(m3_arduino_pinMode)
|
||||
{
|
||||
m3ApiGetArg (uint32_t, pin)
|
||||
m3ApiGetArg (uint32_t, mode)
|
||||
|
||||
pinMode(pin, mapPinMode(mode));
|
||||
|
||||
m3ApiSuccess();
|
||||
}
|
||||
|
||||
m3ApiRawFunction(m3_arduino_digitalWrite)
|
||||
{
|
||||
m3ApiGetArg (uint32_t, pin)
|
||||
m3ApiGetArg (uint32_t, value)
|
||||
|
||||
digitalWrite(pin, value);
|
||||
|
||||
m3ApiSuccess();
|
||||
}
|
||||
|
||||
// This is a convenience function
|
||||
m3ApiRawFunction(m3_arduino_getPinLED)
|
||||
{
|
||||
m3ApiReturnType (uint32_t)
|
||||
|
||||
m3ApiReturn(LED_BUILTIN);
|
||||
}
|
||||
|
||||
|
||||
M3Result m3_LinkArduino (IM3Runtime runtime)
|
||||
{
|
||||
IM3Module module = runtime->modules;
|
||||
const char* arduino = "arduino";
|
||||
|
||||
m3_LinkRawFunction (module, arduino, "millis", "i()", &m3_arduino_millis);
|
||||
m3_LinkRawFunction (module, arduino, "delay", "v(i)", &m3_arduino_delay);
|
||||
m3_LinkRawFunction (module, arduino, "pinMode", "v(ii)", &m3_arduino_pinMode);
|
||||
m3_LinkRawFunction (module, arduino, "digitalWrite", "v(ii)", &m3_arduino_digitalWrite);
|
||||
|
||||
m3_LinkRawFunction (module, arduino, "getPinLED", "i()", &m3_arduino_getPinLED);
|
||||
|
||||
return m3Err_none;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
../../../source
|
@ -0,0 +1,70 @@
|
||||
//
|
||||
// Wasm3 - high performance WebAssembly interpreter written in C.
|
||||
//
|
||||
// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy.
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "m3/m3.h"
|
||||
|
||||
#include "../wasm/arduino_app.wasm.h"
|
||||
|
||||
M3Result m3_LinkArduino (IM3Runtime runtime);
|
||||
|
||||
#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; }
|
||||
|
||||
void wasm_task(void*)
|
||||
{
|
||||
M3Result result = m3Err_none;
|
||||
|
||||
IM3Environment env = m3_NewEnvironment ();
|
||||
if (!env) FATAL("m3_NewEnvironment failed");
|
||||
|
||||
IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL);
|
||||
if (!runtime) FATAL("m3_NewRuntime failed");
|
||||
|
||||
IM3Module module;
|
||||
result = m3_ParseModule (env, &module, arduino_app_wasm, arduino_app_wasm_len-1);
|
||||
if (result) FATAL("m3_ParseModule: %s", result);
|
||||
|
||||
result = m3_LoadModule (runtime, module);
|
||||
if (result) FATAL("m3_LoadModule: %s", result);
|
||||
|
||||
result = m3_LinkArduino (runtime);
|
||||
if (result) FATAL("m3_LinkArduino: %s", result);
|
||||
|
||||
IM3Function f;
|
||||
result = m3_FindFunction (&f, runtime, "_start");
|
||||
if (result) FATAL("m3_FindFunction: %s", result);
|
||||
|
||||
printf("Running WebAssembly...\n");
|
||||
|
||||
const char* i_argv[1] = { NULL };
|
||||
result = m3_CallWithArgs (f, 0, i_argv);
|
||||
|
||||
if (result) FATAL("m3_CallWithArgs: %s", result);
|
||||
|
||||
// Should not arrive here
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
delay(100);
|
||||
|
||||
Serial.print("\nWasm3 v" M3_VERSION ", build " __DATE__ " " __TIME__ "\n");
|
||||
|
||||
#ifdef ESP32
|
||||
// On ESP32, we can launch in a separate thread
|
||||
xTaskCreate(&wasm_task, "wasm3", 32768, NULL, 5, NULL);
|
||||
#else
|
||||
wasm_task(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(100);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
|
||||
#include "arduino_wasm_api.h"
|
||||
|
||||
int LED_BUILTIN;
|
||||
|
||||
void setup() {
|
||||
LED_BUILTIN = getPinLED();
|
||||
|
||||
// initialize digital pin LED_BUILTIN as an output.
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
// the loop function runs over and over again forever
|
||||
void loop() {
|
||||
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
delay(100); // wait 100ms
|
||||
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
|
||||
delay(900); // wait 900ms
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry point
|
||||
*/
|
||||
|
||||
WASM_EXPORT
|
||||
void _start() {
|
||||
setup();
|
||||
while (1) { loop(); }
|
||||
}
|
Binary file not shown.
@ -0,0 +1,20 @@
|
||||
unsigned char arduino_app_wasm[] = {
|
||||
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x11, 0x04, 0x60,
|
||||
0x02, 0x7f, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60,
|
||||
0x00, 0x01, 0x7f, 0x02, 0x4e, 0x04, 0x07, 0x61, 0x72, 0x64, 0x75, 0x69,
|
||||
0x6e, 0x6f, 0x09, 0x67, 0x65, 0x74, 0x50, 0x69, 0x6e, 0x4c, 0x45, 0x44,
|
||||
0x00, 0x03, 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, 0x07, 0x61, 0x72, 0x64, 0x75,
|
||||
0x69, 0x6e, 0x6f, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x02, 0x03,
|
||||
0x02, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07, 0x13, 0x02, 0x06,
|
||||
0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74,
|
||||
0x61, 0x72, 0x74, 0x00, 0x04, 0x0a, 0x3a, 0x01, 0x38, 0x01, 0x01, 0x7f,
|
||||
0x41, 0x80, 0x08, 0x10, 0x00, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00,
|
||||
0x41, 0x01, 0x10, 0x01, 0x03, 0x40, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00,
|
||||
0x41, 0x01, 0x10, 0x02, 0x41, 0xe4, 0x00, 0x10, 0x03, 0x41, 0x80, 0x08,
|
||||
0x28, 0x02, 0x00, 0x41, 0x00, 0x10, 0x02, 0x41, 0x84, 0x07, 0x10, 0x03,
|
||||
0x0c, 0x00, 0x0b, 0x00, 0x0b
|
||||
};
|
||||
unsigned int arduino_app_wasm_len = 197;
|
@ -0,0 +1,30 @@
|
||||
#ifndef arduino_wasm_api_h
|
||||
#define arduino_wasm_api_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define WASM_EXPORT extern "C" __attribute__((used)) __attribute__((visibility ("default")))
|
||||
#define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME)))
|
||||
#define WASM_IMPORT(MODULE,NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME)))
|
||||
#define WASM_CONSTRUCTOR __attribute__((constructor))
|
||||
|
||||
#define LOW 0x0
|
||||
#define HIGH 0x1
|
||||
|
||||
#define INPUT 0x0
|
||||
#define OUTPUT 0x1
|
||||
#define INPUT_PULLUP 0x2
|
||||
|
||||
extern "C" {
|
||||
|
||||
WASM_IMPORT("arduino", "millis") uint32_t millis (void);
|
||||
WASM_IMPORT("arduino", "delay") void delay (uint32_t ms);
|
||||
WASM_IMPORT("arduino", "pinMode") void pinMode (uint32_t pin, uint32_t mode);
|
||||
WASM_IMPORT("arduino", "digitalWrite") void digitalWrite (uint32_t pin, uint32_t value);
|
||||
|
||||
// This is a convenience function
|
||||
WASM_IMPORT("arduino", "getPinLED") uint32_t getPinLED (void);
|
||||
|
||||
}
|
||||
|
||||
#endif // arduino_wasm_api_h
|
@ -0,0 +1,5 @@
|
||||
millis
|
||||
delay
|
||||
pinMode
|
||||
digitalWrite
|
||||
getPinLED
|
@ -0,0 +1,12 @@
|
||||
# Compile
|
||||
wasicc -Os \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined-file=arduino_wasm_api.syms \
|
||||
-Wl,--strip-all -nostdlib \
|
||||
-o arduino_app.wasm arduino_app.cpp
|
||||
|
||||
# Optimize (optional)
|
||||
#wasm-opt -O3 arduino_app.wasm -o arduino_app.wasm
|
||||
|
||||
# Convert to header
|
||||
xxd -i arduino_app.wasm > arduino_app.wasm.h
|
Loading…
Reference in new issue