diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml
index 0f539724..19c559d9 100644
--- a/.github/workflows/compile.yml
+++ b/.github/workflows/compile.yml
@@ -5,9 +5,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # Cancel in-flight jobs for the same branch or PR
-env:
- BENCHMARKS_CACHE: "build-benchmarks"
-
jobs:
formatting-check:
name: Formatting Check
@@ -29,7 +26,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
+ os: [ubuntu-20.04, ubuntu-22.04, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -45,7 +42,7 @@ jobs:
compile-with-arduino:
name: (Arduino) Compile on ${{matrix.board.platform-name}}
- needs: formatting-check
+ needs: [formatting-check]
runs-on: ubuntu-latest
env:
SKETCHES_REPORTS_PATH: sketches-reports
@@ -56,6 +53,7 @@ jobs:
- name: HTTPClient
- name: PubSubClient
- name: Adafruit NeoPixel
+ - source-url: https://github.com/me-no-dev/AsyncTCP.git
strategy:
fail-fast: false
matrix:
@@ -72,7 +70,11 @@ jobs:
sketches: |
- platforms/Arduino
steps:
- - uses: actions/checkout@v2
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: 'recursive'
+
- name: Compile sketches
uses: arduino/compile-sketches@v1
with:
@@ -84,6 +86,7 @@ jobs:
${{ env.LIBRARIES }}
enable-deltas-report: true
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
+
- name: Upload sketches report to workflow artifact
uses: actions/upload-artifact@v2
with:
@@ -107,9 +110,10 @@ jobs:
submodules: 'recursive'
- name: Build WARDuino for ESP-IDF
- uses: espressif/esp-idf-ci-action@main
+ uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: latest
target: esp32
+ command: idf.py build -DBUILD_ESP=ON
path: .
diff --git a/.gitignore b/.gitignore
index ab0901f5..78858d21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,5 @@ _deps
.AppleDouble
.LSOverride
+*.old
+
diff --git a/.gitmodules b/.gitmodules
index db420bdd..c81691f9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "tests/sexpr-parser"]
path = tests/integration/sexpr-parser
url = git@github.com:benthepoet/c-sexpr-parser.git
+[submodule "lib/json"]
+ path = lib/json
+ url = https://github.com/nlohmann/json
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2738064a..09efe83d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ if (BUILD_ESP)
if (NOT EXISTS $ENV{IDF_PATH}/tools/cmake/project.cmake)
message(FATAL_ERROR "Can't find $IDF_PATH/tools/cmake/project.cmake. Make sure ESP-IDF is installed and $IDF_PATH is set.")
endif ()
-
+
message(VERBOSE "Using ESP-IDF toolchain")
set(EXTRA_COMPONENT_DIRS "platforms/ESP-IDF")
@@ -25,23 +25,29 @@ project(WARDuino)
# Build the emulator version of WARDuino
if (BUILD_EMULATOR)
+ set(EXTERNAL_LIB_HEADERS lib/json/single_include)
+
find_package(Threads REQUIRED)
+
set(SOURCE_FILES
+ src/WARDuino/WARDuino.cpp
+ src/WARDuino/CallbackHandler.cpp
+ src/Primitives/emulated.cpp
+ src/Interpreter/instructions.cpp
src/Memory/mem.cpp
src/Utils/util.cpp
src/Utils/util_arduino.cpp
- src/Debug/debugger.cpp
src/Utils/macros.cpp
- src/WARDuino/WARDuino.cpp
- src/WARDuino/CallbackHandler.cpp
- src/Primitives/primitives.cpp
- src/Interpreter/instructions.cpp
- )
+ src/Utils/sockets.cpp
+ src/Debug/debugger.cpp
+ src/Edward/proxy.cpp
+ src/Edward/proxy_supervisor.cpp
+ src/Edward/RFC.cpp)
+
set(TEST_FRAMEWORK
- tests/integration/wasm_tests.cpp
- tests/integration/assertion.cpp
- tests/integration/sexpr-parser/src/sexpr.c
- )
+ tests/integration/wasm_tests.cpp
+ tests/integration/assertion.cpp
+ tests/integration/sexpr-parser/src/sexpr.c)
add_definitions(-DINFO=0)
add_definitions(-DDEBUG=0)
@@ -52,11 +58,12 @@ if (BUILD_EMULATOR)
set(CMAKE_CXX_STANDARD 11)
# Set default compile flags for GCC
- if(CMAKE_COMPILER_IS_GNUCXX)
+ if (CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(-g -v -Wall -Wextra -Wunused)
- endif(CMAKE_COMPILER_IS_GNUCXX)
+ endif (CMAKE_COMPILER_IS_GNUCXX)
# WARDuino CLI
add_executable(wdcli platforms/CLI-Emulator/main.cpp ${SOURCE_FILES} ${TEST_FRAMEWORK})
target_link_libraries(wdcli PRIVATE Threads::Threads)
+ target_include_directories(wdcli PRIVATE ${EXTERNAL_LIB_HEADERS})
endif (BUILD_EMULATOR)
diff --git a/README.md b/README.md
index 8a52c21b..cbbdc30d 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,10 @@
-This project is released under the Mozilla Public License 2.0, and is being developed as part of an active research project at the University of Ghent's [TOPL](https://github.com/TOPLLab) lab.
+This project is released under the Mozilla Public License 2.0, and is being developed as part of an active research project at the University of Ghent's [TOPL Lab](https://github.com/TOPLLab).
The WARDuino virtual machine is a WebAssembly runtime for microcontrollers, which runs both under the Arduino and ESP-IDF toolchains.
-The WARDuino project also includes a [VS Code extension](https://github.com/TOPLLab/WARDuino-VSCode) to use the remote debugging facilities offered by the virtual machine.
+The WARDuino project also includes a [VS Code extension](https://github.com/TOPLLab/WARDuino-VSCode) to use both the remote debugging and the out-of-place debugging facilities offered by the virtual machine.
Installation | Examples | Run Specification tests | Documentation
@@ -22,7 +22,7 @@ Supported platforms: Linux (Ubuntu), macOS, ESP-IDF, Arduino
The project uses CMake. Quick install looks like this:
```bash
-git clone git@github.com:TOPLLab/WARDuino.git
+git clone --recursive git@github.com:TOPLLab/WARDuino.git
cd WARDuino
mkdir build-emu
cd build-emu
@@ -36,6 +36,8 @@ The WARDuino VM can be compiled with both the Arduino and ESP-IDF toolchains, an
### Build for ESP-IDF
+> warning: primitive support for IDF is under construction
+
Before you can compile and flash with ESP-IDF, you must install and enable [the toolchain](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html).
You also need to disable the watchdog timer:
@@ -62,6 +64,7 @@ Or simply run `idf.py flash`.
### Build for Arduino
First, install the [arduino-cli](https://arduino.github.io/arduino-cli/0.21/installation/).
+You will also need python3 with the pyserial pacakge.
Second, create the config file:
@@ -69,15 +72,27 @@ Second, create the config file:
arduino-cli config init
```
-If you need additional boards, such as the esp32 boards, you can add them in the generated config file. More information [here](https://arduino.github.io/arduino-cli/0.21/getting-started/).
+If you need additional boards, such as the esp32 boards, you can add them in the generated config file. More information on how to install the esp32 boards can be found here.
+(_note: WARDuino requires at least version 2.0.2 of the esp32 board manager when using esp32 devices)_
Thirdly, make sure you install the `PubSubClient` and `Adafruit NeoPixel` library. (used for MQTT and pixel primitives)
```bash
-arduino-cli lib install "PubSubClient"
-arduino-cli lib install "Adafruit NeoPixel"
+arduino-cli lib install "PubSubClient" # for MQTT
+arduino-cli lib install "Adafruit NeoPixel" # for some primitives
```
+To build for Arduino with WIFI support you need to also install the following third-party libraries.
+(Wou might need to set `enable_unsafe_install` to `true` in your arduino config )
+
+```bash
+arduino-cli lib install FreeRTOS
+arduino-cli lib install --git-url https://github.com/me-no-dev/AsyncTCP.git
+```
+
+If you haven't done so already, clone (or symlink) this repository to `~/Arduino/libraries` to make WARDuino availible to Arduino.
+
+
After this initial installation steps you can start using WARDuino with the Arduino toolchain.
You can upload the example file as follows, starting from the project root:
diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
index c4f050ed..cc37b2a9 100644
--- a/benchmarks/.gitignore
+++ b/benchmarks/.gitignore
@@ -3,3 +3,6 @@ bin/
output
*.csv
+
+*.json
+*.data
diff --git a/benchmarks/all_bench.sh b/benchmarks/all_bench.sh
index 9ed673bf..ce4dcd88 100755
--- a/benchmarks/all_bench.sh
+++ b/benchmarks/all_bench.sh
@@ -18,14 +18,18 @@ to_csv() {
sed -i -n '0~2{N;s/\n/,/p}' $1
}
-sleep 5
-./espruino_bench.sh $tmpdir/espruino
-to_csv $tmpdir/espruino
+#sleep 5
+#./espruino_bench.sh $tmpdir/espruino
+#to_csv $tmpdir/espruino
sleep 5
./warduino_bench.sh $tmpdir/warduino
to_csv $tmpdir/warduino
+sleep 5
+./edward_bench.sh $tmpdir/edward
+to_csv $tmpdir/edward
+
sleep 5
./wasm3_bench.sh $tmpdir/wasm3
to_csv $tmpdir/wasm3
@@ -38,6 +42,8 @@ echo "# Espruino"
cat $tmpdir/espruino
echo "# Warduino"
cat $tmpdir/warduino
+echo "# Edward"
+cat $tmpdir/edward
echo "# Wasm3"
cat $tmpdir/wasm3
echo "# Native"
diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp
index a3f145a9..aafb2261 100644
--- a/benchmarks/benchmarks.cpp
+++ b/benchmarks/benchmarks.cpp
@@ -2,7 +2,8 @@
#include
-#include "../debug.h"
+#include "../src/Debug/debugger.h"
+#include "../src/Utils/macros.h"
#include "../src/WARDuino.h"
#include "timer.h"
@@ -48,7 +49,7 @@ int run_benchmarks(size_t num_benchmarks, string benchmarks[],
char path[MAX_PATH];
unsigned char bytes[MAX_BYTE_CODE_SIZE];
unsigned int bytes_length;
- auto *w = new WARDuino();
+ auto *w = WARDuino::instance();
size_t correct = 0;
for (size_t i = 0; i < num_benchmarks; i++) {
string name = benchmarks[i];
diff --git a/benchmarks/edward.ino.template b/benchmarks/edward.ino.template
new file mode 100644
index 00000000..e566c6b7
--- /dev/null
+++ b/benchmarks/edward.ino.template
@@ -0,0 +1,88 @@
+#include "Arduino.h"
+#include "WARDuino.h"
+
+WARDuino* wac = WARDuino::instance();
+
+SocketServer* server;
+ServerCredentials serverCredentials = {"{{SSID}}", "{{Password}}"};
+uint16_t pullportno = 8080;
+uint16_t pushportno = 8081;
+
+#define D1 5
+
+volatile bool handelingInterrupt = false;
+uint8_t buff[100] = {0};
+uint8_t buff_len = 0;
+
+void ICACHE_RAM_ATTR handleInput() {
+ if (handelingInterrupt) return;
+ handelingInterrupt = true;
+ interrupts();
+
+ while (Serial.available()) {
+ size_t buff_len = 0;
+ while (Serial.available()) {
+ buff[buff_len++] = (int8_t)Serial.read();
+ }
+ if (buff_len) {
+ wac->handleInterrupt(buff_len, buff);
+ }
+ }
+ handelingInterrupt = false;
+}
+
+void startDebuggerStd(void* pvParameter) {
+ int valread;
+ uint8_t buffer[1024] = {0};
+ wac->debugger->setChannel(fileno(stdout));
+ write(fileno(stdout), "Got a message ... \n", 19);
+ while (true) {
+ // taskYIELD();
+ // vTaskDelay(100 / portTICK_PERIOD_MS);
+ yield();
+
+ while (Serial.available()) {
+ size_t buff_len = 0;
+ while (Serial.available()) {
+ buffer[buff_len++] = (int8_t)Serial.read();
+ }
+ if (buff_len) {
+ write(fileno(stdout), "Reading message ..... \n", 19);
+ fflush(stdout);
+ wac->handleInterrupt(valread - 1, buffer);
+ write(fileno(stdout), buffer, valread);
+ fflush(stdout);
+ }
+ }
+ }
+}
+
+void handleInterrupt(size_t len, uint8_t* buff) {
+ wac->handleInterrupt(len, buff);
+}
+
+void setup() {
+ Serial.begin(115200);
+ attachInterrupt(D1, handleInput, CHANGE);
+
+ // create & connect SocketServer
+ SocketServer::createServer(pullportno, pushportno, &handleInterrupt);
+ server = SocketServer::getServer();
+ server->connect2Wifi(&serverCredentials);
+}
+
+void loop() {
+ disableCore0WDT();
+ Module* m = wac->load_module(impl_wasm, impl_wasm_len, {});
+ server->begin();
+
+ printf("LOADED \n\n");
+ xTaskCreate(startDebuggerStd, "Debug Thread", 5000, NULL, 1, NULL);
+ printf("START\n\n");
+ for (int i = 0; i < 10; i++) {
+ wac->run_module(m);
+ printf("%d: %u\n", i, m->stack->value.uint32);
+ }
+ wac->unload_module(m);
+ printf("DONE\n\n");
+}
\ No newline at end of file
diff --git a/benchmarks/edward_bench.sh b/benchmarks/edward_bench.sh
new file mode 100755
index 00000000..7efea3c9
--- /dev/null
+++ b/benchmarks/edward_bench.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/sh
+# Name: Upload all programs in bench.list to arduino (WARDuino) and time
+# By Robbert Gurdeep Singh
+################################################################################
+tmpfile="$(mktemp --tmpdir)"
+trap "rm '$tmpfile'" EXIT
+cd "$(dirname "$0")"
+date >$1
+make clean all
+make -C tasks all
+
+cat bench.list | while read l; do
+ echo $l | tee -a $1
+ ../scripts/upload ${BOARD:-ESP32WROVER} ./tasks/$l/wast/edward/edward.ino -p /dev/ttyUSB0 2>&1 >"$tmpfile"
+ if [ "$?" -eq "0" ]; then
+ echo "flashed"
+ python3 flash_and_check.py | tee -a $1
+ else
+ cat $tmpfile
+ echo "FAILED!"
+ exit 1
+ fi
+done
diff --git a/benchmarks/flash_and_check.py b/benchmarks/flash_and_check.py
index b5e29449..d83294e6 100644
--- a/benchmarks/flash_and_check.py
+++ b/benchmarks/flash_and_check.py
@@ -7,6 +7,7 @@
import serial.tools.list_ports
import time
import sys
+import math
def await_output(s: serial.Serial, target: str, failure=None):
@@ -49,19 +50,17 @@ def await_output(s: serial.Serial, target: str, failure=None):
port = ports[0]
print(f"using {port}", file=sys.stderr)
+
with serial.Serial(port, 115200) as serial:
if len(sys.argv) == 2:
- with open(sys.argv[1], "rb") as inputText:
- serial.write(inputText.read(-1))
- serial.write(b'\n\n')
- print("Bytes sent", file=sys.stderr)
- print("Await start", file=sys.stderr)
- await_output(serial, "START\n")
- startTime = time.monotonic()
- print("START found, waiting for DONE", file=sys.stderr)
- success = await_output(serial, "DONE\n", failure="Guru Meditation Error")
- if success:
- endTime = time.monotonic()
- print(endTime - startTime)
- else:
- print("\nnan")
+ print("Await start", file=sys.stderr)
+ await_output(serial, "START\n")
+ startTime = time.monotonic()
+ print("START found, waiting for DONE", file=sys.stderr)
+ success = await_output(serial, "DONE\n", failure="Guru Meditation Error")
+ if success:
+ endTime = time.monotonic()
+ print(f"{sys.argv[1]}: iterations=1 runtime: {math.floor((endTime - startTime) * 1000000)}us")
+ else:
+ print("\nnan")
+
diff --git a/benchmarks/makefile b/benchmarks/makefile
index 3ae306e9..95b6bc36 100644
--- a/benchmarks/makefile
+++ b/benchmarks/makefile
@@ -15,7 +15,7 @@ DEBUGFLAGS = -DDEBUG=$(DEBUG) -DTRACE=$(TRACE) -DINFO=$(INFO) -DWARN=$(WARN)
CXX = g++
CC = gcc
CFLAGS = -g -Wall -c
-CXXFLAGS = -g -v -std=c++11 -Wall
+CXXFLAGS = -g -v -std=c++11 -I ../lib/json/single_include -Wall
@@ -26,15 +26,20 @@ TARGET = warduino_benchmark
TASKS = $(notdir $(patsubst %/.,%,$(wildcard tasks/*/.)))
CXXSOURCES = \
- ../mem.cpp \
- ../util.cpp \
- ../util_arduino.cpp \
- ../interrupt_operations.cpp \
- ../debug.cpp \
- ../WARDuino.cpp \
- ../primitives.cpp \
- ../instructions.cpp \
- ../glue.cpp \
+ ../src/Memory/mem.cpp \
+ ../src/Utils/util.cpp \
+ ../src/Utils/util_arduino.cpp \
+ ../src/Debug/debugger.cpp \
+ ../src/Utils/macros.cpp \
+ ../src/WARDuino/WARDuino.cpp \
+ ../src/WARDuino/CallbackHandler.cpp \
+ ../src/Primitives/emulated.cpp \
+ ../src/Interpreter/instructions.cpp \
+ ../src/Edward/RFC.cpp \
+ ../src/Edward/proxy.cpp \
+ ../src/Edward/proxy_supervisor.cpp \
+ ../src/Utils/sockets.cpp \
+ ../lib/json/single_include/nlohmann/json.hpp \
benchmarks.cpp
all: $(OUTPUTDIR)$(TARGET) $(addprefix tasks/,$(addsuffix /wast/impl.wasm, $(TASKS)))
@@ -51,8 +56,8 @@ run: all
$(OUTPUTDIR)$(TARGET)
clean: mostlyclean
- $(MAKE) -C tasks clean
+ -$(MAKE) -C tasks clean
mostlyclean:
- $(RM) -rf $(OUTPUTDIR)
- $(RM) $(COBJECTS)
+ -$(RM) -rf $(OUTPUTDIR)
+ -$(RM) $(COBJECTS)
diff --git a/benchmarks/native_bench.sh b/benchmarks/native_bench.sh
index 3d87de0d..9b71d803 100755
--- a/benchmarks/native_bench.sh
+++ b/benchmarks/native_bench.sh
@@ -1,24 +1,20 @@
#!/usr/bin/sh
-# Name: Upload all programs in bench.list to arduino and time
-# By Robbert Gurdeep Singh
+# This scripts takes the name of a benchmark from the tasks folder and uploads
+# it to arduino and times the execution
################################################################################
+
tmpfile="$(mktemp --tmpdir)"
trap "rm '$tmpfile'" EXIT
cd "$(dirname "$0")"
-outloc=${1:--}
-date >$1
-make clean all
-make -C tasks all
+outloc=${2:--}
-cat bench.list | while read l; do
- echo $l | tee -a $1
- ../scripts/upload ${BOARD:-ESP32WROVER} ./tasks/$l/c/arduino.ino 2>&1 >"$tmpfile"
- if [ "$?" -eq "0" ]; then
- echo "flashed"
- python flash_and_check.py | tee -a $1
- else
- cat $tmpfile
- echo "FAILED!"
- exit 1
- fi
-done
+echo $1 | tee -a $2
+./upload ${BOARD:-ESP32WROVER} ./tasks/$1/c/c.ino 2>&1 >"$tmpfile"
+if [ "$?" -eq "0" ]; then
+ echo "flashed"
+ python3 flash_and_check.py $1 | tee -a $2
+else
+ cat $tmpfile
+ echo "FAILED!"
+ exit 1
+fi
diff --git a/benchmarks/rebench.conf b/benchmarks/rebench.conf
new file mode 100644
index 00000000..84bc6310
--- /dev/null
+++ b/benchmarks/rebench.conf
@@ -0,0 +1,45 @@
+# this run definition will be chosen if no parameters are given to rebench
+default_experiment: all
+default_data_file: 'example.data'
+
+reporting:
+ rebenchdb:
+ db_url: https://rebench.stefan-marr.de/rebenchdb
+ repo_url: https://github.com/TOPLLab/WARDuino
+ record_all: true
+ project_name: WARDuino
+
+# a set of suites with different benchmarks and possibly different settings
+benchmark_suites:
+ Microbenchmarks:
+ gauge_adapter: RebenchLog
+ command: ""
+ benchmarks:
+ - catalan
+ - fac
+ - fib
+ - gcd
+ - primes
+ - tak
+ - tak-mem
+
+# a set of executables for the benchmark execution
+executors:
+ warduino:
+ path: .
+ executable: warduino_bench.sh
+ env:
+ PATH: /snap/bin/:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ args: " %(benchmark)s"
+ build:
+ - cd tasks; make
+
+
+# combining benchmark suites and executions
+experiments:
+ Example:
+ suites:
+ - Microbenchmarks
+ executions:
+ - warduino
+
diff --git a/benchmarks/tasks/.gitignore b/benchmarks/tasks/.gitignore
index 60b2a44a..f97f5809 100644
--- a/benchmarks/tasks/.gitignore
+++ b/benchmarks/tasks/.gitignore
@@ -1,4 +1,5 @@
*/wast/warduino/
+*/wast/edward/
*/wast/wasm3/
*/wast/*.wasm
*/wast/*.wast
diff --git a/benchmarks/tasks/makefile b/benchmarks/tasks/makefile
index 53f9096b..4d5c6deb 100644
--- a/benchmarks/tasks/makefile
+++ b/benchmarks/tasks/makefile
@@ -1,6 +1,6 @@
TASKS=$(patsubst %/.,%,$(wildcard */.))
-all: $(addsuffix /wast/warduino/warduino.ino,$(TASKS)) $(addsuffix /wast/wasm3/wasm3.ino,$(TASKS)) $(addsuffix /wast/impl.wast,$(TASKS)) $(addsuffix /wast/impl.wasm,$(TASKS)) $(addsuffix /c/arduino.ino,$(TASKS))
+all: $(addsuffix /wast/warduino/warduino.ino,$(TASKS)) $(addsuffix /wast/edward/edward.ino,$(TASKS)) $(addsuffix /wast/wasm3/wasm3.ino,$(TASKS)) $(addsuffix /wast/impl.wast,$(TASKS)) $(addsuffix /wast/impl.wasm,$(TASKS)) $(addsuffix /c/c.ino,$(TASKS))
echo $(TASKS)
@@ -8,16 +8,22 @@ all: $(addsuffix /wast/warduino/warduino.ino,$(TASKS)) $(addsuffix /wast/wasm3/w
%/wast/warduino/warduino.ino: %/wast/impl.wasm
-mkdir $(@D)
xxd -i $< $@
- sed -i 's/[^ ]*_impl_wasm/impl_wasm/' $@
+ sed -i 's/[^ ]*_impl_wasm/impl_wasm/' $@
cat ../warduino.ino.template >> $@
+%/wast/edward/edward.ino: %/wast/impl.wasm
+ -mkdir $(@D)
+ xxd -i $< $@
+ sed -i 's/[^ ]*_impl_wasm/impl_wasm/' $@
+ cat ../edward.ino.template >> $@
+
%/wast/wasm3/wasm3.ino: %/wast/impl.wasm
-mkdir $(@D)
xxd -i $< $@
sed -i 's/[^ ]*_impl_wasm/impl_wasm/' $@
cat ../wasm3.ino.template >> $@
-%/c/arduino.ino: %/wast/impl.c ../c.ino.template
+%/c/c.ino: %/wast/impl.c ../c.ino.template
-mkdir $(@D)
echo '#include "Arduino.h"' > $@
echo '#pragma GCC optimize ("O0")' >> $@
@@ -43,5 +49,5 @@ all: $(addsuffix /wast/warduino/warduino.ino,$(TASKS)) $(addsuffix /wast/wasm3/w
wasm2wat -f $< > $@
clean:
- -find -iname "impl.wast" -o -iname "impl.wasm" -o -iname "arduino.ino" -o -iname "warduino.ino" -o -iname "wasm3.ino" | xargs rm
+ -find -iname "impl.wast" -o -iname "impl.wasm" -o -iname "c.ino" -o -iname "warduino.ino" -o -iname "edward.ino" -o -iname "wasm3.ino" | xargs rm
diff --git a/scripts/upload b/benchmarks/upload
similarity index 100%
rename from scripts/upload
rename to benchmarks/upload
diff --git a/benchmarks/warduino.ino.template b/benchmarks/warduino.ino.template
index f07a8a3c..d682df8d 100644
--- a/benchmarks/warduino.ino.template
+++ b/benchmarks/warduino.ino.template
@@ -1,8 +1,7 @@
#include "Arduino.h"
#include "WARDuino.h"
-WARDuino wac;
-
+WARDuino* wac = WARDuino::instance();
#define D1 5
@@ -18,10 +17,10 @@ void ICACHE_RAM_ATTR handleInput() {
while (Serial.available()) {
size_t buff_len = 0;
while (Serial.available()) {
- buff[buff_len++] = (int8_t) Serial.read();
+ buff[buff_len++] = (int8_t)Serial.read();
}
if (buff_len) {
- wac.handleInterrupt(buff_len, buff);
+ wac->handleInterrupt(buff_len, buff);
}
}
handelingInterrupt = false;
@@ -33,13 +32,13 @@ void setup() {
}
void loop() {
- Module *m = wac.load_module(impl_wasm, impl_wasm_len, {});
+ Module *m = wac->load_module(impl_wasm, impl_wasm_len, {});
delay(1000);
printf("START\n\n");
for (int i = 0; i < 10; i++) {
- wac.run_module(m);
+ wac->run_module(m);
printf("%d: %u\n", i, m->stack->value.uint32);
}
- wac.unload_module(m);
+ wac->unload_module(m);
printf("DONE\n\n");
-}
\ No newline at end of file
+}
diff --git a/benchmarks/warduino_bench.sh b/benchmarks/warduino_bench.sh
index 6ebf364f..4589840c 100755
--- a/benchmarks/warduino_bench.sh
+++ b/benchmarks/warduino_bench.sh
@@ -1,23 +1,20 @@
#!/usr/bin/sh
-# Name: Upload all programs in bench.list to arduino (WARDuino) and time
-# By Robbert Gurdeep Singh
+# This scripts takes the name of a benchmark from the tasks folder and uploads
+# it to arduino and times the execution
################################################################################
+
tmpfile="$(mktemp --tmpdir)"
trap "rm '$tmpfile'" EXIT
cd "$(dirname "$0")"
-date >$1
-make clean all
-make -C tasks all
+outloc=${2:--}
-cat bench.list | while read l; do
- echo $l | tee -a $1
- ../scripts/upload ${BOARD:-ESP32WROVER} ./tasks/$l/wast/warduino/warduino.ino 2>&1 >"$tmpfile"
- if [ "$?" -eq "0" ]; then
- echo "flashed"
- python flash_and_check.py | tee -a $1
- else
- cat $tmpfile
- echo "FAILED!"
- exit 1
- fi
-done
+echo $1 | tee -a $2
+./upload ${BOARD:-ESP32WROVER} ./tasks/$1/wast/warduino/warduino.ino 2>&1 >"$tmpfile"
+if [ "$?" -eq "0" ]; then
+ echo "flashed"
+ python3 flash_and_check.py $1 | tee -a $2
+else
+ cat $tmpfile
+ echo "FAILED!"
+ exit 1
+fi
diff --git a/documentation/DumpFormat.md b/documentation/DumpFormat.md
index 95c970c1..2b09b7db 100644
--- a/documentation/DumpFormat.md
+++ b/documentation/DumpFormat.md
@@ -2,7 +2,7 @@
WARDuino sends its information dumps as json.
-## Full dump (0x12)
+## Full dump (0x12)
Lists the following items:
@@ -11,11 +11,13 @@ Lists the following items:
- breakpoints (list of pointers to instrs in program buffer)
- functions (all declared functions)
- callstack (the current callstack, bottom to top)
+- locals
+- events (async events currently in CallbackHandler queue)
### Callstack
-The callstack is printed as a list of objects, with the first object the bottom of the stack.
-Each object represents a block with a type:
+The callstack is printed as a list of objects, with the first object the bottom of the stack. Each object represents a
+block with a type:
- Function 0x00
- Init expression 0x01
@@ -29,46 +31,45 @@ When the block is a function it also holds the function index in the `fidx` fiel
```json
{
- "pc":"0x3ffbdc00",
- "start":[
- "0x3ffbdb70"
- ],
- "breakpoints":[
-
- ],
- "functions":[
+ "pc": "0x3ffbdc00",
+ "start": [
+ "0x3ffbdb70"
+ ],
+ "breakpoints": [
+ ],
+ "functions": [
+ {
+ "fidx": "0x3",
+ "from": "0x3ffbdbee",
+ "to": "0x3ffbdbf4"
+ },
+ {
+ "fidx": "0x4",
+ "from": "0x3ffbdbf9",
+ "to": "0x3ffbdc19"
+ }
+ ],
+ "callstack": [
+ {
+ "type": 0,
+ "fidx": "0x4",
+ "sp": -1,
+ "fp": -1,
+ "start": "0x3ffbdbf9",
+ "ra": "0x3ffbdbdf",
+ "callsite": "0x3ffbdbdd"
+ }
+ ],
+ "locals": {
+ "count": 1,
+ "locals": [
{
- "fidx":"0x3",
- "from":"0x3ffbdbee",
- "to":"0x3ffbdbf4"
- },
- {
- "fidx":"0x4",
- "from":"0x3ffbdbf9",
- "to":"0x3ffbdc19"
- }
- ],
- "callstack":[
- {
- "type":0,
- "fidx":"0x4",
- "sp":-1,
- "fp":-1,
- "start":"0x3ffbdbf9",
- "ra":"0x3ffbdbdf",
- "callsite":"0x3ffbdbdd"
+ "type": "i32",
+ "value": 1000,
+ "index": 0
}
- ],
- "locals":{
- "count":1,
- "locals":[
- {
- "type":"i32",
- "value":1000,
- "index":0
- }
- ]
- }
+ ]
+ }
}
```
@@ -80,14 +81,108 @@ The locals can also be retreived on their own with the 0x11 byte.
```json
{
- "count":1,
- "locals":[
- {
- "type":"i32",
- "value":1000,
- "index":0
- }
- ]
+ "count": 1,
+ "locals": [
+ {
+ "type": "i32",
+ "value": 1000,
+ "index": 0
+ }
+ ]
}
```
+## WOOD Dump (0x60)
+
+```json
+{
+ "pc": "0x60000272806e",
+ "start": [
+ "0x600002728000"
+ ],
+ "breakpoints": [
+ ],
+ "stack": [
+ {
+ "idx": 0,
+ "type": "i32",
+ "value": 5
+ },
+ {
+ "idx": 1,
+ "type": "i32",
+ "value": 5
+ },
+ {
+ "idx": 2,
+ "type": "i32",
+ "value": 5
+ }
+ ],
+ "callstack": [
+ {
+ "type": 0,
+ "fidx": "0x3",
+ "sp": -1,
+ "fp": -1,
+ "block_key": "0x0",
+ "ra": "0x60000272805a",
+ "idx": 0
+ },
+ {
+ "type": 3,
+ "fidx": "0x0",
+ "sp": 0,
+ "fp": 0,
+ "block_key": "0x600002728083",
+ "ra": "0x600002728085",
+ "idx": 1
+ },
+ {
+ "type": 0,
+ "fidx": "0x2",
+ "sp": 0,
+ "fp": 0,
+ "block_key": "0x0",
+ "ra": "0x600002728089",
+ "idx": 2
+ },
+ {
+ "type": 4,
+ "fidx": "0x0",
+ "sp": 2,
+ "fp": 1,
+ "block_key": "0x60000272806a",
+ "ra": "0x60000272806c",
+ "idx": 3
+ }
+ ],
+ "globals": [
+ {
+ "idx": 0,
+ "type": "i32",
+ "value": 0
+ },
+ {
+ "idx": 1,
+ "type": "i32",
+ "value": 0
+ }
+ ],
+ "table": {
+ "max": 2,
+ "init": 2,
+ "elements": ""
+ },
+ "memory": {
+ "pages": 2,
+ "max": 32768,
+ "init": 2,
+ "bytes": ""
+ },
+ "br_table": {
+ "size": "0x100",
+ "labels": "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"
+ }
+}
+```
diff --git a/documentation/InstallArduinoESP32.md b/documentation/InstallArduinoESP32.md
new file mode 100644
index 00000000..fe2c662f
--- /dev/null
+++ b/documentation/InstallArduinoESP32.md
@@ -0,0 +1,51 @@
+# Install instructions for Arduino ESP32
+
+To use ESP32 boards with the WARDuino project you need to install the correct board manager for ESP32.
+
+## Installing the board manager for ESP32
+
+To use the ESP32 boards with `arduino-cli` perform the following steps:
+
+1. Init the config file, if you have not done so yet.
+
+```
+arduino-cli config init
+```
+
+2. To find the location of your config file you can run:
+
+```
+arduino-cli config dump --verbose
+```
+
+3. Add the ESP32 board manager URL to the config file:
+
+```
+board_manager:
+ additional_urls:
+ - https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
+```
+
+4. Update index
+
+```
+arduino-cli core update-index
+```
+
+5. Install the ESP32 platform:
+
+```
+arduino-cli core install esp32:esp32
+```
+
+To use ESP32 boards with the WARDuino Project you need at least version 2.0.2 of the board manager.
+you can check your version with:
+
+```
+arduino-cli core list
+```
+
+## Additional information
+
+More information on how to use `arduino-cli` can be found [here](https://arduino.github.io/arduino-cli/0.21/getting-started/).
+
diff --git a/documentation/Interrupts.md b/documentation/Interrupts.md
index 477e9649..0f2766b4 100644
--- a/documentation/Interrupts.md
+++ b/documentation/Interrupts.md
@@ -13,4 +13,4 @@ character, it should match `([0-9A-F][0-9A-F])+`
The first two character of the HEX sequence (that is the first byte of the
translated binary data) differentiates between the various interrup types.
-See: [interrupt_operations.cpp](../interrupt_operations.cpp)
\ No newline at end of file
+See: [src/Debug/Debugger.cpp](../src/Debug/Debugger.cpp)
diff --git a/documentation/OutOfPlaceDebugging.md b/documentation/OutOfPlaceDebugging.md
new file mode 100644
index 00000000..1259c5c6
--- /dev/null
+++ b/documentation/OutOfPlaceDebugging.md
@@ -0,0 +1,37 @@
+# Out-of-place debugging
+
+Aside from traditional remote debugging, the WARDuino virtual machine also supports pull-push debugging.
+
+## Pull-based OOP Debugging
+
+With pull debugging the current application is debugged in a local emulated WARDuino instance, but with live actuator
+and sensor values from a drone device. To get current values, the emulated debugger initiates proxy calls to the drone
+device. The debugger will wait until this call has completed and the result is returned by the drone.
+
+Communication happens through a minimal byte format.
+
+## Push-based OOP Debugging
+
+A drone device can also push live values to the emulated debugger. These will typically be asynchronous events such as
+hardware interrupts, exceptions, ...
+
+Those are represented by `Events` in WARDuino and send by the drone device as simple json:
+
+```json
+{
+ "topic": "topic string",
+ "payload": "payload as a string"
+}
+```
+
+The supported interrupt messages:
+
+1. `interruptDUMPAllEvents (0x70)` dumps all events.
+2. `interruptDUMPEvents (0x71)` this message' code is followed by two bytes, `a` and `b`. The command dumps at most `b`
+ events, starting in the event queue from index `a`.
+3. `interruptPOPEvent (0x72)` tells the VM to remove the event at the front of the queue and process it.
+4. `interruptPUSHEvent (0x73)` this messages' code is followed by a json representation of an event to be pushed on the
+ stack.
+5. `interruptDUMPCallbackmapping (0x74)` requests a dump of the current callback mapping as json.
+6. `interruptRecvCallbackmapping (0x75)` sends a callback mapping as json to replace the current callback mapping.
+
diff --git a/examples/assemblyscript/lib/warduino.ts b/examples/assemblyscript/lib/warduino.ts
index d827eff5..4d712a07 100644
--- a/examples/assemblyscript/lib/warduino.ts
+++ b/examples/assemblyscript/lib/warduino.ts
@@ -11,7 +11,7 @@
@external("env", "wifi_connect") declare function _wifi_connect(ssid: ArrayBuffer, length: i32, password: ArrayBuffer, size: i32): void;
@external("env", "wifi_status") export declare function wifi_status(): i32;
-@external("env", "wifi_connected") declare function _wifi_status(): i32;
+@external("env", "wifi_connected") declare function _wifi_connected(): i32;
@external("env", "wifi_localip") declare function _wifi_localip(buff: ArrayBuffer, buffer_size: u32): i32;
@external("env", "http_get") declare function _http_get(url: ArrayBuffer, url_len: u32, buffer: ArrayBuffer, buffer_size: u32): i32;
@@ -56,7 +56,7 @@ export function print(text: string): void {
export function wifi_connected(): bool {
- return _wifi_status() == 1;
+ return _wifi_connected() === 1;
}
export function wifi_connect(ssid: string, password: string): void {
diff --git a/examples/assemblyscript/main/CMakeLists.txt b/examples/assemblyscript/main/CMakeLists.txt
index f9742f5a..3fdb8c1d 100644
--- a/examples/assemblyscript/main/CMakeLists.txt
+++ b/examples/assemblyscript/main/CMakeLists.txt
@@ -1,14 +1,14 @@
set(SOURCE_FILES
- ../../../src/Memory/mem.cpp
- ../../../src/Utils/util.cpp
- ../../../src/Utils/util_arduino.cpp
- ../../../src/Debug/debugger.cpp
- ../../../src/Utils/macros.cpp
- ../../../src/WARDuino/WARDuino.cpp
- ../../../src/Primitives/primitives.cpp
- ../../../src/Interpreter/instructions.cpp
- ../../../src/WARDuino/CallbackHandler.cpp
- )
+ ../../../src/Memory/mem.cpp
+ ../../../src/Utils/util.cpp
+ ../../../src/Utils/util_arduino.cpp
+ ../../../src/Debug/debugger.cpp
+ ../../../src/Utils/macros.cpp
+ ../../../src/WARDuino/WARDuino.cpp
+ ../../../src/Primitives/emulated.cpp
+ ../../../src/Interpreter/instructions.cpp
+ ../../../src/WARDuino/CallbackHandler.cpp
+ )
idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS "" REQUIRES driver)
diff --git a/examples/assemblyscript/main/smartlamp.ts b/examples/assemblyscript/main/smartlamp.ts
index 67bf90fa..b46e3431 100644
--- a/examples/assemblyscript/main/smartlamp.ts
+++ b/examples/assemblyscript/main/smartlamp.ts
@@ -7,10 +7,12 @@ const PASSWORD = "network-password";
const CLIENT_ID = "random-mqtt-client-id";
function until_connected(connect: () => void,
- connected: () => boolean): void {
+ connected: () => boolean,
+ retry: () => boolean): void {
+ connect();
while (!connected()) {
wd.delay(1000);
- connect();
+ if (retry) connect();
}
}
@@ -40,7 +42,8 @@ export function main(): void {
// Connect to Wi-Fi
until_connected(
() => { wd.wifi_connect(SSID, PASSWORD); },
- wd.wifi_connected);
+ wd.wifi_connected,
+ () => { return wd.wifi_status() === 6; });
let message = "Connected to wifi network with ip: ";
wd.print(message.concat(wd.wifi_localip()));
@@ -48,7 +51,8 @@ export function main(): void {
wd.mqtt_init("192.168.0.24", 1883);
until_connected(
() => { wd.mqtt_connect(CLIENT_ID); wd.mqtt_loop(); },
- () => { return wd.mqtt_connected(); });
+ () => { return wd.mqtt_connected(); },
+ () => { return true; });
// Subscribe to MQTT topic and turn on LED
wd.mqtt_subscribe("LED", callback);
@@ -60,7 +64,8 @@ export function main(): void {
while (true) {
until_connected(
() => { wd.mqtt_connect(CLIENT_ID); wd.mqtt_loop(); },
- () => { return wd.mqtt_connected(); });
+ () => { return wd.mqtt_connected(); },
+ () => { return true; });
wd.sleep(5); // Sleep for 5 seconds
}
diff --git a/examples/assemblyscript/package-lock.json b/examples/assemblyscript/package-lock.json
index 7d6be6f1..4cfe17db 100644
--- a/examples/assemblyscript/package-lock.json
+++ b/examples/assemblyscript/package-lock.json
@@ -1,8 +1,59 @@
{
"name": "smartlamp",
- "version": "1.0.0",
- "lockfileVersion": 1,
+ "version": "0.1.0",
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "smartlamp",
+ "version": "0.1.0",
+ "license": "ISC",
+ "dependencies": {
+ "@assemblyscript/loader": "^0.17.1"
+ },
+ "devDependencies": {
+ "assemblyscript": "^0.17.14"
+ }
+ },
+ "node_modules/@assemblyscript/loader": {
+ "version": "0.17.14",
+ "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.17.14.tgz",
+ "integrity": "sha512-+PVTOfla/0XMLRTQLJFPg4u40XcdTfon6GGea70hBGi8Pd7ZymIXyVUR+vK8wt5Jb4MVKTKPIz43Myyebw5mZA=="
+ },
+ "node_modules/assemblyscript": {
+ "version": "0.17.14",
+ "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.17.14.tgz",
+ "integrity": "sha512-TLuwNvZAIH26wu2puKpAJokzLp10kJkVXxbgDjFFmbW9VF/qg7rkmi0hjsiu41bjoH1UaVgY4vYvbbUeOHtKyg==",
+ "dev": true,
+ "dependencies": {
+ "binaryen": "98.0.0-nightly.20201109",
+ "long": "^4.0.0"
+ },
+ "bin": {
+ "asc": "bin/asc",
+ "asinit": "bin/asinit"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/assemblyscript"
+ }
+ },
+ "node_modules/binaryen": {
+ "version": "98.0.0-nightly.20201109",
+ "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-98.0.0-nightly.20201109.tgz",
+ "integrity": "sha512-iRarAqdH5lMWlMBzrDuJgLYJR2g4QXk93iYE2zpr6gEZkb/jCgDpPUXdhuN11Ge1zZ/6By4DwA1mmifcx7FWaw==",
+ "dev": true,
+ "bin": {
+ "wasm-opt": "bin/wasm-opt"
+ }
+ },
+ "node_modules/long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
+ "dev": true
+ }
+ },
"dependencies": {
"@assemblyscript/loader": {
"version": "0.17.14",
diff --git a/examples/blink/build.sh b/examples/blink/build.sh
index 05a05915..fb7e1ae3 100755
--- a/examples/blink/build.sh
+++ b/examples/blink/build.sh
@@ -17,7 +17,7 @@ if [[ $src == *.wat ]] || [[ $extension == *.wast ]]; then
fi
# Optimize (optional)
-wasm-opt -O3 "${src}.wasm" -o "src.wasm"
+#wasm-opt -O3 "${src}.wasm" -o "src.wasm"
wasm-strip "src.wasm"
echo -e "> optimized src.wasm"
diff --git a/examples/blink/main/CMakeLists.txt b/examples/blink/main/CMakeLists.txt
index f9742f5a..7ddf2d42 100644
--- a/examples/blink/main/CMakeLists.txt
+++ b/examples/blink/main/CMakeLists.txt
@@ -1,16 +1,19 @@
set(SOURCE_FILES
- ../../../src/Memory/mem.cpp
- ../../../src/Utils/util.cpp
- ../../../src/Utils/util_arduino.cpp
- ../../../src/Debug/debugger.cpp
- ../../../src/Utils/macros.cpp
- ../../../src/WARDuino/WARDuino.cpp
- ../../../src/Primitives/primitives.cpp
- ../../../src/Interpreter/instructions.cpp
- ../../../src/WARDuino/CallbackHandler.cpp
- )
+ ../../src/Memory/mem.cpp
+ ../../src/Utils/util.cpp
+ ../../src/Utils/util_arduino.cpp
+ ../../src/Debug/debugger.cpp
+ ../../src/Utils/macros.cpp
+ ../../src/WARDuino/WARDuino.cpp
+ ../../src/Primitives/idf.cpp
+ ../../src/Interpreter/instructions.cpp
+ ../../src/RFC/rfc.cpp
+ ../../src/RFC/proxy_server.cpp
+ ../../src/RFC/SocketServer.cpp
+ ../../src/WARDuino/CallbackHandler.cpp
+ )
-idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS "" REQUIRES driver)
+idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS ../../lib/json/single_include/ REQUIRES driver)
add_definitions(-DESP=1)
diff --git a/examples/rust/.cargo/config b/examples/rust/.cargo/config
new file mode 100644
index 00000000..e4f6290f
--- /dev/null
+++ b/examples/rust/.cargo/config
@@ -0,0 +1,5 @@
+[build]
+target = "wasm32-unknown-unknown"
+rustflags = [
+ "-C", "link-args=-zstack-size=2048 -s",
+]
diff --git a/examples/rust/.gitignore b/examples/rust/.gitignore
new file mode 100644
index 00000000..40fac1ff
--- /dev/null
+++ b/examples/rust/.gitignore
@@ -0,0 +1,17 @@
+.idea
+idf/
+
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
diff --git a/examples/rust/CMakeLists.txt b/examples/rust/CMakeLists.txt
new file mode 100644
index 00000000..bb72b053
--- /dev/null
+++ b/examples/rust/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(rust)
+
diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml
new file mode 100644
index 00000000..86d0c3f6
--- /dev/null
+++ b/examples/rust/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "button"
+version = "0.1.0"
+authors = ["Tom Lauwaerts "]
+edition = "2018"
+
+[lib]
+path = "main/button.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+warduino = { path = "lib/warduino" }
+
+[profile.dev]
+panic = "abort"
+opt-level = 2
+
+[profile.release]
+panic = "abort"
+opt-level = 3
+debug = true
diff --git a/examples/rust/README.md b/examples/rust/README.md
new file mode 100644
index 00000000..259df2ce
--- /dev/null
+++ b/examples/rust/README.md
@@ -0,0 +1,14 @@
+# Button demo
+
+This demo is used to show case that interrupts on pins can also be subscribed on with the WARDuino callback system.
+
+## Running the demo
+
+Flash the wasm code and WARDuino VM onto the esp with the following commands:
+
+```
+./build.sh
+```
+
+The program listens for changes on pin 26.
+
diff --git a/examples/rust/button.wat b/examples/rust/button.wat
new file mode 100644
index 00000000..e7eefecf
--- /dev/null
+++ b/examples/rust/button.wat
@@ -0,0 +1,57 @@
+(module
+ (type $t0 (func (param i32 i32)))
+ (type $t1 (func (param i32) (result i32)))
+ (type $t2 (func (param i32 i32 i32)))
+ (type $t3 (func (param i32 i32 i32 i32 i32)))
+ (type $t4 (func))
+ (import "env" "chip_pin_mode" (func $env.chip_pin_mode (type $t0)))
+ (import "env" "chip_digital_write" (func $env.chip_digital_write (type $t0)))
+ (import "env" "chip_digital_read" (func $env.chip_digital_read (type $t1)))
+ (import "env" "subscribe_interrupt" (func $env.subscribe_interrupt (type $t2)))
+ (func $f4 (type $t3) (param $p0 i32) (param $p1 i32) (param $p2 i32) (param $p3 i32) (param $p4 i32)
+ i32.const 26
+ i32.const 26
+ call $f8
+ i32.const 1
+ i32.ne
+ call $f7)
+ (func $main (type $t4)
+ i32.const 25
+ i32.const 0
+ call $f6
+ i32.const 26
+ i32.const 2
+ call $f6
+ i32.const 25
+ i32.const 1
+ i32.const 2
+ call $f9
+ loop $L0
+ br $L0
+ end)
+ (func $f6 (type $t0) (param $p0 i32) (param $p1 i32)
+ local.get $p0
+ local.get $p1
+ call $env.chip_pin_mode)
+ (func $f7 (type $t0) (param $p0 i32) (param $p1 i32)
+ local.get $p0
+ local.get $p1
+ call $env.chip_digital_write)
+ (func $f8 (type $t1) (param $p0 i32) (result i32)
+ local.get $p0
+ call $env.chip_digital_read)
+ (func $f9 (type $t2) (param $p0 i32) (param $p1 i32) (param $p2 i32)
+ local.get $p0
+ local.get $p1
+ local.get $p2
+ call $env.subscribe_interrupt)
+ (table $T0 2 2 funcref)
+ (memory $memory 1)
+ (global $g0 (mut i32) (i32.const 2048))
+ (global $__data_end i32 (i32.const 2048))
+ (global $__heap_base i32 (i32.const 2048))
+ (export "memory" (memory $memory))
+ (export "main" (func $main))
+ (export "__data_end" (global $__data_end))
+ (export "__heap_base" (global $__heap_base))
+ (elem $e0 (i32.const 1) func $f4))
diff --git a/examples/rust/lib/warduino/.gitignore b/examples/rust/lib/warduino/.gitignore
new file mode 100644
index 00000000..20694291
--- /dev/null
+++ b/examples/rust/lib/warduino/.gitignore
@@ -0,0 +1,5 @@
+target/
+*.wasm*
+*.wat
+*.log
+*.h
diff --git a/examples/rust/lib/warduino/Cargo.toml b/examples/rust/lib/warduino/Cargo.toml
new file mode 100644
index 00000000..524c4d2e
--- /dev/null
+++ b/examples/rust/lib/warduino/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "warduino"
+version = "0.1.0"
+authors = ["Tom Lauwaerts "]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/examples/rust/lib/warduino/src/lib.rs b/examples/rust/lib/warduino/src/lib.rs
new file mode 100644
index 00000000..63d7a4d2
--- /dev/null
+++ b/examples/rust/lib/warduino/src/lib.rs
@@ -0,0 +1,127 @@
+#![allow(dead_code)]
+
+use std::mem;
+
+#[link(wasm_import_module = "env")]
+//#[link(wasm_import_module = "arduino")]
+extern {
+ #[link_name = "test"] pub fn test(f: fn(&str, &str, u32));
+
+ #[link_name = "millis"] fn _millis() -> u32;
+ #[link_name = "chip_delay"] fn _delay(ms: u32);
+ #[link_name = "getPinLED"] fn _getPinLED() -> u32;
+ #[link_name = "chip_pin_mode"] fn _pinMode(pin: u32, mode: u32);
+ #[link_name = "chip_digital_write"] fn _digitalWrite(pin: u32, value: u32);
+ #[link_name = "chip_digital_read"] fn _digitalRead(pin: u32) -> u32;
+ #[link_name = "chip_analog_read"] fn _analogRead(pin: u32) -> i32;
+//}
+
+
+//#[link(wasm_import_module = "serial")]
+//extern {
+ #[link_name = "print_string"] fn _print_buffer(text: *const u8, length: usize);
+ #[link_name = "print_int"] fn _print_int(integer: i32);
+//}
+
+//#[link(wasm_import_module = "wifi")]
+//extern {
+ #[link_name = "wifi_connect"] fn _connect(ssid: &str, password: &str);
+ #[link_name = "wifi_status"] fn _status() -> i32;
+ #[link_name = "wifi_localip"] fn _localip(buffer: *const u8, buffer_length: usize) -> i32;
+//}
+
+//#[link(wasm_import_module = "http")]
+//extern {
+ #[link_name = "http_get"] fn _get(url: *const u8, url_len: usize, buffer: *const u8, buffer_size: usize) -> i32;
+ #[link_name = "http_post"] fn _post(url: *const u8, url_len: usize,
+ body: *const u8, body_len: usize,
+ content_type: *const u8, content_type_len: usize,
+ authorization: *const u8, authorization_len: usize,
+ buffer: *const u8, buffer_size: usize)
+ -> i32;
+
+
+//#[link(wasm_import_module = "interrupt")]
+//extern {
+ #[link_name = "subscribe_interrupt"] fn _sub_interrupt(pin: u32, f: fn(&str, &str, u32), mode: u32);
+ #[link_name = "unsubscribe_interrupt"] fn _unsub_interrupt(pin: u32);
+
+//#[link(wasm_import_module = "mqtt")]
+//extern {
+ #[link_name = "mqtt_init"] fn _mqtt_init(server: *const u8, server_length: usize, port: u32);
+ #[link_name = "mqtt_connect"] fn _mqtt_connect(client_id: *const u8, client_id_length: usize) -> i32;
+ #[link_name = "mqtt_connected"] fn _mqtt_connected() -> i32;
+ #[link_name = "mqtt_state"] fn _mqtt_state() -> i32;
+ #[link_name = "mqtt_publish"] fn _mqtt_publish(topic: *const u8, topic_length: usize, payload: *const u8, payload_length: usize) -> i32;
+ #[link_name = "mqtt_subscribe"] fn _mqtt_subscribe(topic: *const u8, topic_length: usize, f: fn(&str, &str, u32)) -> i32;
+ #[link_name = "mqtt_unsubscribe"] fn _mqtt_unsubscribe(topic: *const u8, topic_length: usize, f: fn(&str, &str, u32)) -> i32;
+ #[link_name = "mqtt_loop"] fn _mqtt_loop() -> i32;
+}
+
+#[repr(C)]
+pub struct Headers {
+ pub content_type: &'static str,
+ pub authorization: &'static str, // TODO make optional
+}
+
+#[repr(C)]
+pub struct PostOptions {
+ pub uri: &'static str,
+ pub body: String,
+ pub headers: Headers,
+}
+
+fn size_of_post_options(options: &PostOptions) -> usize {
+ options.uri.len() + options.body.len() + options.headers.content_type.len()
+}
+
+pub static LOW : u32 = 0x0;
+pub static HIGH : u32 = 0x1;
+
+pub static CHANGE : u32 = 1;
+pub static FALLING : u32 = 2;
+pub static RISING : u32 = 3;
+
+pub static INPUT : u32 = 0x0;
+pub static OUTPUT : u32 = 0x2;
+
+pub fn millis () -> u32 { unsafe { _millis() } }
+pub fn delay (ms: u32) { unsafe { _delay(ms); } }
+pub fn get_pin_led () -> u32 { unsafe { _getPinLED() } }
+pub fn pin_mode (pin: u32, mode: u32) { unsafe { _pinMode(pin, mode) } }
+pub fn digital_write(pin: u32, value: u32) { unsafe { _digitalWrite(pin, value) } }
+pub fn digital_read (pin: u32) -> u32 { unsafe { _digitalRead(pin) } }
+pub fn analog_read (pin: u32) -> i32 { unsafe { _analogRead(pin) } }
+
+pub fn wifi_connect (ssid: &str, password: &str) { unsafe { _connect(ssid, password) } }
+pub fn wifi_status () -> i32 { unsafe { _status() } }
+pub fn wifi_localip () -> String { unsafe { let buffer: [u8; 100] = [0; 100];
+ _localip(buffer.as_ptr(), mem::size_of_val(&buffer) / mem::size_of::());
+ std::str::from_utf8(&buffer).unwrap().to_owned()
+ } }
+
+pub fn get (url: &str, buffer: &[u8]) -> i32 { unsafe { _get(url.as_ptr(), url.len(), buffer.as_ptr(), mem::size_of_val(buffer) / mem::size_of::()) } }
+pub fn post (options: &PostOptions, buffer: &[u8]) -> i32 { unsafe {
+ _post(options.uri.as_ptr(), options.uri.len(),
+ options.body.as_ptr(), options.body.len(),
+ options.headers.content_type.as_ptr(), options.headers.content_type.len(),
+ options.headers.authorization.as_ptr(), options.headers.authorization.len(),
+ buffer.as_ptr(), mem::size_of_val(buffer) / mem::size_of::())
+ }
+}
+
+pub fn print (text: &[u8]) { unsafe { _print_buffer(text.as_ptr(), text.len()) } }
+pub fn print_int (integer: i32) { unsafe { _print_int(integer) } }
+
+pub fn sub_interrupt (pin: u32, f: fn(&str, &str, u32), mode: u32) { unsafe { _sub_interrupt(pin, f, mode) } }
+pub fn unsub_interrupt (pin: u32) { unsafe { _unsub_interrupt(pin) } }
+
+pub fn mqtt_init (server: &str, port: u32) { unsafe { _mqtt_init(server.as_ptr(), server.len(), port) } }
+pub fn mqtt_connect (client_id: &str) -> bool { unsafe { _mqtt_connect(client_id.as_ptr(), client_id.len()) != 0 } }
+pub fn mqtt_connected () -> bool { unsafe { _mqtt_connected() > 0 } }
+pub fn mqtt_state () -> i32 { unsafe { _mqtt_state() } }
+pub fn mqtt_publish (topic: &str, payload: &str) -> i32 { unsafe { _mqtt_publish(topic.as_ptr(), topic.len(), payload.as_ptr(), payload.len()) } }
+pub fn mqtt_subscribe (topic: &str, f: fn(&str, &str, u32)) -> i32 { unsafe { _mqtt_subscribe(topic.as_ptr(), topic.len(), f) } }
+pub fn mqtt_unsubscribe (topic: &str, f: fn(&str, &str, u32)) -> i32 { unsafe { _mqtt_unsubscribe(topic.as_ptr(), topic.len(), f) } }
+pub fn mqtt_loop () -> i32 { unsafe { _mqtt_loop() } }
+
diff --git a/examples/rust/main/CMakeLists.txt b/examples/rust/main/CMakeLists.txt
new file mode 100644
index 00000000..3fdb8c1d
--- /dev/null
+++ b/examples/rust/main/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(SOURCE_FILES
+ ../../../src/Memory/mem.cpp
+ ../../../src/Utils/util.cpp
+ ../../../src/Utils/util_arduino.cpp
+ ../../../src/Debug/debugger.cpp
+ ../../../src/Utils/macros.cpp
+ ../../../src/WARDuino/WARDuino.cpp
+ ../../../src/Primitives/emulated.cpp
+ ../../../src/Interpreter/instructions.cpp
+ ../../../src/WARDuino/CallbackHandler.cpp
+ )
+
+idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS "" REQUIRES driver)
+
+add_definitions(-DESP=1)
+
diff --git a/examples/rust/main/button.rs b/examples/rust/main/button.rs
new file mode 100644
index 00000000..6688a6b2
--- /dev/null
+++ b/examples/rust/main/button.rs
@@ -0,0 +1,27 @@
+use warduino::*;
+
+static BUTTON : u32 = 25;
+static LED : u32 = 26;
+
+fn callback(_topic: &str, _payload: &str, _length: u32) {
+ let val = digital_read(LED);
+ //print(format!("Switch LED to {}\n", (val + 1) % 2).as_bytes());
+ if val == HIGH {
+ digital_write(LED, LOW);
+ } else {
+ digital_write(LED, HIGH);
+ }
+}
+
+#[no_mangle]
+pub fn main() {
+ pin_mode(BUTTON, INPUT);
+ pin_mode(LED, OUTPUT);
+
+ sub_interrupt(BUTTON, callback, FALLING);
+
+ loop {
+ //delay(1);
+ }
+}
+
diff --git a/examples/rust/main/main.cpp b/examples/rust/main/main.cpp
new file mode 100644
index 00000000..133c2ad3
--- /dev/null
+++ b/examples/rust/main/main.cpp
@@ -0,0 +1,52 @@
+//
+// WARDuino - WebAssembly interpreter for embedded devices.
+//
+//
+#include
+
+#include "../../../../src/WARDuino.h"
+#include "driver/gpio.h"
+#include "driver/uart.h"
+#include "esp_err.h"
+#include "esp_task_wdt.h"
+#include "esp_vfs_dev.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "sdkconfig.h"
+
+volatile bool handelingInterrupt = false;
+
+#include "src.wasm.h"
+
+extern "C" {
+extern void app_main(void);
+}
+
+WARDuino wac;
+Module* m;
+
+void startDebuggerStd(void* pvParameter) {
+ int valread;
+ uint8_t buffer[1024] = {0};
+ wac.debugger->socket = fileno(stdout);
+ while (true) {
+ taskYIELD();
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
+
+ while ((valread = read(fileno(stdin), buffer, 1024)) != -1) {
+ write(fileno(stdout), "got a message ... \n", 19);
+ wac.handleInterrupt(valread - 1, buffer);
+ write(fileno(stdout), buffer, valread);
+ fflush(stdout);
+ }
+ }
+}
+
+void app_main(void) {
+ m = wac.load_module(src_wasm, src_wasm_len, {});
+ xTaskCreate(startDebuggerStd, "Debug Thread", 5000, NULL, 1, NULL);
+ printf("START\n\n");
+ wac.run_module(m);
+ printf("END\n\n");
+ wac.unload_module(m);
+}
diff --git a/lib/json b/lib/json
new file mode 160000
index 00000000..b205361d
--- /dev/null
+++ b/lib/json
@@ -0,0 +1 @@
+Subproject commit b205361d8652759b6d850a37b227c8d57ee19005
diff --git a/library.properties b/library.properties
index 2eab09ef..3c19512d 100644
--- a/library.properties
+++ b/library.properties
@@ -1,6 +1,6 @@
name=WARDuino
-version=0.9.2
-author=Robbert Gurdeep Singh , Christophe Scholliers , Tom Lauwaerts , Joel Martin
+version=0.2.1
+author=Robbert Gurdeep Singh , Christophe Scholliers , Tom Lauwaerts , Carlos Rojas Castillo , Joel Martin
maintainer=Robbert Gurdeep Singh , Christophe Scholliers , Tom Lauwaerts
sentence=A library that enables the use of WebAssembly on Arduino boards with debugging support
paragraph=
diff --git a/platforms/Arduino/Arduino.ino b/platforms/Arduino/Arduino.ino
index 919bee00..20f3514c 100644
--- a/platforms/Arduino/Arduino.ino
+++ b/platforms/Arduino/Arduino.ino
@@ -15,19 +15,18 @@
unsigned int wasm_len = upload_wasm_len;
unsigned char* wasm = upload_wasm;
-WARDuino wac;
+WARDuino* wac = WARDuino::instance();
Module* m;
#define UART_PIN 3
void startDebuggerStd(void* pvParameter) {
- int valread;
+ Channel* sink = new Sink(stdout);
+ wac->debugger->setChannel(sink);
+ sink->open();
+
uint8_t buffer[1024] = {0};
- wac.debugger->socket = fileno(stdout);
- write(fileno(stdout), "Got a message ... \n", 19);
while (true) {
- // taskYIELD();
- // vTaskDelay(100 / portTICK_PERIOD_MS);
yield();
while (Serial.available()) {
@@ -36,11 +35,8 @@ void startDebuggerStd(void* pvParameter) {
buffer[buff_len++] = (int8_t)Serial.read();
}
if (buff_len) {
- write(fileno(stdout), "Reading message ..... \n", 19);
- fflush(stdout);
- wac.handleInterrupt(valread - 1, buffer);
- write(fileno(stdout), buffer, valread);
- fflush(stdout);
+ buffer[buff_len] = '\0';
+ wac->handleInterrupt(buff_len, buffer);
}
}
}
@@ -63,18 +59,18 @@ void setup(void) {
void loop() {
disableCore0WDT();
- m = wac.load_module(wasm, wasm_len, {});
+ m = wac->load_module(wasm, wasm_len, {});
printf("LOADED \n\n");
uint8_t command[] = {'0', '3', '\n'};
- wac.handleInterrupt(3, command);
+ wac->handleInterrupt(3, command);
xTaskCreate(startDebuggerStd, "Debug Thread", 5000, NULL, 1, NULL);
printf("START\n\n");
Serial.println("\nFree heap:");
Serial.println(ESP.getFreeHeap());
- wac.run_module(m);
+ wac->run_module(m);
printf("END\n\n");
- wac.unload_module(m);
+ wac->unload_module(m);
}
diff --git a/platforms/Arduino/Makefile b/platforms/Arduino/Makefile
index 4b1f2ff8..3e189220 100644
--- a/platforms/Arduino/Makefile
+++ b/platforms/Arduino/Makefile
@@ -1,8 +1,14 @@
+# Arduino Platform
+
+PORT = /dev/ttyUSB0
+FQBN = esp32:esp32:esp32wrover
+
flash:
- arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32wrover Arduino.ino
+ arduino-cli upload -p $(PORT) --fqbn $(FQBN) Arduino.ino
compile:
- arduino-cli -v compile --fqbn esp32:esp32:esp32wrover Arduino.ino
+ arduino-cli compile --fqbn $(FQBN) Arduino.ino
monitor:
- arduino-cli monitor -p /dev/ttyUSB0 -c baudrate=115200
+ arduino-cli monitor -p $(PORT) -c baudrate=115200
+
diff --git a/platforms/Arduino/examples/blink.c b/platforms/Arduino/examples/blink.c
new file mode 100644
index 00000000..c64c74a4
--- /dev/null
+++ b/platforms/Arduino/examples/blink.c
@@ -0,0 +1,20 @@
+unsigned char blink_wasm[] = {
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x03, 0x60,
+ 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x02,
+ 0x4f, 0x04, 0x03, 0x65, 0x6e, 0x76, 0x0a, 0x63, 0x68, 0x69, 0x70, 0x5f,
+ 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x0d,
+ 0x63, 0x68, 0x69, 0x70, 0x5f, 0x70, 0x69, 0x6e, 0x5f, 0x6d, 0x6f, 0x64,
+ 0x65, 0x00, 0x00, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x63, 0x68, 0x69, 0x70,
+ 0x5f, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x72, 0x69,
+ 0x74, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6e, 0x76, 0x09, 0x70, 0x72, 0x69,
+ 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x00, 0x01, 0x03, 0x03, 0x02, 0x02,
+ 0x02, 0x06, 0x10, 0x03, 0x7f, 0x00, 0x41, 0x0a, 0x0b, 0x7f, 0x00, 0x41,
+ 0x01, 0x0b, 0x7f, 0x00, 0x41, 0x00, 0x0b, 0x07, 0x08, 0x01, 0x04, 0x6d,
+ 0x61, 0x69, 0x6e, 0x00, 0x05, 0x0a, 0x33, 0x02, 0x08, 0x00, 0x23, 0x00,
+ 0x41, 0x02, 0x10, 0x01, 0x0b, 0x28, 0x01, 0x01, 0x7f, 0x41, 0xe8, 0x07,
+ 0x21, 0x00, 0x10, 0x04, 0x03, 0x40, 0x23, 0x00, 0x23, 0x00, 0x10, 0x03,
+ 0x23, 0x01, 0x10, 0x02, 0x20, 0x00, 0x10, 0x00, 0x23, 0x00, 0x23, 0x02,
+ 0x10, 0x02, 0x20, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x0b, 0x0b};
+unsigned int blink_wasm_len = 190;
+/*
+ */
diff --git a/platforms/Arduino/examples/blink.wast b/platforms/Arduino/examples/blink.wast
new file mode 100644
index 00000000..0e0ed2df
--- /dev/null
+++ b/platforms/Arduino/examples/blink.wast
@@ -0,0 +1,54 @@
+(module
+ ;; Type declarations
+ (type $int32->int32->void (func (param i32 i32)))
+ (type $int32->void (func (param i32)))
+ (type $void->void (func))
+
+ ;; Imports from the WARDuino VM
+ (import "env" "chip_delay" (func $env.chip_delay (type $int32->void)))
+ (import "env" "chip_pin_mode" (func $env.chip_pin_mode (type $int32->int32->void)))
+ (import "env" "chip_digital_write" (func $env.chip_digital_write (type $int32->int32->void)))
+ (import "env" "print_int" (func $env.print_int (type $int32->void)))
+
+
+ ;; Non-mutable globals
+ (global $led i32 (i32.const 10))
+ (global $on i32 (i32.const 1))
+ (global $off i32 (i32.const 0))
+
+ ;; Initialise function (private)
+ (func $init (type $void->void)
+ ;; Set pin mode
+ global.get $led
+ i32.const 2
+ call $env.chip_pin_mode)
+
+ ;; Blink function (public)
+ (func $blink (type $void->void)
+ ;; Declare local $delay
+ (local $delay i32)
+ i32.const 1000
+ local.set $delay
+
+ ;; Initialise
+ call $init
+
+ ;; Blink in infinite loop
+ loop $infinite
+ global.get $led
+ global.get $led
+ call $env.print_int ;;print led nr
+ global.get $on
+ call $env.chip_digital_write ;; turn led on
+ local.get $delay
+ call $env.chip_delay ;; wait
+ global.get $led
+ global.get $off
+ call $env.chip_digital_write ;; turn led off
+ local.get $delay
+ call $env.chip_delay ;; wait
+ br $infinite ;; jump back to start of loop
+ end)
+
+ ;; Export blink as function
+ (export "main" (func $blink)))
diff --git a/platforms/Arduino/upload b/platforms/Arduino/upload
deleted file mode 100644
index abef5100..00000000
--- a/platforms/Arduino/upload
+++ /dev/null
@@ -1 +0,0 @@
-arduino-cli upload -p $1 --fqbn esp32:esp32:esp32wrover Arduino.ino
diff --git a/platforms/CLI-Emulator/main.cpp b/platforms/CLI-Emulator/main.cpp
index 689fca8d..4414c6f3 100644
--- a/platforms/CLI-Emulator/main.cpp
+++ b/platforms/CLI-Emulator/main.cpp
@@ -1,17 +1,19 @@
//
// WARDuino - WebAssembly interpreter for embedded devices.
//
+#include
#include
#include
-#include
#include
#include
#include
#include
+#include
#include "../../src/Debug/debugger.h"
#include "../../src/Utils/macros.h"
+#include "../../src/Utils/sockets.h"
#include "../../src/WARDuino.h"
#include "../../tests/integration/wasm_tests.h"
@@ -32,13 +34,13 @@
}
void print_help() {
- fprintf(stdout, "WARDuino WebAssembly Runtime - 0.1.0\n\n");
+ fprintf(stdout, "WARDuino WebAssembly Runtime - 0.2.1\n\n");
fprintf(stdout, "Usage:\n");
fprintf(stdout, " warduino [options] \n");
fprintf(stdout, "Options:\n");
- fprintf(
- stdout,
- " --loop Let the runtime loop infinitely on exceptions\n");
+ fprintf(stdout,
+ " --loop Let the runtime loop infinitely on exceptions "
+ "(default: false)\n");
fprintf(stdout,
" --asserts Name of file containing asserts to run against "
"loaded module\n");
@@ -47,6 +49,24 @@ void print_help() {
"binaries (default: wat2wasm)\n");
fprintf(stdout,
" --file Wasm file (module) to load and execute\n");
+ fprintf(stdout,
+ " --no-debug Run without debug thread"
+ "(default: false)\n");
+ fprintf(stdout,
+ " --no-socket Run debug on stdout"
+ "(default: false)\n");
+ fprintf(stdout,
+ " --socket Port number for debug socket (ignored if "
+ "'--no-socket' is true)"
+ "(default: 8192)\n");
+ fprintf(stdout,
+ " --paused Pause program on entry (default: false)\n");
+ fprintf(stdout,
+ " --proxy Localhost port or serial port (ignored if mode "
+ "is 'proxy')\n");
+ fprintf(stdout,
+ " --mode The mode to run in: interpreter, proxy "
+ "(default: interpreter)\n");
}
Module *load(WARDuino wac, const char *file_name, Options opt) {
@@ -89,106 +109,64 @@ Module *load(WARDuino wac, const char *file_name, Options opt) {
return nullptr;
}
-// Socket Debugger Interface
-void setFileDescriptorOptions(int socket_fd) {
- int opt = 1;
- if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
- perror("Failed to set socket file descriptor options");
- exit(EXIT_FAILURE);
+void *startDebuggerCommunication(void *arg) {
+ Channel *duplex = WARDuino::instance()->debugger->channel;
+ if (duplex == nullptr) {
+ return nullptr;
}
-}
-int createSocketFileDescriptor() {
- int socket_fd;
- if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
- perror("Failed to make a new socket file descriptor");
- exit(EXIT_FAILURE);
- }
- setFileDescriptorOptions(socket_fd);
- return socket_fd;
-}
+ duplex->open();
-void bindSocketToAddress(int socket_fd, struct sockaddr_in address) {
- if (bind(socket_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
- perror("Binding socket to address failed");
- exit(EXIT_FAILURE);
+ ssize_t valread;
+ uint8_t buffer[1024] = {0};
+ while (true) {
+ while ((valread = duplex->read(buffer, 1024)) != -1) {
+ WARDuino::instance()->handleInterrupt(valread - 1, buffer);
+ }
}
}
-struct sockaddr_in createAddress(int port) {
- struct sockaddr_in address;
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = INADDR_ANY;
- address.sin_port = htons(port);
- return address;
-}
+// Connect to proxy via a web socket
+int connectToProxySocket(int proxy) {
+ int channel;
+ struct sockaddr_in address = createLocalhostAddress(proxy);
-void startListening(int socket_fd) {
- if (listen(socket_fd, 1) < 0) {
- perror("listen");
- exit(EXIT_FAILURE);
+ if ((channel = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ dbg_info("Socket creation error\n");
+ return -1;
}
-}
-int listenForIncomingConnection(int socket_fd, struct sockaddr_in address) {
- int new_socket;
- int size = sizeof(address);
- if ((new_socket = accept(socket_fd, (struct sockaddr *)&address,
- (socklen_t *)&size)) < 0) {
- perror("Failed to listen for incoming connections");
- exit(EXIT_FAILURE);
+ if (connect(channel, (struct sockaddr *)&address, sizeof(address)) < 0) {
+ dbg_info("Connection failed\n");
+ return -1;
}
- return new_socket;
-}
-void startDebuggerStd(WARDuino *wac, Module *m) {
- int valread;
- uint8_t buffer[1024] = {0};
- wac->debugger->socket = fileno(stdout);
- while (true) {
- debug("waiting for debug command\n");
- while ((valread = read(fileno(stdin), buffer, 1024)) != -1) {
- write(fileno(stdout), "got a message ... \n", 19);
- wac->handleInterrupt(valread - 1, buffer);
- write(fileno(stdout), buffer, valread);
- fflush(stdout);
- }
- }
+ return channel;
}
-void startDebuggerSocket(WARDuino *wac, Module *m) {
- int socket_fd = createSocketFileDescriptor();
- struct sockaddr_in address = createAddress(8192);
- bindSocketToAddress(socket_fd, address);
- startListening(socket_fd);
-
- int valread;
- uint8_t buffer[1024] = {0};
- while (true) {
- int socket = listenForIncomingConnection(socket_fd, address);
- wac->debugger->socket = socket;
- // wac->debugger->socket = fileno(stdout); // todo remove
- while ((valread = read(socket, buffer, 1024)) != -1) {
- write(socket, "got a message ... \n", 19);
- wac->handleInterrupt(valread - 1, buffer);
- // runningstate program_state = warduinorun;
- write(socket, buffer, valread);
- // while (checkdebugmessages(m, &program_state)) {
- // printf("checkdebugmessages \n");
- //};
- // fflush(stdout);
- }
- }
-}
+// Connect to proxy via file descriptor
+int connectToProxyFd(const char *proxyfd) { return open(proxyfd, O_RDWR); }
-WARDuino wac;
+WARDuino *wac = WARDuino::instance();
Module *m;
-void *runWAC(void *p) {
- // Print value received as argument:
- dbg_info("\n=== STARTED INTERPRETATION (in separate thread) ===\n");
- wac.run_module(m);
- wac.unload_module(m);
+struct debugger_options {
+ const char *socket;
+ bool no_socket;
+};
+
+void *setupDebuggerCommunication(debugger_options *options) {
+ dbg_info("\n=== STARTED DEBUGGER (in separate thread) ===\n");
+ // Start debugger
+ Channel *duplex;
+ if (options->no_socket) {
+ duplex = new Duplex(stdin, stdout);
+ } else {
+ int port = std::stoi(options->socket);
+ duplex = new WebSocket(port);
+ }
+
+ wac->debugger->setChannel(duplex);
}
int main(int argc, const char *argv[]) {
@@ -196,8 +174,13 @@ int main(int argc, const char *argv[]) {
bool return_exception = true;
bool run_tests = false;
+ bool no_debug = false;
bool no_socket = false;
+ const char *socket = "8192";
+ bool paused = false;
const char *file_name = nullptr;
+ const char *proxy = nullptr;
+ const char *mode = "interpreter";
const char *asserts_file = nullptr;
const char *watcompiler = "wat2wasm";
@@ -222,8 +205,18 @@ int main(int argc, const char *argv[]) {
ARGV_GET(asserts_file);
} else if (!strcmp("--watcompiler", arg)) {
ARGV_GET(watcompiler);
+ } else if (!strcmp("--no-debug", arg)) {
+ no_debug = true;
} else if (!strcmp("--no-socket", arg)) {
no_socket = true;
+ } else if (!strcmp("--socket", arg)) {
+ ARGV_GET(socket);
+ } else if (!strcmp("--paused", arg)) {
+ wac->program_state = WARDUINOpause;
+ } else if (!strcmp("--proxy", arg)) {
+ ARGV_GET(proxy); // /dev/ttyUSB0
+ } else if (!strcmp("--mode", arg)) {
+ ARGV_GET(mode);
}
}
@@ -235,10 +228,10 @@ int main(int argc, const char *argv[]) {
if (argc == 0 && file_name != nullptr) {
if (run_tests) {
dbg_info("=== STARTING SPEC TESTS ===\n");
- return run_wasm_test(wac, file_name, asserts_file, watcompiler);
+ return run_wasm_test(*wac, file_name, asserts_file, watcompiler);
}
dbg_info("=== LOAD MODULE INTO WARDUINO ===\n");
- m = load(wac, file_name,
+ m = load(*wac, file_name,
{.disable_memory_bounds = false,
.mangle_table_index = false,
.dlsym_trim_underscore = false,
@@ -249,19 +242,60 @@ int main(int argc, const char *argv[]) {
}
if (m) {
+ m->warduino = wac;
+
+ if (strcmp(mode, "proxy") == 0) {
+ // Run in proxy mode
+ wac->debugger->proxify();
+ } else if (proxy) {
+ // Connect to proxy device
+ Channel *connection = nullptr;
+ try {
+ int port = std::stoi(proxy);
+ connection = new WebSocket(port);
+ } catch (std::invalid_argument const &ex) {
+ // argument is not a port
+ // treat as filename
+ connection = new FileDescriptorChannel(open(proxy, O_RDWR));
+ } catch (std::out_of_range const &ex) {
+ // argument is an integer but is out of range
+ fprintf(stderr,
+ "wdcli: out of range integer argument for --proxy\n");
+ return 1;
+ }
+
+ if (connection == nullptr) {
+ // Failed to connect stop program
+ fprintf(stderr, "wdcli: failed to connect to proxy device\n");
+ return 1;
+ }
+
+ // Start supervising proxy device (new thread)
+ wac->debugger->startProxySupervisor(connection);
+ }
+
+ // Start debugger (new thread)
pthread_t id;
- uint8_t command[] = {'0', '3', '\n'};
- // wac.handleInterrupt(3, command);
- m->warduino = &wac;
- pthread_create(&id, nullptr, runWAC, nullptr);
- if (no_socket) {
- startDebuggerStd(&wac, m);
- } else {
- startDebuggerSocket(&wac, m);
+ if (!no_debug) {
+ auto *options =
+ (debugger_options *)malloc(sizeof(struct debugger_options));
+ options->no_socket = no_socket;
+ options->socket = socket;
+ setupDebuggerCommunication(options);
+ free(options);
+
+ pthread_create(&id, nullptr, startDebuggerCommunication, nullptr);
}
+
+ // Run Wasm module
+ dbg_info("\n=== STARTED INTERPRETATION (main thread) ===\n");
+ wac->run_module(m);
+ wac->unload_module(m);
+ wac->debugger->stop();
+
int *ptr;
pthread_join(id, (void **)&ptr);
}
return 0;
-}
+}
\ No newline at end of file
diff --git a/platforms/ESP-IDF/CMakeLists.txt b/platforms/ESP-IDF/CMakeLists.txt
index 694cad97..335bdc5c 100644
--- a/platforms/ESP-IDF/CMakeLists.txt
+++ b/platforms/ESP-IDF/CMakeLists.txt
@@ -1,16 +1,20 @@
set(SOURCE_FILES
- ../../src/Memory/mem.cpp
- ../../src/Utils/util.cpp
- ../../src/Utils/util_arduino.cpp
- ../../src/Debug/debugger.cpp
- ../../src/Utils/macros.cpp
- ../../src/WARDuino/WARDuino.cpp
- ../../src/Primitives/primitives.cpp
- ../../src/Interpreter/instructions.cpp
- ../../src/WARDuino/CallbackHandler.cpp
- )
+ ../../src/Debug/debugger.cpp
+ ../../src/Interpreter/instructions.cpp
+ ../../src/Memory/mem.cpp
+ ../../src/Primitives/idf.cpp
+ ../../src/Edward/proxy.cpp
+ ../../src/Edward/proxy_supervisor.cpp
+ ../../src/Edward/RFC.cpp
+ ../../src/Utils/macros.cpp
+ ../../src/Utils/sockets.cpp
+ ../../src/Utils/util.cpp
+ ../../src/Utils/util_arduino.cpp
+ ../../src/WARDuino/CallbackHandler.cpp
+ ../../src/WARDuino/WARDuino.cpp
+ )
-idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS "" REQUIRES driver)
+idf_component_register(SRCS "main.cpp" ${SOURCE_FILES} INCLUDE_DIRS ../../lib/json/single_include/ REQUIRES driver)
add_definitions(-DINFO=0)
add_definitions(-DDEBUG=0)
diff --git a/platforms/ESP-IDF/main.cpp b/platforms/ESP-IDF/main.cpp
index bbbed898..a4df9175 100644
--- a/platforms/ESP-IDF/main.cpp
+++ b/platforms/ESP-IDF/main.cpp
@@ -2,8 +2,6 @@
// WARDuino - WebAssembly interpreter for embedded devices.
//
//
-//#include
-
#include
#include "../../src/WARDuino.h"
@@ -11,76 +9,48 @@
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_task_wdt.h"
-#include "esp_vfs_dev.h"
+//#include "esp_vfs_dev.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
+#include "upload.h"
volatile bool handelingInterrupt = false;
-unsigned char wasm[] = {
- 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x03, 0x60,
- 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7e, 0x7f, 0x01, 0x7f,
- 0x03, 0x04, 0x03, 0x00, 0x02, 0x01, 0x04, 0x04, 0x01, 0x70, 0x00, 0x03,
- 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x23, 0x04, 0x7f, 0x01, 0x41, 0x00,
- 0x0b, 0x7f, 0x01, 0x41, 0x00, 0x0b, 0x7c, 0x01, 0x44, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x7c, 0x01, 0x44, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x07, 0x08, 0x01, 0x04, 0x6d, 0x61,
- 0x69, 0x6e, 0x00, 0x02, 0x09, 0x09, 0x01, 0x00, 0x41, 0x00, 0x0b, 0x03,
- 0x02, 0x01, 0x00, 0x0a, 0x54, 0x03, 0x02, 0x00, 0x0b, 0x39, 0x00, 0x20,
- 0x01, 0x41, 0x01, 0x4a, 0x04, 0x7f, 0x20, 0x00, 0x42, 0x01, 0x7c, 0x20,
- 0x01, 0x41, 0x01, 0x6b, 0x10, 0x01, 0x20, 0x01, 0x6c, 0x05, 0x41, 0x20,
- 0x24, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, 0x24,
- 0x02, 0x23, 0x00, 0x23, 0x00, 0x6a, 0x24, 0x01, 0x23, 0x02, 0x23, 0x02,
- 0xa0, 0x24, 0x03, 0x41, 0x01, 0x0b, 0x0b, 0x15, 0x01, 0x01, 0x7f, 0x41,
- 0x06, 0x21, 0x00, 0x03, 0x40, 0x42, 0x0d, 0x20, 0x00, 0x10, 0x01, 0x10,
- 0x00, 0x0c, 0x00, 0x0b, 0x0b, 0x00, 0x31, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x01, 0x13, 0x03, 0x00, 0x05, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x01, 0x03,
- 0x66, 0x61, 0x63, 0x02, 0x04, 0x66, 0x61, 0x63, 0x35, 0x02, 0x15, 0x03,
- 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x01,
- 0x00, 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x33, 0x32};
-unsigned int wasm_len = 236;
+unsigned int wasm_len = upload_wasm_len;
+unsigned char* wasm = upload_wasm;
extern "C" {
extern void app_main(void);
}
-WARDuino wac;
+WARDuino* wac = WARDuino::instance();
Module* m;
void startDebuggerStd(void* pvParameter) {
+ Channel* duplex = new Duplex(stdin, stdout);
+ wac->debugger->setChannel(duplex);
+ duplex->open();
+
int valread;
uint8_t buffer[1024] = {0};
- wac.debugger->socket = fileno(stdout);
while (true) {
taskYIELD();
vTaskDelay(1000 / portTICK_PERIOD_MS);
- while ((valread = read(fileno(stdin), buffer, 1024)) != -1) {
- write(fileno(stdout), "got a message ... \n", 19);
- wac.handleInterrupt(valread - 1, buffer);
- write(fileno(stdout), buffer, valread);
- fflush(stdout);
+ while ((valread = duplex->read(buffer, 1024)) != -1) {
+ wac->handleInterrupt(valread - 1, buffer);
}
}
}
void app_main(void) {
- m = wac.load_module(wasm, wasm_len, {});
- uint8_t command[] = {'0', '3', '\n'};
- wac.handleInterrupt(3, command);
+ m = wac->load_module(wasm, wasm_len, {});
+ // uint8_t command[] = {'0', '3', '\n'};
+ // wac->handleInterrupt(3, command);
xTaskCreate(startDebuggerStd, "Debug Thread", 5000, NULL, 1, NULL);
printf("START\n\n");
- wac.run_module(m);
+ wac->run_module(m);
printf("END\n\n");
- wac.unload_module(m);
+ wac->unload_module(m);
}
-
-/*void app_main(void) {
- m = wac.load_module(wasm, wasm_len, {});
- printf("START\n\n");
- //wac.run_module(m);
- //printf("END\n\n");
- //wac.unload_module(m);
- while(true);
-}*/
diff --git a/platforms/ESP-IDF/upload.h b/platforms/ESP-IDF/upload.h
new file mode 100644
index 00000000..753e37df
--- /dev/null
+++ b/platforms/ESP-IDF/upload.h
@@ -0,0 +1,17 @@
+unsigned char upload_wasm[] = {
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x03, 0x60,
+ 0x02, 0x7f, 0x7f, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, 0x02,
+ 0x3f, 0x03, 0x03, 0x65, 0x6e, 0x76, 0x0a, 0x63, 0x68, 0x69, 0x70, 0x5f,
+ 0x64, 0x65, 0x6c, 0x61, 0x79, 0x00, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x0d,
+ 0x63, 0x68, 0x69, 0x70, 0x5f, 0x70, 0x69, 0x6e, 0x5f, 0x6d, 0x6f, 0x64,
+ 0x65, 0x00, 0x00, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x63, 0x68, 0x69, 0x70,
+ 0x5f, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x72, 0x69,
+ 0x74, 0x65, 0x00, 0x00, 0x03, 0x03, 0x02, 0x02, 0x02, 0x06, 0x10, 0x03,
+ 0x7f, 0x00, 0x41, 0x17, 0x0b, 0x7f, 0x00, 0x41, 0x01, 0x0b, 0x7f, 0x00,
+ 0x41, 0x00, 0x0b, 0x07, 0x08, 0x01, 0x04, 0x6d, 0x61, 0x69, 0x6e, 0x00,
+ 0x04, 0x0a, 0x2f, 0x02, 0x08, 0x00, 0x23, 0x00, 0x41, 0x02, 0x10, 0x01,
+ 0x0b, 0x24, 0x01, 0x01, 0x7f, 0x41, 0xe8, 0x07, 0x21, 0x00, 0x10, 0x03,
+ 0x03, 0x40, 0x23, 0x00, 0x23, 0x01, 0x10, 0x02, 0x20, 0x00, 0x10, 0x00,
+ 0x23, 0x00, 0x23, 0x02, 0x10, 0x02, 0x20, 0x00, 0x10, 0x00, 0x0c, 0x00,
+ 0x0b, 0x0b};
+unsigned int upload_wasm_len = 170;
diff --git a/platforms/README.md b/platforms/README.md
new file mode 100644
index 00000000..20d0e805
--- /dev/null
+++ b/platforms/README.md
@@ -0,0 +1,9 @@
+# Platforms
+
+This folder contains the code necessary to compile WARDuino for the different supported platforms.
+
+- Arduino: WARDuino with primitives implemented for the Arduino platform
+- Arduino-socket: WARDuino with primitives implemented for the Arduino platform and a socket server to debug over Wi-Fi
+- CLI-EMULATOR: a cli for WARDuino with emulated primitives, to run on desktop environments
+- ESP-IDF: WARDuino compiled with the ESP-IDF toolchain
+
diff --git a/scripts/signal b/scripts/signal
deleted file mode 100755
index 4138bed4..00000000
--- a/scripts/signal
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/bin/sh
-
-if test -n "$WARDUINO_DEV"; then
- echo "USING: $WARDUINO_DEV"
- target="$WARDUINO_DEV"
- write() {
- (
- tr -d '\n\t '
- echo""
- ) | tr '[:lower:]' '[:upper:]' | tee $WARDUINO_DEV
- echo "Written to $WARDUINO_DEV"
- }
-else
- write() {
- # xxd -r -p > /tmp/change
- (
- tr -d '\n\t '
- echo""
- ) | tr '[:lower:]' '[:upper:]' | tee /tmp/change
- kill -USR1 "$(pgrep -i warduino)"
- }
-fi
-
-#echo "AAcAQeQAEAIL" | base64 -d > /tmp/change
-case "$1" in
-"REPLACE")
- cat </dev/null | sort | uniq | sed 's/^/ export WARDUINO_DEV=/')
-
- Communication via /tmp/change and kill -USR1
- export WARDUINO_DEV=""
-HELP
-
- ;;
-esac
diff --git a/sdkconfig b/sdkconfig
index 88079570..2d5dd7d3 100644
--- a/sdkconfig
+++ b/sdkconfig
@@ -10,6 +10,7 @@ CONFIG_SOC_DAC_SUPPORTED=y
CONFIG_SOC_MCPWM_SUPPORTED=y
CONFIG_SOC_SDMMC_HOST_SUPPORTED=y
CONFIG_SOC_BT_SUPPORTED=y
+CONFIG_SOC_BLUEDROID_SUPPORTED=y
CONFIG_SOC_CLASSIC_BT_SUPPORTED=y
CONFIG_SOC_PCNT_SUPPORTED=y
CONFIG_SOC_WIFI_SUPPORTED=y
@@ -19,23 +20,32 @@ CONFIG_SOC_EMAC_SUPPORTED=y
CONFIG_SOC_CPU_CORES_NUM=2
CONFIG_SOC_ULP_SUPPORTED=y
CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y
-CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y
CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y
CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y
CONFIG_SOC_I2S_SUPPORTED=y
CONFIG_SOC_RMT_SUPPORTED=y
CONFIG_SOC_SIGMADELTA_SUPPORTED=y
+CONFIG_SOC_SUPPORT_COEXISTENCE=y
+CONFIG_SOC_AES_SUPPORTED=y
+CONFIG_SOC_MPI_SUPPORTED=y
+CONFIG_SOC_SHA_SUPPORTED=y
+CONFIG_SOC_FLASH_ENC_SUPPORTED=y
+CONFIG_SOC_SECURE_BOOT_SUPPORTED=y
CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y
CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y
CONFIG_SOC_ADC_PERIPH_NUM=2
CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10
+CONFIG_SOC_ADC_ATTEN_NUM=4
CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2
CONFIG_SOC_ADC_PATT_LEN_MAX=16
CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=9
CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12
CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=2
CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=2000
-CONFIG_SOC_ADC_MAX_BITWIDTH=12
+CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9
+CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12
+CONFIG_SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256=y
+CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y
CONFIG_SOC_CPU_BREAKPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINT_SIZE=64
@@ -56,17 +66,22 @@ CONFIG_SOC_APLL_MULTIPLIER_OUT_MAX_HZ=500000000
CONFIG_SOC_APLL_MIN_HZ=5303031
CONFIG_SOC_APLL_MAX_HZ=125000000
CONFIG_SOC_I2S_NUM=2
+CONFIG_SOC_I2S_HW_VERSION_1=y
CONFIG_SOC_I2S_SUPPORTS_APLL=y
+CONFIG_SOC_I2S_SUPPORTS_PDM=y
CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y
CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y
+CONFIG_SOC_I2S_SUPPORTS_ADC_DAC=y
CONFIG_SOC_I2S_SUPPORTS_ADC=y
CONFIG_SOC_I2S_SUPPORTS_DAC=y
+CONFIG_SOC_I2S_SUPPORTS_LCD_CAMERA=y
CONFIG_SOC_I2S_TRANS_SIZE_ALIGN_WORD=y
CONFIG_SOC_I2S_LCD_I80_VARIANT=y
CONFIG_SOC_LCD_I80_SUPPORTED=y
-CONFIG_SOC_LCD_I80_BUSES=y
+CONFIG_SOC_LCD_I80_BUSES=2
CONFIG_SOC_LCD_I80_BUS_WIDTH=24
CONFIG_SOC_LEDC_HAS_TIMER_SPECIFIC_MUX=y
+CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y
CONFIG_SOC_LEDC_SUPPORT_REF_TICK=y
CONFIG_SOC_LEDC_SUPPORT_HS_MODE=y
CONFIG_SOC_LEDC_CHANNEL_NUM=8
@@ -94,6 +109,7 @@ CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=8
CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8
CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=64
CONFIG_SOC_RMT_SUPPORT_REF_TICK=y
+CONFIG_SOC_RMT_SUPPORT_APB=y
CONFIG_SOC_RMT_CHANNEL_CLK_INDEPENDENT=y
CONFIG_SOC_RTCIO_PIN_COUNT=18
CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y
@@ -107,10 +123,15 @@ CONFIG_SOC_SPI_PERIPH_NUM=3
CONFIG_SOC_SPI_DMA_CHAN_NUM=2
CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64
CONFIG_SOC_SPI_MAX_PRE_DIVIDER=8192
+CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y
+CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y
+CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED=y
+CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y
CONFIG_SOC_TIMER_GROUPS=2
CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2
CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64
CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4
+CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y
CONFIG_SOC_TOUCH_VERSION_1=y
CONFIG_SOC_TOUCH_SENSOR_NUM=10
CONFIG_SOC_TOUCH_PAD_MEASURE_WAIT_MAX=0xFF
@@ -130,10 +151,13 @@ CONFIG_SOC_RSA_MAX_BIT_LEN=4096
CONFIG_SOC_AES_SUPPORT_AES_128=y
CONFIG_SOC_AES_SUPPORT_AES_192=y
CONFIG_SOC_AES_SUPPORT_AES_256=y
+CONFIG_SOC_SECURE_BOOT_V1=y
+CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y
CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32
CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21
CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y
CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y
+CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y
CONFIG_SOC_SDMMC_USE_IOMUX=y
CONFIG_SOC_SDMMC_NUM_SLOTS=2
CONFIG_SOC_BLE_DONT_UPDATE_OWN_RPA=y
@@ -154,6 +178,8 @@ CONFIG_APP_BUILD_BOOTLOADER=y
CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y
# CONFIG_APP_REPRODUCIBLE_BUILD is not set
# CONFIG_APP_NO_BLOBS is not set
+# CONFIG_APP_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
+# CONFIG_APP_COMPATIBLE_PRE_V3_1_BOOTLOADERS is not set
# end of Build type
#
@@ -185,6 +211,7 @@ CONFIG_BOOTLOADER_LOG_LEVEL=3
CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y
# CONFIG_BOOTLOADER_FACTORY_RESET is not set
# CONFIG_BOOTLOADER_APP_TEST is not set
+CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y
CONFIG_BOOTLOADER_WDT_ENABLE=y
# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set
CONFIG_BOOTLOADER_WDT_TIME_MS=9000
@@ -200,6 +227,7 @@ CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y
#
# Security features
#
+CONFIG_SECURE_BOOT_V1_SUPPORTED=y
# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set
# CONFIG_SECURE_BOOT is not set
# CONFIG_SECURE_FLASH_ENC_ENABLED is not set
@@ -267,10 +295,12 @@ CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set
+CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2
# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set
CONFIG_COMPILER_HIDE_PATHS_MACROS=y
-# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
+CONFIG_COMPILER_CXX_EXCEPTIONS=y
+CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
# CONFIG_COMPILER_CXX_RTTI is not set
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
@@ -290,6 +320,10 @@ CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
#
# CONFIG_APPTRACE_DEST_JTAG is not set
CONFIG_APPTRACE_DEST_NONE=y
+# CONFIG_APPTRACE_DEST_UART1 is not set
+# CONFIG_APPTRACE_DEST_UART2 is not set
+CONFIG_APPTRACE_DEST_UART_NONE=y
+CONFIG_APPTRACE_UART_TASK_PRIO=1
CONFIG_APPTRACE_LOCK_ENABLE=y
# end of Application Level Tracing
@@ -351,6 +385,7 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# GPIO Configuration
#
# CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL is not set
+# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set
# end of GPIO Configuration
#
@@ -370,6 +405,14 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set
# end of PCNT Configuration
+
+#
+# RMT Configuration
+#
+# CONFIG_RMT_ISR_IRAM_SAFE is not set
+# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set
+# CONFIG_RMT_ENABLE_DEBUG_LOG is not set
+# end of RMT Configuration
# end of Driver configurations
#
@@ -388,50 +431,12 @@ CONFIG_EFUSE_MAX_BLK_LEN=192
#
CONFIG_ESP_TLS_USING_MBEDTLS=y
# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set
-# CONFIG_ESP_TLS_SERVER is not set
# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set
+# CONFIG_ESP_TLS_SERVER is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_TLS_INSECURE is not set
# end of ESP-TLS
-#
-# ESP32-specific
-#
-CONFIG_ESP32_REV_MIN_0=y
-# CONFIG_ESP32_REV_MIN_1 is not set
-# CONFIG_ESP32_REV_MIN_2 is not set
-# CONFIG_ESP32_REV_MIN_3 is not set
-CONFIG_ESP32_REV_MIN=0
-CONFIG_ESP32_DPORT_WORKAROUND=y
-# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set
-CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y
-# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set
-CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160
-# CONFIG_ESP32_SPIRAM_SUPPORT is not set
-# CONFIG_ESP32_TRAX is not set
-CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0
-CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT=y
-# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set
-# CONFIG_ESP32_TIME_SYSCALL_USE_HRT is not set
-# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set
-CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y
-# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set
-# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set
-# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set
-CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
-CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
-CONFIG_ESP32_XTAL_FREQ_40=y
-# CONFIG_ESP32_XTAL_FREQ_26 is not set
-# CONFIG_ESP32_XTAL_FREQ_AUTO is not set
-CONFIG_ESP32_XTAL_FREQ=40
-# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set
-# CONFIG_ESP32_NO_BLOBS is not set
-# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
-# CONFIG_ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS is not set
-# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set
-CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5
-# end of ESP32-specific
-
#
# ADC-Calibration
#
@@ -463,6 +468,7 @@ CONFIG_ETH_USE_SPI_ETHERNET=y
# CONFIG_ETH_SPI_ETHERNET_W5500 is not set
# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set
# CONFIG_ETH_USE_OPENETH is not set
+# CONFIG_ETH_TRANSMIT_MUTEX is not set
# end of Ethernet
#
@@ -495,6 +501,7 @@ CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
CONFIG_HTTPD_PURGE_BUF_LEN=32
# CONFIG_HTTPD_LOG_PURGE_DATA is not set
# CONFIG_HTTPD_WS_SUPPORT is not set
+# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set
# end of HTTP Server
#
@@ -513,6 +520,7 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32
#
# Hardware Settings
#
+# CONFIG_SPIRAM is not set
#
# MAC Config
@@ -533,12 +541,36 @@ CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y
CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y
# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set
# CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND is not set
+CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000
# end of Sleep Config
#
# RTC Clock Config
#
+CONFIG_RTC_CLK_SRC_INT_RC=y
+# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set
+# CONFIG_RTC_CLK_SRC_EXT_OSC is not set
+# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set
+CONFIG_RTC_CLK_CAL_CYCLES=1024
# end of RTC Clock Config
+
+#
+# Peripheral Control
+#
+# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set
+# end of Peripheral Control
+
+CONFIG_ESP32_REV_MIN_0=y
+# CONFIG_ESP32_REV_MIN_1 is not set
+# CONFIG_ESP32_REV_MIN_2 is not set
+# CONFIG_ESP32_REV_MIN_3 is not set
+CONFIG_ESP32_REV_MIN=0
+CONFIG_ESP32_DPORT_WORKAROUND=y
+CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5
+CONFIG_ESP32_XTAL_FREQ_40=y
+# CONFIG_ESP32_XTAL_FREQ_26 is not set
+# CONFIG_ESP32_XTAL_FREQ_AUTO is not set
+CONFIG_ESP32_XTAL_FREQ=40
# end of Hardware Settings
#
@@ -549,6 +581,7 @@ CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y
# LCD Peripheral Configuration
#
CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32
+# CONFIG_LCD_ENABLE_DEBUG_LOG is not set
# end of LCD Peripheral Configuration
# end of LCD and Touch Panel
@@ -558,7 +591,6 @@ CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32
CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120
CONFIG_ESP_NETIF_TCPIP_LWIP=y
# CONFIG_ESP_NETIF_LOOPBACK is not set
-CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y
# CONFIG_ESP_NETIF_L2_TAP is not set
# end of ESP NETIF Adapter
@@ -581,6 +613,24 @@ CONFIG_ESP_PHY_REDUCE_TX_POWER=y
#
# ESP System Settings
#
+# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y
+# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240 is not set
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160
+
+#
+# Memory
+#
+# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set
+# end of Memory
+
+#
+# Trace memory
+#
+# CONFIG_ESP32_TRAX is not set
+CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0
+# end of Trace memory
+
# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set
CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y
# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
@@ -608,7 +658,11 @@ CONFIG_ESP_CONSOLE_MULTIPLE_UART=y
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
# CONFIG_ESP_INT_WDT is not set
-# CONFIG_ESP_TASK_WDT is not set
+CONFIG_ESP_TASK_WDT=y
+# CONFIG_ESP_TASK_WDT_PANIC is not set
+CONFIG_ESP_TASK_WDT_TIMEOUT_S=5
+CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
+CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
# CONFIG_ESP_PANIC_HANDLER_IRAM is not set
# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set
CONFIG_ESP_DEBUG_OCDAWARE=y
@@ -629,6 +683,8 @@ CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0=y
# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7 is not set
CONFIG_ESP_BROWNOUT_DET_LVL=0
# end of Brownout Detector
+
+# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set
# end of ESP System Settings
#
@@ -740,75 +796,56 @@ CONFIG_FATFS_PER_FILE_CACHE=y
# end of FAT Filesystem support
#
-# Modbus configuration
-#
-CONFIG_FMB_COMM_MODE_TCP_EN=y
-CONFIG_FMB_TCP_PORT_DEFAULT=502
-CONFIG_FMB_TCP_PORT_MAX_CONN=5
-CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20
-CONFIG_FMB_COMM_MODE_RTU_EN=y
-CONFIG_FMB_COMM_MODE_ASCII_EN=y
-CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
-CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
-CONFIG_FMB_QUEUE_LENGTH=20
-CONFIG_FMB_PORT_TASK_STACK_SIZE=4096
-CONFIG_FMB_SERIAL_BUF_SIZE=256
-CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8
-CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000
-CONFIG_FMB_PORT_TASK_PRIO=10
-# CONFIG_FMB_PORT_TASK_AFFINITY_NO_AFFINITY is not set
-CONFIG_FMB_PORT_TASK_AFFINITY_CPU0=y
-# CONFIG_FMB_PORT_TASK_AFFINITY_CPU1 is not set
-CONFIG_FMB_PORT_TASK_AFFINITY=0x0
-CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y
-CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233
-CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20
-CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
-CONFIG_FMB_CONTROLLER_STACK_SIZE=4096
-CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20
-# CONFIG_FMB_TIMER_PORT_ENABLED is not set
-# CONFIG_FMB_TIMER_USE_ISR_DISPATCH_METHOD is not set
-# end of Modbus configuration
+# FreeRTOS
+#
#
-# FreeRTOS
+# Kernel
#
+# CONFIG_FREERTOS_SMP is not set
# CONFIG_FREERTOS_UNICORE is not set
-CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
-CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER=y
-CONFIG_FREERTOS_CORETIMER_0=y
-# CONFIG_FREERTOS_CORETIMER_1 is not set
-CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y
CONFIG_FREERTOS_HZ=100
-CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
-# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
-CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
-CONFIG_FREERTOS_ISR_STACKSIZE=1536
# CONFIG_FREERTOS_USE_IDLE_HOOK is not set
# CONFIG_FREERTOS_USE_TICK_HOOK is not set
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set
-CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
-# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set
CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048
CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
+# end of Kernel
+
+#
+# Port
+#
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
+# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
+# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set
CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
-# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
-# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set
-CONFIG_FREERTOS_DEBUG_OCDAWARE=y
+CONFIG_FREERTOS_ISR_STACKSIZE=1536
+CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
# CONFIG_FREERTOS_FPU_IN_ISR is not set
-CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
+CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER=y
+CONFIG_FREERTOS_CORETIMER_0=y
+# CONFIG_FREERTOS_CORETIMER_1 is not set
+CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y
+# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set
# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set
+# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
+CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
+CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y
+# end of Port
+
+CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
+CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
+CONFIG_FREERTOS_DEBUG_OCDAWARE=y
# end of FreeRTOS
#
@@ -1025,6 +1062,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set
# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set
+CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200
# end of Certificate Bundle
# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set
@@ -1036,6 +1074,7 @@ CONFIG_MBEDTLS_ROM_MD5=y
# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set
# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set
CONFIG_MBEDTLS_HAVE_TIME=y
+# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y
CONFIG_MBEDTLS_SHA512_C=y
@@ -1123,6 +1162,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
#
# mDNS
#
+CONFIG_MDNS_MAX_INTERFACES=3
CONFIG_MDNS_MAX_SERVICES=10
CONFIG_MDNS_TASK_PRIORITY=1
CONFIG_MDNS_TASK_STACK_SIZE=4096
@@ -1135,6 +1175,14 @@ CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000
CONFIG_MDNS_TIMER_PERIOD_MS=100
# CONFIG_MDNS_NETWORKING_SOCKET is not set
CONFIG_MDNS_MULTIPLE_INSTANCE=y
+
+#
+# MDNS Predefined interfaces
+#
+CONFIG_MDNS_PREDEF_NETIF_STA=y
+CONFIG_MDNS_PREDEF_NETIF_AP=y
+CONFIG_MDNS_PREDEF_NETIF_ETH=y
+# end of MDNS Predefined interfaces
# end of mDNS
#
@@ -1162,6 +1210,10 @@ CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set
CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
# CONFIG_NEWLIB_NANO_FORMAT is not set
+CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
+# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set
+# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set
+# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set
# end of Newlib
#
@@ -1301,7 +1353,6 @@ CONFIG_VFS_SUPPORT_TERMIOS=y
# Host File System I/O (Semihosting)
#
CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1
-CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
# end of Host File System I/O (Semihosting)
# end of Virtual file system
@@ -1324,6 +1375,7 @@ CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
# Supplicant
#
CONFIG_WPA_MBEDTLS_CRYPTO=y
+CONFIG_WPA_MBEDTLS_TLS_CLIENT=y
# CONFIG_WPA_WAPI_PSK is not set
# CONFIG_WPA_SUITE_B_192 is not set
# CONFIG_WPA_DEBUG_PRINT is not set
@@ -1332,11 +1384,16 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y
# CONFIG_WPA_11KV_SUPPORT is not set
# CONFIG_WPA_MBO_SUPPORT is not set
# CONFIG_WPA_DPP_SUPPORT is not set
+# CONFIG_WPA_11R_SUPPORT is not set
+# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set
# end of Supplicant
# end of Component config
# Deprecated options for backward compatibility
# CONFIG_NO_BLOBS is not set
+# CONFIG_ESP32_NO_BLOBS is not set
+# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
+# CONFIG_ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
@@ -1359,7 +1416,8 @@ CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2
-# CONFIG_CXX_EXCEPTIONS is not set
+CONFIG_CXX_EXCEPTIONS=y
+CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
CONFIG_STACK_CHECK_NONE=y
# CONFIG_STACK_CHECK_NORM is not set
# CONFIG_STACK_CHECK_STRONG is not set
@@ -1370,30 +1428,37 @@ CONFIG_STACK_CHECK_NONE=y
CONFIG_ESP32_APPTRACE_DEST_NONE=y
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
CONFIG_ADC2_DISABLE_DAC=y
-# CONFIG_SPIRAM_SUPPORT is not set
-CONFIG_TRACEMEM_RESERVE_DRAM=0x0
-CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
-# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set
-CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
-# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set
-# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set
-# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set
-# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set
-# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
# CONFIG_OTA_ALLOW_HTTP is not set
+# CONFIG_SPIRAM_SUPPORT is not set
+# CONFIG_ESP32_SPIRAM_SUPPORT is not set
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
CONFIG_ESP_SYSTEM_PD_FLASH=y
+CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
+CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y
+CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
+# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set
+# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set
+# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set
+# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set
+# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set
+# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set
+CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set
CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
CONFIG_ESP32_PHY_MAX_TX_POWER=20
CONFIG_REDUCE_PHY_TX_POWER=y
CONFIG_ESP32_REDUCE_PHY_TX_POWER=y
+# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set
+CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y
+# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set
+CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160
+CONFIG_TRACEMEM_RESERVE_DRAM=0x0
# CONFIG_ESP32_PANIC_PRINT_HALT is not set
CONFIG_ESP32_PANIC_PRINT_REBOOT=y
# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set
@@ -1409,7 +1474,11 @@ CONFIG_CONSOLE_UART=y
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=115200
# CONFIG_INT_WDT is not set
-# CONFIG_TASK_WDT is not set
+CONFIG_TASK_WDT=y
+# CONFIG_TASK_WDT_PANIC is not set
+CONFIG_TASK_WDT_TIMEOUT_S=5
+CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
+CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set
CONFIG_ESP32_DEBUG_OCDAWARE=y
CONFIG_BROWNOUT_DET=y
@@ -1432,28 +1501,16 @@ CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y
# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set
CONFIG_BROWNOUT_DET_LVL=0
CONFIG_ESP32_BROWNOUT_DET_LVL=0
+# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_TIMER_TASK_STACK_SIZE=3584
# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
-CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
-CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
-CONFIG_MB_QUEUE_LENGTH=20
-CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096
-CONFIG_MB_SERIAL_BUF_SIZE=256
-CONFIG_MB_SERIAL_TASK_PRIO=10
-CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y
-CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233
-CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20
-CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
-CONFIG_MB_CONTROLLER_STACK_SIZE=4096
-CONFIG_MB_EVENT_QUEUE_TIMEOUT=20
-# CONFIG_MB_TIMER_PORT_ENABLED is not set
-# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set
CONFIG_TIMER_TASK_PRIORITY=1
CONFIG_TIMER_TASK_STACK_DEPTH=2048
CONFIG_TIMER_QUEUE_LENGTH=10
+# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set
# CONFIG_L2_TO_L3_COPY is not set
CONFIG_ESP_GRATUITOUS_ARP=y
CONFIG_GARP_TMR_INTERVAL=60
@@ -1476,6 +1533,12 @@ CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_PPP_SUPPORT is not set
+CONFIG_ESP32_TIME_SYSCALL_USE_RTC_HRT=y
+CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
+# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set
+# CONFIG_ESP32_TIME_SYSCALL_USE_HRT is not set
+# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set
+# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
@@ -1491,5 +1554,4 @@ CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
-CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
# End of deprecated options
diff --git a/src/Debug/debugger.cpp b/src/Debug/debugger.cpp
index 00aaedc9..85e5d51d 100644
--- a/src/Debug/debugger.cpp
+++ b/src/Debug/debugger.cpp
@@ -1,23 +1,41 @@
#include "debugger.h"
-#include
-
+#include
+#include
#include
+#ifndef ARDUINO
+#include
+#else
+#include "../../lib/json/single_include/nlohmann/json.hpp"
+#endif
+#include "../Edward/proxy.h"
+#include "../Edward/proxy_supervisor.h"
#include "../Memory/mem.h"
#include "../Utils//util.h"
#include "../Utils/macros.h"
-#include "../WARDuino.h"
// Debugger
-Debugger::Debugger(int socket) { this->socket = socket; }
+Debugger::Debugger(Channel *duplex) { this->channel = duplex; }
// Public methods
+void Debugger::setChannel(Channel *duplex) {
+ delete this->channel;
+ this->channel = duplex;
+}
+
void Debugger::addDebugMessage(size_t len, const uint8_t *buff) {
uint8_t *data = this->parseDebugBuffer(len, buff);
- if (data != nullptr) {
+ if (data != nullptr && *data == interruptRecvCallbackmapping) {
+ std::string text = (char *)buff;
+ auto *msg =
+ (uint8_t *)acalloc(sizeof(uint8_t), len, "interrupt buffer");
+ memcpy(msg, buff, len * sizeof(uint8_t));
+ *msg = *data;
+ this->debugMessages.push_back(msg);
+ } else if (data != nullptr) {
this->debugMessages.push_back(data);
}
}
@@ -35,6 +53,9 @@ uint8_t *Debugger::parseDebugBuffer(size_t len, const uint8_t *buff) {
case 'A' ... 'F':
r = buff[i] - 'A' + 10;
break;
+ case 'a' ... 'f':
+ r = buff[i] - 'a' + 10;
+ break;
default:
success = false;
}
@@ -89,8 +110,8 @@ bool Debugger::isBreakpoint(uint8_t *loc) {
return this->breakpoints.find(loc) != this->breakpoints.end();
}
-void Debugger::notifyBreakpoint(uint8_t *pc_ptr) {
- dprintf(this->socket, "AT %p!\n", (void *)pc_ptr);
+void Debugger::notifyBreakpoint(uint8_t *pc_ptr) const {
+ this->channel->write("AT %p!\n", (void *)pc_ptr);
}
/**
@@ -121,34 +142,35 @@ bool Debugger::checkDebugMessages(Module *m, RunningState *program_state) {
return false;
}
- dprintf(this->socket, "Interrupt: %x\n", *interruptData);
+ this->channel->write("Interrupt: %x\n", *interruptData);
+
+ long start = 0, size = 0;
switch (*interruptData) {
case interruptRUN:
this->handleInterruptRUN(m, program_state);
free(interruptData);
break;
case interruptHALT:
- dprintf(this->socket, "STOP!\n");
+ this->channel->write("STOP!\n");
+ this->channel->close();
free(interruptData);
exit(0);
case interruptPAUSE:
*program_state = WARDUINOpause;
- dprintf(this->socket, "PAUSE!\n");
+ this->channel->write("PAUSE!\n");
free(interruptData);
break;
case interruptSTEP:
- dprintf(this->socket, "STEP!\n");
+ this->channel->write("STEP!\n");
*program_state = WARDUINOstep;
this->skipBreakpoint = m->pc_ptr;
free(interruptData);
break;
case interruptBPAdd: // Breakpoint
case interruptBPRem: // Breakpoint remove
- {
this->handleInterruptBP(interruptData);
free(interruptData);
break;
- }
case interruptDUMP:
*program_state = WARDUINOpause;
this->dump(m);
@@ -165,20 +187,93 @@ bool Debugger::checkDebugMessages(Module *m, RunningState *program_state) {
free(interruptData);
break;
case interruptUPDATEFun:
- dprintf(this->socket, "CHANGE function!\n");
- this->handleChangedFunction(m, interruptData);
+ this->channel->write("CHANGE function!\n");
+ Debugger::handleChangedFunction(m, interruptData);
// do not free(interruptData);
// we need it to run that code
// TODO: free double replacements
break;
case interruptUPDATELocal:
- dprintf(this->socket, "CHANGE local!\n");
+ this->channel->write("CHANGE local!\n");
this->handleChangedLocal(m, interruptData);
free(interruptData);
break;
+ case interruptWOODDUMP:
+ *program_state = WARDUINOpause;
+ free(interruptData);
+ woodDump(m);
+ break;
+ case interruptOffset:
+ free(interruptData);
+ this->channel->write("{\"offset\":\"%p\"}\n", (void *)m->bytes);
+ break;
+ case interruptRecvState:
+ if (!this->receivingData) {
+ *program_state = WARDUINOpause;
+ debug("paused program execution\n");
+ CallbackHandler::manual_event_resolution = true;
+ dbg_info("Manual event resolution is on.");
+ this->receivingData = true;
+ this->freeState(m, interruptData);
+ free(interruptData);
+ this->channel->write("ack!\n");
+ } else {
+ printf("receiving state\n");
+ debug("receiving state\n");
+ receivingData = !this->saveState(m, interruptData);
+ free(interruptData);
+ debug("sending %s!\n", receivingData ? "ack" : "done");
+ this->channel->write("%s!\n", receivingData ? "ack" : "done");
+ if (!this->receivingData) {
+ debug("receiving state done\n");
+ }
+ }
+ break;
+ case interruptProxyCall: {
+ this->handleProxyCall(m, program_state, interruptData + 1);
+ free(interruptData);
+ } break;
+ case interruptMonitorProxies: {
+ printf("receiving functions list to proxy\n");
+ this->handleMonitorProxies(m, interruptData + 1);
+ free(interruptData);
+ } break;
+ case interruptProxify: {
+ dbg_info("Converting to proxy settings.\n");
+ this->proxify();
+ free(interruptData);
+ break;
+ }
+ case interruptDUMPAllEvents:
+ printf("InterruptDUMPEvents\n");
+ size = (long)CallbackHandler::event_count();
+ case interruptDUMPEvents:
+ // TODO get start and size from message
+ this->channel->write("{");
+ this->dumpEvents(start, size);
+ this->channel->write("}\n");
+ free(interruptData);
+ break;
+ case interruptPOPEvent:
+ CallbackHandler::resolve_event(true);
+ free(interruptData);
+ break;
+ case interruptPUSHEvent:
+ this->handlePushedEvent(reinterpret_cast(interruptData));
+ free(interruptData);
+ break;
+ case interruptRecvCallbackmapping:
+ Debugger::updateCallbackmapping(
+ m, reinterpret_cast(interruptData + 2));
+ free(interruptData);
+ break;
+ case interruptDUMPCallbackmapping:
+ this->dumpCallbackmapping();
+ free(interruptData);
+ break;
default:
// handle later
- dprintf(this->socket, "COULD not parse interrupt data!\n");
+ this->channel->write("COULD not parse interrupt data!\n");
free(interruptData);
break;
}
@@ -187,16 +282,57 @@ bool Debugger::checkDebugMessages(Module *m, RunningState *program_state) {
}
// Private methods
+void Debugger::printValue(StackValue *v, uint32_t idx, bool end = false) const {
+ char buff[256];
+
+ switch (v->value_type) {
+ case I32:
+ snprintf(buff, 255, R"("type":"i32","value":%)" PRIi32,
+ v->value.uint32);
+ break;
+ case I64:
+ snprintf(buff, 255, R"("type":"i64","value":%)" PRIi64,
+ v->value.uint64);
+ break;
+ case F32:
+ snprintf(buff, 255, R"("type":"F32","value":%.7f)", v->value.f32);
+ break;
+ case F64:
+ snprintf(buff, 255, R"("type":"F64","value":%.7f)", v->value.f64);
+ break;
+ default:
+ snprintf(buff, 255, R"("type":"%02x","value":"%)" PRIx64 "\"",
+ v->value_type, v->value.uint64);
+ }
+ this->channel->write(R"({"idx":%d,%s}%s)", idx, buff, end ? "" : ",");
+}
+
+uint8_t *Debugger::findOpcode(Module *m, Block *block) {
+ auto find =
+ std::find_if(std::begin(m->block_lookup), std::end(m->block_lookup),
+ [&](const std::pair &pair) {
+ return pair.second == block;
+ });
+ uint8_t *opcode = nullptr;
+ if (find != std::end(m->block_lookup)) {
+ opcode = find->first;
+ } else {
+ // FIXME FATAL?
+ debug("find_opcode: not found\n");
+ exit(33);
+ }
+ return opcode;
+}
void Debugger::handleInterruptRUN(Module *m, RunningState *program_state) {
- dprintf(this->socket, "GO!\n");
+ this->channel->write("GO!\n");
if (*program_state == WARDUINOpause && this->isBreakpoint(m->pc_ptr)) {
this->skipBreakpoint = m->pc_ptr;
}
*program_state = WARDUINOrun;
}
-void Debugger::handleInterruptBP(uint8_t *interruptData) {
+void Debugger::handleInterruptBP(const uint8_t *interruptData) {
// TODO: segfault may happen here!
uint8_t len = interruptData[1];
uintptr_t bp = 0x0;
@@ -205,7 +341,7 @@ void Debugger::handleInterruptBP(uint8_t *interruptData) {
bp |= interruptData[i + 2];
}
auto *bpt = (uint8_t *)bp;
- dprintf(this->socket, "BP %p!\n", static_cast(bpt));
+ this->channel->write("BP %p!\n", static_cast(bpt));
if (*interruptData == 0x06) {
this->addBreakpoint(bpt);
@@ -215,50 +351,52 @@ void Debugger::handleInterruptBP(uint8_t *interruptData) {
}
void Debugger::dump(Module *m, bool full) const {
- dprintf(this->socket, "{");
+ this->channel->write("{");
// current PC
- dprintf(this->socket, R"("pc":"%p",)", (void *)m->pc_ptr);
+ this->channel->write(R"("pc":"%p",)", (void *)m->pc_ptr);
// start of bytes
- dprintf(this->socket, R"("start":["%p"],)", (void *)m->bytes);
+ this->channel->write(R"("start":["%p"],)", (void *)m->bytes);
- this->dumpBreakpoints(m);
+ this->dumpBreakpoints();
this->dumpFunctions(m);
this->dumpCallstack(m);
if (full) {
- dprintf(this->socket, R"(, "locals": )");
+ this->channel->write(R"(, "locals": )");
this->dumpLocals(m);
+ this->channel->write(", ");
+ this->dumpEvents(0, CallbackHandler::event_count());
}
- dprintf(this->socket, "}\n\n");
- fflush(stdout);
+ this->channel->write("}\n\n");
+ // fflush(stdout);
}
-void Debugger::dumpBreakpoints(Module *m) const {
- dprintf(this->socket, "\"breakpoints\":[");
+void Debugger::dumpBreakpoints() const {
+ this->channel->write("\"breakpoints\":[");
{
size_t i = 0;
for (auto bp : this->breakpoints) {
- dprintf(this->socket, R"("%p"%s)", bp,
- (++i < this->breakpoints.size()) ? "," : "");
+ this->channel->write(R"("%p"%s)", bp,
+ (++i < this->breakpoints.size()) ? "," : "");
}
}
- dprintf(this->socket, "],");
+ this->channel->write("],");
}
void Debugger::dumpFunctions(Module *m) const {
- dprintf(this->socket, "\"functions\":[");
+ this->channel->write("\"functions\":[");
for (size_t i = m->import_count; i < m->function_count; i++) {
- dprintf(this->socket, R"({"fidx":"0x%x","from":"%p","to":"%p"}%s)",
- m->functions[i].fidx,
- static_cast(m->functions[i].start_ptr),
- static_cast(m->functions[i].end_ptr),
- (i < m->function_count - 1) ? "," : "],");
+ this->channel->write(R"({"fidx":"0x%x","from":"%p","to":"%p"}%s)",
+ m->functions[i].fidx,
+ static_cast(m->functions[i].start_ptr),
+ static_cast(m->functions[i].end_ptr),
+ (i < m->function_count - 1) ? "," : "],");
}
}
@@ -266,12 +404,11 @@ void Debugger::dumpFunctions(Module *m) const {
* {"type":%u,"fidx":"0x%x","sp":%d,"fp":%d,"ra":"%p"}%s
*/
void Debugger::dumpCallstack(Module *m) const {
- dprintf(this->socket, "\"callstack\":[");
+ this->channel->write("\"callstack\":[");
for (int i = 0; i <= m->csp; i++) {
Frame *f = &m->callstack[i];
uint8_t *callsite = f->ra_ptr - 2; // callsite of function (if type 0)
- dprintf(
- this->socket,
+ this->channel->write(
R"({"type":%u,"fidx":"0x%x","sp":%d,"fp":%d,"start":"%p","ra":"%p","callsite":"%p"}%s)",
f->block->block_type, f->block->fidx, f->sp, f->fp,
f->block->start_ptr, static_cast(f->ra_ptr),
@@ -280,7 +417,7 @@ void Debugger::dumpCallstack(Module *m) const {
}
void Debugger::dumpLocals(Module *m) const {
- fflush(stdout);
+ // fflush(stdout);
int firstFunFramePtr = m->csp;
while (m->callstack[firstFunFramePtr].block->block_type != 0) {
firstFunFramePtr--;
@@ -289,10 +426,10 @@ void Debugger::dumpLocals(Module *m) const {
}
}
Frame *f = &m->callstack[firstFunFramePtr];
- dprintf(this->socket, R"({"count":%u,"locals":[)", 0);
- fflush(stdout); // FIXME: this is needed for ESP to propery print
+ this->channel->write(R"({"count":%u,"locals":[)", 0);
+ // fflush(stdout); // FIXME: this is needed for ESP to properly print
char _value_str[256];
- for (size_t i = 0; i < f->block->local_count; i++) {
+ for (uint32_t i = 0; i < f->block->local_count; i++) {
auto v = &m->stack[m->fp + i];
switch (v->value_type) {
case I32:
@@ -304,11 +441,11 @@ void Debugger::dumpLocals(Module *m) const {
v->value.uint64);
break;
case F32:
- snprintf(_value_str, 255, R"("type":"i64","value":%.7f)",
+ snprintf(_value_str, 255, R"("type":"F32","value":%.7f)",
v->value.f32);
break;
case F64:
- snprintf(_value_str, 255, R"("type":"i64","value":%.7f)",
+ snprintf(_value_str, 255, R"("type":"F64","value":%.7f)",
v->value.f64);
break;
default:
@@ -317,12 +454,40 @@ void Debugger::dumpLocals(Module *m) const {
v->value_type, v->value.uint64);
}
- dprintf(this->socket, "{%s, \"index\":%i}%s", _value_str,
- i + f->block->type->param_count,
- (i + 1 < f->block->local_count) ? "," : "");
+ this->channel->write("{%s, \"index\":%u}%s", _value_str,
+ i + f->block->type->param_count,
+ (i + 1 < f->block->local_count) ? "," : "");
}
- dprintf(this->socket, "]}");
- fflush(stdout);
+ this->channel->write("]}");
+ // fflush(stdout);
+}
+
+void Debugger::dumpEvents(long start, long size) const {
+ bool previous = CallbackHandler::resolving_event;
+ CallbackHandler::resolving_event = true;
+ if (size > EVENTS_SIZE) {
+ size = EVENTS_SIZE;
+ }
+
+ this->channel->write(R"("events": [)");
+ long index = start, end = start + size;
+ std::for_each(CallbackHandler::event_begin() + start,
+ CallbackHandler::event_begin() + end,
+ [this, &index, &end](const Event &e) {
+ this->channel->write(
+ R"({"topic": "%s", "payload": "%s"})",
+ e.topic.c_str(), e.payload.c_str());
+ if (++index < end) {
+ this->channel->write(", ");
+ }
+ });
+ this->channel->write("]");
+
+ CallbackHandler::resolving_event = previous;
+}
+
+void Debugger::dumpCallbackmapping() const {
+ this->channel->write("%s\n", CallbackHandler::dump_callbacks().c_str());
}
/**
@@ -394,10 +559,10 @@ bool Debugger::handleChangedFunction(Module *m, uint8_t *bytes) {
bool Debugger::handleChangedLocal(Module *m, uint8_t *bytes) const {
if (*bytes != interruptUPDATELocal) return false;
uint8_t *pos = bytes + 1;
- dprintf(this->socket, "Local updates: %x\n", *pos);
+ this->channel->write("Local updates: %x\n", *pos);
uint32_t localId = read_LEB_32(&pos);
- dprintf(this->socket, "Local %u being changed\n", localId);
+ this->channel->write("Local %u being changed\n", localId);
auto v = &m->stack[m->fp + localId];
switch (v->value_type) {
case I32:
@@ -413,6 +578,478 @@ bool Debugger::handleChangedLocal(Module *m, uint8_t *bytes) const {
memcpy(&v->value.uint64, pos, 8);
break;
}
- dprintf(this->socket, "Local %u changed to %u\n", localId, v->value.uint32);
+ this->channel->write("Local %u changed to %u\n", localId, v->value.uint32);
+ return true;
+}
+
+void Debugger::notifyPushedEvent() const {
+ this->channel->write("new pushed event");
+}
+
+bool Debugger::handlePushedEvent(char *bytes) const {
+ if (*bytes != interruptPUSHEvent) return false;
+ auto parsed = nlohmann::json::parse(bytes);
+ printf("handle pushed event: %s", bytes);
+ auto *event = new Event(*parsed.find("topic"), *parsed.find("payload"));
+ CallbackHandler::push_event(event);
+ this->notifyPushedEvent();
return true;
}
+
+void Debugger::woodDump(Module *m) {
+ debug("asked for doDump\n");
+ printf("asked for woodDump\n");
+ this->channel->write("DUMP!\n");
+ this->channel->write("{");
+
+ // current PC
+ this->channel->write(R"("pc":"%p",)", (void *)m->pc_ptr);
+
+ // start of bytes
+ this->channel->write(R"("start":["%p"],)", (void *)m->bytes);
+
+ this->channel->write("\"breakpoints\":[");
+ size_t i = 0;
+ for (auto bp : this->breakpoints) {
+ this->channel->write(R"("%p"%s)", bp,
+ (++i < this->breakpoints.size()) ? "," : "");
+ }
+ this->channel->write("],");
+
+ // stack
+ this->channel->write("\"stack\":[");
+ for (int j = 0; j <= m->sp; j++) {
+ auto v = &m->stack[j];
+ printValue(v, j, j == m->sp);
+ }
+ this->channel->write("],");
+
+ // Callstack
+ this->channel->write("\"callstack\":[");
+ for (int j = 0; j <= m->csp; j++) {
+ Frame *f = &m->callstack[j];
+ uint8_t *block_key =
+ f->block->block_type == 0 ? nullptr : findOpcode(m, f->block);
+ this->channel->write(
+ R"({"type":%u,"fidx":"0x%x","sp":%d,"fp":%d,"block_key":"%p", "ra":"%p", "idx":%d}%s)",
+ f->block->block_type, f->block->fidx, f->sp, f->fp, block_key,
+ static_cast(f->ra_ptr), j, (j < m->csp) ? "," : "");
+ }
+
+ // Globals
+ this->channel->write("],\"globals\":[");
+ for (uint32_t j = 0; j < m->global_count; j++) {
+ auto v = m->globals + j;
+ printValue(v, j, j == (m->global_count - 1));
+ }
+ this->channel->write("]"); // closing globals
+
+ this->channel->write(R"(,"table":{"max":%d, "init":%d, "elements":[)",
+ m->table.maximum, m->table.initial);
+
+ for (uint32_t j = 0; j < m->table.size; j++) {
+ this->channel->write("%" PRIu32 "%s", m->table.entries[j],
+ (j + 1) == m->table.size ? "" : ",");
+ }
+ this->channel->write("]}"); // closing table
+
+ // memory
+ uint32_t total_elems =
+ m->memory.pages * (uint32_t)PAGE_SIZE; // TODO debug PAGE_SIZE
+ this->channel->write(
+ R"(,"memory":{"pages":%d,"max":%d,"init":%d,"bytes":[)",
+ m->memory.pages, m->memory.maximum, m->memory.initial);
+ for (uint32_t j = 0; j < total_elems; j++) {
+ this->channel->write("%" PRIu8 "%s", m->memory.bytes[j],
+ (j + 1) == total_elems ? "" : ",");
+ }
+ this->channel->write("]}"); // closing memory
+
+ this->channel->write(R"(,"br_table":{"size":"0x%x","labels":[)",
+ BR_TABLE_SIZE);
+ for (uint32_t j = 0; j < BR_TABLE_SIZE; j++) {
+ this->channel->write("%" PRIu32 "%s", m->br_table[j],
+ (j + 1) == BR_TABLE_SIZE ? "" : ",");
+ }
+ this->channel->write("]}}\n");
+}
+
+enum ReceiveState {
+ pcState = 0x01,
+ breakpointsState = 0x02,
+ callstackState = 0x03,
+ globalsState = 0x04,
+ tblState = 0x05,
+ memState = 0x06,
+ brtblState = 0x07,
+ stackvalsState = 0x08,
+ pcErrorState = 0x09
+};
+
+void Debugger::freeState(Module *m, uint8_t *interruptData) {
+ debug("freeing the program state\n");
+ uint8_t *first_msg = nullptr;
+ uint8_t *endfm = nullptr;
+ first_msg = interruptData + 1; // skip interruptRecvState
+ endfm = first_msg + read_B32(&first_msg);
+
+ // nullify state
+ this->breakpoints.clear();
+ m->csp = -1;
+ m->sp = -1;
+ memset(m->br_table, 0, BR_TABLE_SIZE);
+
+ while (first_msg < endfm) {
+ switch (*first_msg++) {
+ case globalsState: {
+ debug("receiving globals info\n");
+ uint32_t amount = read_B32(&first_msg);
+ debug("total globals %d\n", amount);
+ // TODO if global_count != amount Otherwise set all to zero
+ if (m->global_count != amount) {
+ debug("globals freeing state and then allocating\n");
+ if (m->global_count > 0) free(m->globals);
+ if (amount > 0)
+ m->globals = (StackValue *)acalloc(
+ amount, sizeof(StackValue), "globals");
+ } else {
+ debug("globals setting existing state to zero\n");
+ for (uint32_t i = 0; i < m->global_count; i++) {
+ debug("decreasing global_count\n");
+ StackValue *sv = &m->globals[i];
+ sv->value_type = 0;
+ sv->value.uint32 = 0;
+ }
+ }
+ m->global_count = 0;
+ break;
+ }
+ case tblState: {
+ debug("receiving table info\n");
+ m->table.initial = read_B32(&first_msg);
+ m->table.maximum = read_B32(&first_msg);
+ uint32_t size = read_B32(&first_msg);
+ debug("init %d max %d size %d\n", m->table.initial,
+ m->table.maximum, size);
+ if (m->table.size != size) {
+ debug("old table size %d\n", m->table.size);
+ if (m->table.size != 0) free(m->table.entries);
+ m->table.entries = (uint32_t *)acalloc(
+ size, sizeof(uint32_t), "Module->table.entries");
+ }
+ m->table.size = 0; // allows to accumulatively add entries
+ break;
+ }
+ case memState: {
+ debug("receiving memory info\n");
+ // FIXME: init & max not needed
+ m->memory.maximum = read_B32(&first_msg);
+ m->memory.initial = read_B32(&first_msg);
+ uint32_t pages = read_B32(&first_msg);
+ debug("max %d init %d current page %d\n", m->memory.maximum,
+ m->memory.initial, pages);
+ // if(pages !=m->memory.pages){
+ // if(m->memory.pages !=0)
+ if (m->memory.bytes != nullptr) {
+ free(m->memory.bytes);
+ }
+ m->memory.bytes =
+ (uint8_t *)acalloc(pages * PAGE_SIZE, sizeof(uint32_t),
+ "Module->memory.bytes");
+ m->memory.pages = pages;
+ // }
+ // else{
+ // //TODO fill memory.bytes with zeros
+ // memset(m->memory.bytes, 0, m->memory.pages * PAGE_SIZE) ;
+ // }
+ break;
+ }
+ default: {
+ FATAL("freeState: receiving unknown command\n");
+ break;
+ }
+ }
+ }
+ debug("done with first msg\n");
+}
+
+bool Debugger::saveState(Module *m, uint8_t *interruptData) {
+ uint8_t *program_state = nullptr;
+ uint8_t *end_state = nullptr;
+ program_state = interruptData + 1; // skip interruptRecvState
+ end_state = program_state + read_B32(&program_state);
+
+ debug("saving program_state\n");
+ while (program_state < end_state) {
+ switch (*program_state++) {
+ case pcState: { // PC
+ m->pc_ptr = (uint8_t *)readPointer(&program_state);
+ /* printf("receiving pc %p\n", static_cast(m->pc_ptr));
+ */
+ break;
+ }
+ case breakpointsState: { // breakpoints
+ uint8_t quantity_bps = *program_state++;
+ debug("receiving breakpoints %" PRIu8 "\n", quantity_bps);
+ for (size_t i = 0; i < quantity_bps; i++) {
+ auto bp = (uint8_t *)readPointer(&program_state);
+ this->addBreakpoint(bp);
+ }
+ break;
+ }
+ case callstackState: {
+ debug("receiving callstack\n");
+ uint16_t quantity = read_B16(&program_state);
+ debug("quantity frames %" PRIu16 "\n", quantity);
+ /* printf("quantity frames %" PRIu16 "\n", quantity); */
+ for (size_t i = 0; i < quantity; i++) {
+ /* printf("frame IDX: %lu\n", i); */
+ uint8_t block_type = *program_state++;
+ m->csp += 1;
+ Frame *f = m->callstack + m->csp;
+ f->sp = read_B32_signed(&program_state);
+ f->fp = read_B32_signed(&program_state);
+ f->ra_ptr = (uint8_t *)readPointer(&program_state);
+ if (block_type == 0) { // a function
+ debug("function block\n");
+ uint32_t fidx = read_B32(&program_state);
+ /* debug("function block idx=%" PRIu32 "\n", fidx); */
+ f->block = m->functions + fidx;
+
+ if (f->block->fidx != fidx) {
+ FATAL("incorrect fidx: exp %" PRIu32 " got %" PRIu32
+ ". Exiting program\n",
+ fidx, f->block->fidx);
+ }
+ m->fp = f->sp + 1;
+ } else {
+ debug("non function block\n");
+ auto *block_key =
+ (uint8_t *)readPointer(&program_state);
+ /* debug("block_key=%p\n", static_cast(block_key)); */
+ f->block = m->block_lookup[block_key];
+ if (f->block == nullptr) {
+ FATAL("block_lookup cannot be nullptr\n");
+ }
+ }
+ }
+ break;
+ }
+ case globalsState: { // TODO merge globalsState stackvalsState into
+ // one case
+ debug("receiving global state\n");
+ uint32_t quantity_globals = read_B32(&program_state);
+ uint8_t valtypes[] = {I32, I64, F32, F64};
+
+ debug("receiving #%" PRIu32 " globals\n", quantity_globals);
+ for (uint32_t q = 0; q < quantity_globals; q++) {
+ uint8_t type_index = *program_state++;
+ if (type_index >= sizeof(valtypes)) {
+ FATAL("received unknown type %" PRIu8 "\n", type_index);
+ }
+ StackValue *sv = &m->globals[m->global_count++];
+ size_t qb = type_index == 0 || type_index == 2 ? 4 : 8;
+ debug("receiving type %" PRIu8 " and %d bytes \n",
+ type_index,
+ type_index == 0 || type_index == 2 ? 4 : 8);
+
+ sv->value_type = valtypes[type_index];
+ memcpy(&sv->value, program_state, qb);
+ program_state += qb;
+ }
+ break;
+ }
+ case tblState: {
+ program_state++; // for now only funcref
+ uint32_t quantity = read_B32(&program_state);
+ for (size_t i = 0; i < quantity; i++) {
+ uint32_t ne = read_B32(&program_state);
+ m->table.entries[m->table.size++] = ne;
+ }
+ break;
+ }
+ case memState: {
+ debug("receiving memory\n");
+ uint32_t start = read_B32(&program_state);
+ uint32_t limit = read_B32(&program_state);
+ debug("memory offsets start=%" PRIu32 " , limit=%" PRIu32 "\n",
+ start, limit);
+ if (start > limit) {
+ FATAL("incorrect memory offsets\n");
+ }
+ uint32_t total_bytes = limit - start + 1;
+ uint8_t *mem_end =
+ m->memory.bytes + m->memory.pages * (uint32_t)PAGE_SIZE;
+ debug("will copy #%" PRIu32 " bytes\n", total_bytes);
+ if ((m->memory.bytes + start) + total_bytes > mem_end) {
+ FATAL("memory overflow %p > %p\n",
+ static_cast((m->bytes + start) + total_bytes),
+ static_cast(mem_end));
+ }
+ memcpy(m->memory.bytes + start, program_state, total_bytes + 1);
+ for (auto i = start; i <= (start + total_bytes - 1); i++) {
+ debug("GOT byte idx %" PRIu32 " =%" PRIu8 "\n", i,
+ m->memory.bytes[i]);
+ }
+ debug("outside the out\n");
+ program_state += total_bytes;
+ break;
+ }
+ case brtblState: {
+ debug("receiving br_table\n");
+ uint16_t begin_index = read_B16(&program_state);
+ uint16_t end_index = read_B16(&program_state);
+ debug("br_table offsets begin=%" PRIu16 " , end=%" PRIu16 "\n",
+ begin_index, end_index);
+ if (begin_index > end_index) {
+ FATAL("incorrect br_table offsets\n");
+ }
+ if (end_index >= BR_TABLE_SIZE) {
+ FATAL("br_table overflow\n");
+ }
+ for (auto idx = begin_index; idx <= end_index; idx++) {
+ // FIXME speedup with memcpy?
+ uint32_t el = read_B32(&program_state);
+ m->br_table[idx] = el;
+ }
+ break;
+ }
+ case stackvalsState: {
+ // FIXME the float does add numbers at the end. The extra
+ // numbers are present in the send information when dump occurs
+ debug("receiving stack\n");
+ uint16_t quantity_sv = read_B16(&program_state);
+ uint8_t valtypes[] = {I32, I64, F32, F64};
+ for (size_t i = 0; i < quantity_sv; i++) {
+ uint8_t type_index = *program_state++;
+ if (type_index >= sizeof(valtypes)) {
+ FATAL("received unknown type %" PRIu8 "\n", type_index);
+ }
+ m->sp += 1;
+ StackValue *sv = &m->stack[m->sp];
+ sv->value.uint64 = 0; // init whole union to 0
+ size_t qb = type_index == 0 || type_index == 2 ? 4 : 8;
+ sv->value_type = valtypes[type_index];
+ memcpy(&sv->value, program_state, qb);
+ program_state += qb;
+ }
+ break;
+ }
+ default: {
+ FATAL("saveState: Received unknown program state\n");
+ }
+ }
+ }
+ auto done = (uint8_t)*program_state;
+ return done == (uint8_t)1;
+}
+
+uintptr_t Debugger::readPointer(uint8_t **data) {
+ uint8_t len = (*data)[0];
+ uintptr_t bp = 0x0;
+ for (size_t i = 0; i < len; i++) {
+ bp <<= sizeof(uint8_t) * 8;
+ bp |= (*data)[i + 1];
+ }
+ *data += 1 + len; // skip pointer
+ return bp;
+}
+
+void Debugger::proxify() {
+ WARDuino::instance()->program_state = PROXYhalt;
+ this->proxy = new Proxy(); // TODO delete
+}
+
+void Debugger::handleProxyCall(Module *m, RunningState *program_state,
+ uint8_t *interruptData) {
+ if (this->proxy == nullptr) {
+ dbg_info("No proxy available to send proxy call to.\n");
+ // TODO how to handle this error?
+ return;
+ }
+ uint8_t *data = interruptData;
+ uint32_t fidx = read_L32(&data);
+ dbg_info("Proxycall func %" PRIu32 "\n", fidx);
+
+ Block *func = &m->functions[fidx];
+ StackValue *args = Proxy::readRFCArgs(func, data);
+ dbg_trace("Enqueuing callee %" PRIu32 "\n", func->fidx);
+
+ auto *rfc = new RFC(fidx, func->type, args);
+ this->proxy->pushRFC(m, rfc);
+}
+
+RFC *Debugger::topProxyCall() {
+ if (proxy == nullptr) {
+ return nullptr;
+ }
+ return this->proxy->topRFC();
+}
+
+void Debugger::sendProxyCallResult(Module *m) {
+ if (proxy == nullptr) {
+ return;
+ }
+ this->proxy->returnResult(m);
+}
+
+bool Debugger::isProxied(uint32_t fidx) const {
+ return this->supervisor != nullptr && this->supervisor->isProxied(fidx);
+}
+
+void Debugger::handleMonitorProxies(Module *m, uint8_t *interruptData) {
+ uint32_t amount_funcs = read_B32(&interruptData);
+ printf("funcs_total %" PRIu32 "\n", amount_funcs);
+
+ m->warduino->debugger->supervisor->unregisterAllProxiedCalls();
+ for (uint32_t i = 0; i < amount_funcs; i++) {
+ uint32_t fidx = read_B32(&interruptData);
+ printf("registering fid=%" PRIu32 "\n", fidx);
+ m->warduino->debugger->supervisor->registerProxiedCall(fidx);
+ }
+
+ this->channel->write("done!\n");
+}
+
+void Debugger::startProxySupervisor(Channel *socket) {
+ this->connected_to_proxy = true;
+ pthread_mutex_init(&this->supervisor_mutex, nullptr);
+ pthread_mutex_lock(&this->supervisor_mutex);
+
+ this->supervisor = new ProxySupervisor(socket, &this->supervisor_mutex);
+ printf("Connected to proxy.\n");
+}
+
+bool Debugger::proxy_connected() const { return this->connected_to_proxy; }
+
+void Debugger::disconnect_proxy() {
+ if (!this->proxy_connected()) {
+ return;
+ }
+ int *ptr;
+ // TODO close file
+ pthread_mutex_unlock(&this->supervisor_mutex);
+ pthread_join(this->supervisor->getThreadID(), (void **)&ptr);
+}
+
+void Debugger::updateCallbackmapping(Module *m, const char *data) {
+ nlohmann::basic_json<> parsed = nlohmann::json::parse(data);
+ CallbackHandler::clear_callbacks();
+ nlohmann::basic_json<> callbacks = *parsed.find("callbacks");
+ for (auto &array : callbacks.items()) {
+ auto callback = array.value().begin();
+ for (auto &functions : callback.value().items()) {
+ CallbackHandler::add_callback(
+ Callback(m, callback.key(), functions.value()));
+ }
+ }
+}
+
+// Stop the debugger
+void Debugger::stop() {
+ if (this->channel != nullptr) {
+ this->channel->close();
+ this->channel = nullptr;
+ }
+}
diff --git a/src/Debug/debugger.h b/src/Debug/debugger.h
index d0ee12c4..cfa99646 100644
--- a/src/Debug/debugger.h
+++ b/src/Debug/debugger.h
@@ -1,15 +1,37 @@
#pragma once
+#include
+#include
#include // std::queue
#include
#include
#include
-struct Module;
+#include "../Edward/proxy.h"
+#include "../Edward/proxy_supervisor.h"
+#include "../Utils/sockets.h"
-enum RunningState { WARDUINOrun, WARDUINOpause, WARDUINOstep };
+#ifndef ARDUINO
+#include
+#endif
+struct Module;
+struct Block;
+struct StackValue;
+
+enum RunningState {
+ WARDUINOrun,
+ WARDUINOpause,
+ WARDUINOstep,
+ PROXYrun, // Running state used when executing a proxy call. During
+ // this state the call is set up and executed by the main
+ // loop. After execution, the state is restored to
+ // PROXYhalt
+ PROXYhalt // Do not run the program (program runs on computer, which
+ // sends messages for primitives, do forward interrupts)
+};
enum InterruptTypes {
+ // Remote Debugging
interruptRUN = 0x01,
interruptHALT = 0x02,
interruptPAUSE = 0x03,
@@ -20,7 +42,23 @@ enum InterruptTypes {
interruptDUMPLocals = 0x11,
interruptDUMPFull = 0x12,
interruptUPDATEFun = 0x20,
- interruptUPDATELocal = 0x21
+ interruptUPDATELocal = 0x21,
+
+ // Pull Debugging
+ interruptWOODDUMP = 0x60,
+ interruptOffset = 0x61,
+ interruptRecvState = 0x62,
+ interruptMonitorProxies = 0x63,
+ interruptProxyCall = 0x64,
+ interruptProxify = 0x65, // wifi SSID \0 wifi PASS \0
+
+ // Push Debugging
+ interruptDUMPAllEvents = 0x70,
+ interruptDUMPEvents = 0x71,
+ interruptPOPEvent = 0x72,
+ interruptPUSHEvent = 0x73,
+ interruptDUMPCallbackmapping = 0x74,
+ interruptRecvCallbackmapping = 0x75
};
class Debugger {
@@ -28,15 +66,24 @@ class Debugger {
std::deque debugMessages = {};
// Help variables
+
volatile bool interruptWrite{};
volatile bool interruptRead{};
bool interruptEven = true;
uint8_t interruptLastChar{};
std::vector interruptBuffer;
long interruptSize{};
+ bool receivingData = false;
+
+ Proxy *proxy = nullptr; // proxy module for debugger
+
+ bool connected_to_proxy = false;
+ pthread_mutex_t supervisor_mutex;
// Private methods
+ void printValue(StackValue *v, uint32_t idx, bool end) const;
+
// TODO Move parsing to WARDuino class?
uint8_t *parseDebugBuffer(size_t len, const uint8_t *buff);
@@ -44,7 +91,7 @@ class Debugger {
void handleInterruptRUN(Module *m, RunningState *program_state);
- void handleInterruptBP(uint8_t *interruptData);
+ void handleInterruptBP(const uint8_t *interruptData);
//// Information dumps
@@ -52,26 +99,51 @@ class Debugger {
void dumpLocals(Module *m) const;
- void dumpBreakpoints(Module *m) const;
+ void dumpBreakpoints() const;
void dumpFunctions(Module *m) const;
void dumpCallstack(Module *m) const;
+ void dumpEvents(long start, long size) const;
+
+ void dumpCallbackmapping() const;
+
//// Handle live code update
- bool handleChangedFunction(Module *m, uint8_t *bytes);
+ static bool handleChangedFunction(Module *m, uint8_t *bytes);
bool handleChangedLocal(Module *m, uint8_t *bytes) const;
+ //// Handle out-of-place debugging
+
+ void freeState(Module *m, uint8_t *interruptData);
+
+ static uint8_t *findOpcode(Module *m, Block *block);
+
+ bool saveState(Module *m, uint8_t *interruptData);
+
+ static uintptr_t readPointer(uint8_t **data);
+
+ static void updateCallbackmapping(Module *m, const char *interruptData);
+
public:
- int socket;
+ // Public fields
+ Channel *channel;
+ ProxySupervisor *supervisor = nullptr;
std::set breakpoints = {}; // Vector, we expect few breakpoints
uint8_t *skipBreakpoint =
nullptr; // Breakpoint to skip in the next interpretation step
- explicit Debugger(int socket);
+ // Constructor
+ explicit Debugger(Channel *duplex);
+
+ void setChannel(Channel *duplex);
+
+ // Public methods
+
+ void stop();
// Interrupts
@@ -89,5 +161,36 @@ class Debugger {
bool isBreakpoint(uint8_t *loc);
- void notifyBreakpoint(uint8_t *pc_ptr);
+ void notifyBreakpoint(uint8_t *pc_ptr) const;
+
+ // Out-of-place debugging
+
+ void woodDump(Module *m);
+
+ void proxify();
+
+ void handleProxyCall(Module *m, RunningState *program_state,
+ uint8_t *interruptData);
+
+ RFC *topProxyCall();
+
+ void sendProxyCallResult(Module *m);
+
+ bool isProxied(uint32_t fidx) const;
+
+ void startProxySupervisor(Channel *socket);
+
+ bool proxy_connected() const;
+
+ void disconnect_proxy();
+
+ // Pull-based
+
+ void handleMonitorProxies(Module *m, uint8_t *interruptData);
+
+ // Push-based
+
+ void notifyPushedEvent() const;
+
+ bool handlePushedEvent(char *bytes) const;
};
diff --git a/src/Edward/RFC.cpp b/src/Edward/RFC.cpp
new file mode 100644
index 00000000..8bcf131e
--- /dev/null
+++ b/src/Edward/RFC.cpp
@@ -0,0 +1,4 @@
+#include "RFC.h"
+
+RFC::RFC(uint32_t id, Type *t_type, StackValue *t_args)
+ : fidx(id), args(t_args), type(t_type) {}
diff --git a/src/Edward/RFC.h b/src/Edward/RFC.h
new file mode 100644
index 00000000..2ed7b9c8
--- /dev/null
+++ b/src/Edward/RFC.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include
+struct StackValue;
+struct Type;
+
+struct SerializeData {
+ const unsigned char *raw;
+ uint32_t size;
+};
+
+class RFC {
+ public:
+ const uint32_t fidx;
+ StackValue *args;
+ const Type *type;
+ StackValue *result;
+
+ bool success = true;
+ char *exception;
+ uint16_t exception_size;
+
+ RFC(uint32_t id, Type *t_type, StackValue *t_args = nullptr);
+};
diff --git a/src/Edward/proxy.cpp b/src/Edward/proxy.cpp
new file mode 100644
index 00000000..b03dbc60
--- /dev/null
+++ b/src/Edward/proxy.cpp
@@ -0,0 +1,165 @@
+#include "proxy.h"
+
+#include
+#include
+#include
+#include
+#include