Crate micrortu_sdk
source ·Expand description
§MicroRTU SDK
Provides utilities to create wasm blocks for MicroRTU.
§Example
This is a basic example of a block that adds two numbers.
use micrortu_sdk::{
params, ports, register_block, Shared, StepResult, FactoryInput
};
use static_cell::StaticCell;
pub struct Counter;
ports! {
#[block_names(counter)]
pub struct Ports {
count: TI13 InOut 1 1,
}
}
params! {
#[block_names(counter)]
pub struct Params {}
}
pub fn factory(_: &mut FactoryInput) -> Option<&'static mut Counter> {
static COUTNER: StaticCell<Counter> = StaticCell::new();
Some(COUTNER.init(Counter))
}
pub fn init(_: &mut Shared, _: &mut Counter) -> StepResult {
0
}
pub fn step(shared: &mut Shared, _: &mut Counter) -> StepResult {
let mut ports = Ports::parse(&mut shared.latched_ports[..]);
ports.count.value += 1.;
0
}
register_block!(Counter, counter, factory, init, step);
§WASM Binary Layout
To define block block_name
, that can be later referenced in MicroRTU
configuration, you need export 3 functions from your final wasm blob.
§Required Exports
§init
init
function with signature () -> ()
.
§SHARED
SHARED
symbol, aligned to 8 bytes, and must be valid
for reads and writes for at least 512 bytes.
§COLLECTED_STRINGS
It should be &[u8]
, which is a pointer to the start and length of the slice.
It should point to all names of the ports and params, concatenated.
name_offset
and name_len
are relative to this slice.
§factory_{block_name}
factory_{block_name}
is a function that will be called to produce a wasm block.
It’s signature should be (i32) -> i32
and code must ensure it follows Rust’s
semantics of that signagure:
for<'a> extern "C" fn(&'a FactoryInput) -> Option<&'static mut BlockName>;
Where BlockName
is your block’s type.
§init_{block_name}
init_{block_name}
is a function that will be called before step
. It’s
signature should be (i32, i32) -> i32
and code must ensure it follows Rust’s
semantics of that signagure:
for<'a> extern "C" fn(&'a mut Shared, &'a mut BlockName) -> StepResult;
§step_{block_name}
step_{block_name}
is a function that will be called to make a “step”. It’s
signature should be (i32, i32) -> i32
and code must ensure it follows Rust’s
semantics of that signature:
for<'a> extern "C" fn(&'a mut Shared, &'a mut BlockName) -> StepResult;
§ports_{block_name}
and params_{block_name}
There also must be exports for ports and params of type &[BindingDefinition]
,
which is [i32; 2] in memory - pointer to the start and length of the slice.
Re-exports§
pub use bump_allocator::BumpAllocator;
pub use ie_base;
pub use ufmt;
Modules§
- Helper trait for trapping errors in an iterator.
Macros§
- Macros for generating parser of arguments block requires. Finalize the build process. That macro must be called at the end to embed metadata into the binary. It creates a link section “metadata” with json data of all registered blocks and exported symbol
COLLECTED_STRINGS
with all strings from the build.BindingDefinition
’sname_offset
andname_len
are referencingCOLLECTED_STRINGS
. - Macros for generating parser of arguments block requires.
- Macros for generating parser of arguments block requires.
- Macros for generating parser of arguments block requires. Register block. That macro should be called for each block to register it.
Structs§
- A binding definition.
- A direction of a binding. Meaningful values are
IN
,OUT
,IN_OUT
. All other values are invalid, but safe. - Shared data between the wasm module and the host.
- A
BindingDefinition
for native (non-wasm) blocks. - Shared data between the wasm module and the host.
Enums§
- Erorrs that can occur while parsing genarated ports from
Shared
, written byMicroRTU
. Indicates misconfiguration ofMicroRTU
or a bug inports!
macro orMicroRTU
firmware.
Constants§
- Represents an input binding.
- Represents an input-output binding.
- Represents an output binding.
Traits§
Functions§
Type Aliases§
- The result of a step.
0
means success, anything else is an error. Implementation could also trap, but it’s not recommended. Any error would be logged.
Derive Macros§
- Macros for generating parser of arguments block requires. Derive macro for
Config
trait. If block requires some configuration, it should be derived fromConfig
trait. It requires type to beAsBytes
andFromBytes
. Firmware will pass slice of bytes and you should be able to callfrom_bytes
method on it to get the configuration. For C code you should be able to cast a pointer to your struct.