Getting Started

Download

Download and install Microvium from the downloads page.

In a command prompt, run the following command to check the installation was successful:

microvium -v

The latest version of Microvium is 0.0.16.

Compile a Script

Create a new script file, script.mvm.js:

// script.mvm.js

const print = vmImport(1);
vmExport(1, add);
vmExport(2, sayHello);

function add(a, b) {
  return a + b;
}

function sayHello() {
  print('Hello');
}

Here we have declared the functions add and sayHello and then exported them to the host firmware with IDs 1 and 2 respectively. IDs can be any integer from 0 to 32767 and do not need to be contiguous.

The print function is imported from the host firmware and called by the script.

Note that not all JavaScript features are supported at present. See Language Features for a description of the supported features. New features are being added all the time.

To compile the script to bytecode, open a command prompt in the same directory as the script and run the following:

microvium script.mvm.js

The above command runs the top-level code in the script, including the vmExport and vmImport function calls. It will output a file named script.mvm-bc, which is the bytecode image that must be downloaded to the target firmware.

The bytecode image includes the add and sayHello functions, as well as an index table that associates the numeric IDs with corresponding function code.

Integrate the Microvium engine

To execute functions in this image from a firmware host, the firmware must use the Microvium runtime engine. The Microvium runtime engine is a C file that must be compiled into the host firmware.

In the host firmware project, run the following command to unpack microvium.c and its header files into the host firmware. (You can also run this command in a subdirectory if you prefer).

microvium --generate-lib

Any time you download a new version of the Microvium compiler, you should re-run the above command to get the latest version of the runtime library.

This does not configure your project or makefile. You need to manually add microvium/microvium.c to your project build.

Also in the host firmware project, run the following command

Call the Script

To call the add function from firmware code, you’ll need code something like this:

The Microvium API is documented as comments in microvium.h

The above example assumes that the bytecode variable contains the exact bytes from the script.mvm-bc file. To make it easier to get started with an example like this, you can get the data literal by running the microvium compiler with the optional argument --output-bytes.

microvium script.mvm.js --output-bytes

Exports and Imports

mvm_resolveExports searches the bytecode’s export table for each of the IDs listed in the importIDs array and populates the corresponding entry in the imports array.

Similarly, resolveHostFunction in the example code should search the host firmware for functions it wants to expose to the script code. In this example, there is only the print function.

Garbage Collection

JavaScript is a garbage-collected language. The virtual machine will consume progressively more memory until a garbage collection (GC) cycle is triggered with mvm_runGC. A GC cycle is also automatically triggered when the VM hits its maximum configured heap size (MVM_MAX_HEAP_SIZE). See Memory Management for more detail.

The VM’s heap memory is allocated in chunks (256B chunks by default) from the host’s heap using malloc.

Dynamic Typing

JavaScript is a dynamically typed language. To refer to JavaScript values with C code, use the mvm_Value type. mvm_Value is a reference (like a pointer) to a JavaScript value in the virtual machine’s own memory heap.

These should be considered to be weak references — the values they point to are not guaranteed to be preserved across garbage collection cycles (there are some exceptions to this, such as a mvm_Value returned from mvm_resolveExports).

In general, it’s best to assume that mvm_Value variables become dangling pointers during garbage collection, unless they are imports or are wrapped in a handle. In the example, we needed to call mvm_toInt32 before calling mvm_runGC, to get the value out of result before it might become dangling.

To create an mvm_Value, use one of the following:

  • mvm_undefined (the undefined value in JavaScript)
  • mvm_null (the null value in JavaScript)
  • mvm_newBoolean (creates a boolean value)
  • mvm_newNumber (creates a number value)
  • mvm_newInt32 (creates a number value from an int32_t)
  • mvm_newString (creates a string value)

To extract the value of an mvm_Value, use:

  • mvm_typeOf
  • mvm_isNaN
  • mvm_toBool
  • mvm_toInt32
  • mvm_toFloat64
  • mvm_toStringUtf8

An mvm_Value can also point to a JavaScript function, as demonstrated by the imports variable in the above example. Using mvm_typeOf in that case will return VM_T_FUNCTION. As in the example, JavaScript function values can be called using mvm_call.

Scripts can also internally use JavaScript arrays and objects, but there is no way to create or access these through the Microvium API.