Colibri WebAssembly Notes
Various notes, investigations and other useful information that might be needed later.
Zephyr Mutexes
I now have a case where the a zephyr mutex was set up in main(), and later called from a different Zephyr thread, and immediately crashes.
k_mutex_lock(&data->lock, K_FOREVER);
That is an inlined function of
__pinned_func
static inline int k_mutex_lock(struct k_mutex * mutex, k_timeout_t timeout)
{
compiler_barrier();
return z_impl_k_mutex_lock(mutex, timeout);
}
And compiler_barrier() expands to
do { __asm__ __volatile__ ("" ::: "memory"); }
while (0);
on the STM32.
I am now moving code around to ensure that it is always the same thread calling the mutex.
Hmmm... Now instead completely crashing, it is ending up in
void arch_system_halt(unsigned int reason){}
with a reason=4, which is K_ERR_KERNEL_PANIC
Call stack reveals nothing.
arch_system_halt fatal.c:30 k_sys_fatal_error_handler fatal.c:44 z_fatal_error fatal.c:119 z_arm_fatal_error fatal.c:93 z_arm_fault fault.c:1090 z_arm_usage_fault fault_s.S:103 assert_post_action assert.c:44 z_spinlock_validate_pre spinlock.h:132 k_spin_lock spinlock.h:192 z_unpend1_no_timeout sched.c:717 z_impl_k_timer_stop timer.c:276 z_log_msg_post_finalize log_core.c:195 msg_commit log_core.c:717 z_log_msg_commit log_core.c:723 z_log_msg_finalize log_msg.c:54 z_log_msg_simple_create log_msg.c:130 z_impl_z_log_msg_simple_create_1 log_msg.c:229 esf_dump fatal.c:67 z_arm_fatal_error fatal.c:76 z_do_kernel_oops fatal.c:141 z_arm_svc svc.S:158
Need more work here...
CMake for I/O drivers
It is crucial that the wasm binary is stripped of all meta data. This is an example of a reasonable CMakeLists.txt for the Colibri DIO1 module.
cmake_minimum_required(VERSION 3.5)
set(CMAKE_LINK_DEPENDS_USE_LINKER FALSE)
project(io_dio1 C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_COMPILER clang)
include_directories(colibri-sdk/)
add_executable(io_dio1 dio1.c)
set_target_properties(io_dio1 PROPERTIES SUFFIX ".wasm")
target_compile_options(io_dio1 PRIVATE
--target=wasm32
-Oz
-ffunction-sections
-fdata-sections
)
target_link_options(io_dio1 PRIVATE
--target=wasm32-unknown-unknown-wasm # or just =wasm
-nostdlib
-Wl,--no-entry
-Wl,--allow-undefined
-Wl,--gc-sections
-Wl,--strip-all
# Exports
-Wl,--export=event
-Wl,--export=init
-Wl,--export=loaded
-Wl,--export=unloading
# Memory Management
-Wl,--import-memory # Host provides the memory
-Wl,--initial-memory=65536 # Request 2 pages (required for standard compliance)
-Wl,--max-memory=65536 # Cap it at 2 pages
-Wl,-z,stack-size=512 # Shrink WASM-internal stack (Default is often 64KB!)
)
add_custom_command(
TARGET io_dio1 POST_BUILD
COMMAND xxd -i -n io_dio1 ${CMAKE_BINARY_DIR}/io_dio1/io_dio1.wasm | sed 's/unsigned /const unsigned /' >${CMAKE_BINARY_DIR}/io_dio1.h
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating io_dio1.h from io_dio1.wasm using xxd"
)
Memory Allocations
This was an investigation into how much RAM is used to instantiate WebAssembly runtimes. 8 wasm files were deployed, each blinking the LED for the respective slot.
---- Program to be loaded ----
#include "colibri.h"
#define export __attribute__((visibility("default")))
static int next = 0;
static int state = 0;
int tick(long time) {
if (next < time) {
if (state){
set_rgb_error();
next = time + 100;
}
else {
set_rgb_off();
next = time + 500;
}
}
return state;
}
export void event(int id, long value) {
tick(value);
}
export void init() {
set_rgb_ok_color(0x000400);
set_rgb_warning_color(0x040400);
set_rgb_error_color(0x080000);
}
export void loaded() {
set_rgb_off();
}
export void unloading() {
set_rgb_off();
}
Env Heap @ 0x10000000 112 bytes
wasm0 Heap @ 0x10000070 4960 bytes
wasm1 Heap @ 0x100013D0 4368 bytes
wasm2 Heap @ 0x100024E0 4368 bytes
wasm3 Heap @ 0x100035f0 4368 bytes
wasm4 Heap @ 0x10004700 4608 bytes
wasm5 Heap @ 0x10005900 4368 bytes
wasm6 Heap @ 0x10006a10 4368 bytes
wasm7 Heap @ 0x10007b20 5200 bytes
End Heap @ 0x10008F70
----- Once -----
NewEnvironment
M3Environment struct 0x20
AllocFuncType 0x09
AllocFuncType 0x09
AllocFuncType 0x09
AllocFuncType 0x09
AllocFuncType 0x09
----- Per wasm ---
NewRuntime
M3Runtime struct 0x434
runtime->origStack 0x410 (stack + 4 32bit words)
ParseModule
M3Module module 0x78
io_module->functTypes 0x0c
AllocFuncType 0x08
Free
AllocFuncType 0x09
Free
AllocFuncType 0x0A
Free
PreAllocFunctions 0x154 (5 functions * 68 bytes?)
"env" 0x04
"memory" 0x07
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
"env" 0x04
"set_rgb_off" 0x0C
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
"env" 0x04
"set_rgb_ok_color" 0x11
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
"env" 0x04
"set_rgb_warning_color" 0x16
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
"env" 0x04
"set_rgb_error_color" 0x14
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
Free NULL (freeing import, module name)
Free NULL (freeing import, field name)
PreAllocFunctions 0x220
AddGlobal 0x20
"event" 0x06 (exports)
Free NULL (exported name)
"init" 0x05
Free NULL (exported name)
"loaded" 0x07
Free NULL (exported name)
"unloading" 0x0A
Free NULL (exported name)
Free NULL (one extra exported name)
M3DataSegments 0x20 (0 data segment)
LoadModule
NewCodePage 0x40
Free NULL
Free NULL
Free NULL
Free NULL
AllocFuncType 0x09
Free
AllocFuncType 0x09
Free
AllocFuncType 0x09
Free
AllocFuncType 0x09
Free
AllocFuncType 0x09
Free
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
CompileFunction 0x08 ("event")
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
CompileFunction 0x12 ("init")
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
NewCodePage 0x40
CompileFunction 0x14