From 6785fe17f2c27fd509cc12d6589d675045209e06 Mon Sep 17 00:00:00 2001 From: Friedrich Date: Fri, 22 Mar 2024 13:34:39 +0100 Subject: [PATCH] Switch to proper wit deps handling (#10) * guest works * working version * actually it's kinda works * add some docs --- .github/workflows/main.yml | 18 ++ .gitignore | 3 + Justfile | 20 ++ README.md | 20 +- empty.wasm | Bin 0 -> 8 bytes empty.wat | 1 + guest/Cargo.lock | 9 +- guest/Cargo.toml | 4 +- guest/hat/Cargo.toml | 9 +- guest/hat/src/bindings.rs | 154 +++++++++++---- guest/hat/src/lib.rs | 4 +- guest/lcd/Cargo.toml | 4 +- guest/lcd/src/bindings.rs | 259 +++++++++++++------------ guest/lcd/src/lib.rs | 10 +- host/Cargo.lock | 383 +++++++++++++++++-------------------- host/Cargo.toml | 4 +- host/src/device.rs | 145 ++++++++++++-- host/src/device/screen.rs | 136 ------------- host/src/device/sensor.rs | 118 ------------ host/src/main.rs | 27 +-- wit/deps.lock | 4 + wit/deps.toml | 1 + wit/deps/i2c/delay.wit | 12 ++ wit/deps/i2c/i2c.wit | 82 ++++++++ wit/deps/i2c/world.wit | 6 + wit/device.wit | 32 ++-- wit/embedded.wit | 360 ---------------------------------- 27 files changed, 775 insertions(+), 1050 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 Justfile create mode 100644 empty.wasm create mode 100644 empty.wat delete mode 100644 host/src/device/screen.rs delete mode 100644 host/src/device/sensor.rs create mode 100644 wit/deps.lock create mode 100644 wit/deps.toml create mode 100644 wit/deps/i2c/delay.wit create mode 100644 wit/deps/i2c/i2c.wit create mode 100644 wit/deps/i2c/world.wit delete mode 100644 wit/embedded.wit diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..1249d8d --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,18 @@ +name: CI +on: + push: + branches: [root] + pull_request: + branches: [root] + +jobs: + deps-up-to-date: + name: Check I2C dependency is up-to-date + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: ensure `./wit/deps` are in sync + run: | + curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.2/wit-deps-x86_64-unknown-linux-musl + chmod +x ./wit-deps + ./wit-deps lock --check \ No newline at end of file diff --git a/.gitignore b/.gitignore index ed96cb4..065bc00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ **/target +# Ignore all wasm files, except the empty ones +*.wasm +!empty.wasm # Added by cargo diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..e9fbc48 --- /dev/null +++ b/Justfile @@ -0,0 +1,20 @@ +default: hat host + +hat: build-hat cp-hat +lcd: build-lcd cp-lcd +host: build-host + +build-hat: + cd guest/hat && cargo +nightly component build --release + +cp-hat: + cp guest/target/wasm32-wasi/release/hat.wasm hat.wasm + +build-lcd: + cd guest/lcd && cargo +nightly component build --release + +cp-lcd: + cp guest/target/wasm32-wasi/release/lcd.wasm lcd.wasm + +build-host: + cd host && cargo build --release --target aarch64-unknown-linux-gnu diff --git a/README.md b/README.md index 06283cf..f04cfd4 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ The purpose of this repository is to serve as a proof of concept of a potential Currently, the setup is as follows: Raspberry Pi 4 Model B → I2C Interface → HD44780 LCD. It is my intention to switch out the Pi for a Pi Pico microcontroller, to have a proof of concept for a more constrained piece of hardware. I also have a Pi 3 Model B hooked up with a HTS221. +## Just + +To make building easier [just](https://just.systems/man/en/) is used, see `Justfile`. + ## Host To compile for Raspberry Pi make sure to have the corresponding target and linker installed. @@ -12,6 +16,12 @@ rustup target add aarch64-unknown-linux-gnu yay -S aarch64-linux-gnu-gcc ``` +### Switching guest + +1. Change the `included` guest in the wit. +2. Change the method invocations in the `run` function inside `device.rs`. +3. Change the used `wasm` file inside `main`. + ## Guest ### Screen This guest component is written in Rust and uses the received I²C connection to display `hello world` to the HD44780 LCD screen. @@ -32,9 +42,15 @@ cargo +nightly component build ``` ## WIT -`embedded.wit` comes from [hello-embedded](https://github.com/sunfishcode/hello-embedded) by sunfishcode. Only the `i2c` and `delay` interfaces are used from this. +See [wasi-i2c](https://github.com/WebAssembly/wasi-i2c) for the source of the wit files. + +### `app` world and how I tried to make a generic interface for the host + +As I currently have multiple guest components, I would like to use whichever in the host via a CLI. Problem is that the [bindgen](https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html) macro is quite restrictive, e.g. it's not possible to have one for each world or to define a wrapper around the guest components and then call that one (see [this commit](https://github.com/Zelzahn/i2c-wasm-components/pull/10/commits/5ea3c0f43e3e46022cf8d05a31e439431b359e2d)). + +So I came to the `app` world, it includes one of the guest components. The benefit of this wrapper is that the world itself does not change, thus limiting the number of changes required to switch the linked guest in the host. -I had to use the same package for my `screen.wit` to make the `bindgen` in the host work, more specifically the `with`. +Another solution would be to define a host for each guest component, see [this commit](https://github.com/Zelzahn/i2c-wasm-components/commit/7b9648b57c24aad50015215e89f6b6db9342f19e), but this leads to loads of code duplication. ## Embedded HAL The [embedded-hal](https://crates.io/crates/embedded-hal) crate is the main inspiration for the design of the API. But I currently have not found a way to package a crate that uses this API into a WASM module. diff --git a/empty.wasm b/empty.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d8fc92d022fbf4d1072da17bc8e0840054b51ddc GIT binary patch literal 8 PcmZQbEY4+QU|;|M2ZjMd literal 0 HcmV?d00001 diff --git a/empty.wat b/empty.wat new file mode 100644 index 0000000..3af8f25 --- /dev/null +++ b/empty.wat @@ -0,0 +1 @@ +(module) diff --git a/guest/Cargo.lock b/guest/Cargo.lock index 6fcbd89..52698f2 100644 --- a/guest/Cargo.lock +++ b/guest/Cargo.lock @@ -10,9 +10,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "compiler_builtins" @@ -93,8 +93,9 @@ dependencies = [ [[package]] name = "wasi-embedded-hal" -version = "0.0.1" -source = "git+https://github.com/Zelzahn/wasi-embedded-hal#6ff963665ed749da344c933377ac22dfccb02161" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d6f50a2f8cf61975dc996d084d3a08a3dcbb79a92f3e2010aa7b026853f8d10" dependencies = [ "bitflags", "embedded-hal", diff --git a/guest/Cargo.toml b/guest/Cargo.toml index 3b5e476..99e2fe7 100644 --- a/guest/Cargo.toml +++ b/guest/Cargo.toml @@ -3,7 +3,7 @@ members = ["lcd", "hat"] resolver = "2" [workspace.dependencies] -lol_alloc = "0.4.0" -bitflags = "2.4.2" +lol_alloc = "0.4.1" +bitflags = "2.5.0" wit-bindgen-rt = { version = "0.22.0", default-features = false } compiler_builtins = { version = "0.1.108", features = ["mem"] } diff --git a/guest/hat/Cargo.toml b/guest/hat/Cargo.toml index 055c7ee..dd8b38e 100644 --- a/guest/hat/Cargo.toml +++ b/guest/hat/Cargo.toml @@ -14,19 +14,22 @@ bitflags = { workspace = true } wit-bindgen-rt = { workspace = true } compiler_builtins = { workspace = true } embedded-hal = "1.0.0" -wasi-embedded-hal = { git = "https://github.com/Zelzahn/wasi-embedded-hal", default-features = false, features = [ "use_alloc" ] } +wasi-embedded-hal = { version = "0.2.0", default-features = false, features = [ + "use_alloc", +] } [package.metadata.component] -package = "embedded:hat" +package = "sketch:implementation" # We don't need an adapter, but cargo-component doesn't yet have an option to # disable the adapter. As a workaround, use an empty adapter. adapter = "../empty.wasm" [package.metadata.component.target] path = "../../wit" -world = "sensor" +world = "app" [package.metadata.component.target.dependencies] +"wasi:i2c" = { path = "../../wit/deps/i2c" } [package.metadata.component.bindings] # Enable this to put `std` usage behind a feature, so that we can use `no_std`. diff --git a/guest/hat/src/bindings.rs b/guest/hat/src/bindings.rs index a199ca1..1d2d1b6 100644 --- a/guest/hat/src/bindings.rs +++ b/guest/hat/src/bindings.rs @@ -1,8 +1,8 @@ // Generated by `wit-bindgen` 0.21.0. DO NOT EDIT! // Options used: // * std_feature -pub mod sketch { - pub mod embedded { +pub mod wasi { + pub mod i2c { #[allow(clippy::all)] pub mod i2c { #[used] @@ -107,7 +107,7 @@ pub mod sketch { /// An operation used by the `transaction` method. #[derive(Clone)] pub enum Operation { - /// Read the given number of bytes. + /// Read the give number of bytes. Read(u64), /// Write the given bytes. Write(_rt::Vec), @@ -154,7 +154,7 @@ pub mod sketch { #[cfg(target_arch = "wasm32")] { - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[resource-drop]i2c"] fn drop(_: u32); @@ -213,7 +213,7 @@ pub mod sketch { } let ptr2 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.transaction"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: *mut u8); @@ -299,7 +299,7 @@ pub mod sketch { let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 12]); let ptr0 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.read"] fn wit_import(_: i32, _: i32, _: i64, _: *mut u8); @@ -370,7 +370,7 @@ pub mod sketch { let len0 = vec0.len(); let ptr1 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.write"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: *mut u8); @@ -442,7 +442,7 @@ pub mod sketch { let len0 = vec0.len(); let ptr1 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.write-read"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: i64, _: *mut u8); @@ -503,11 +503,89 @@ pub mod sketch { } } } + + #[allow(clippy::all)] + pub mod delay { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// Delay with up to nanosecond precision. + + #[derive(Debug)] + #[repr(transparent)] + pub struct Delay { + handle: _rt::Resource, + } + + impl Delay { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: _rt::Resource::from_handle(handle), + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + + unsafe impl _rt::WasmResource for Delay { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link(wasm_import_module = "wasi:i2c/delay@0.1.0")] + extern "C" { + #[link_name = "[resource-drop]delay"] + fn drop(_: u32); + } + + drop(_handle); + } + } + } + + impl Delay { + #[allow(unused_unsafe, clippy::all)] + /// Pauses execution for at minimum `ns` nanoseconds. Pause can be + /// longer if the implementation requires it due to precision/timing + /// issues. + pub fn delay_ns(&self, ns: u32) { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:i2c/delay@0.1.0")] + extern "C" { + #[link_name = "[method]delay.delay-ns"] + fn wit_import(_: i32, _: i32); + } + + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32, _: i32) { + unreachable!() + } + wit_import((self).handle() as i32, _rt::as_i32(&ns)); + } + } + } + } } } pub mod exports { pub mod sketch { - pub mod embedded { + pub mod implementation { #[allow(clippy::all)] pub mod hts { #[used] @@ -516,15 +594,13 @@ pub mod exports { static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; use super::super::super::super::_rt; - pub type I2c = super::super::super::super::sketch::embedded::i2c::I2c; - pub type ErrorCode = super::super::super::super::sketch::embedded::i2c::ErrorCode; + pub type I2c = super::super::super::super::wasi::i2c::i2c::I2c; + pub type ErrorCode = super::super::super::super::wasi::i2c::i2c::ErrorCode; #[doc(hidden)] #[allow(non_snake_case)] pub unsafe fn _export_get_temperature_cabi(arg0: i32) -> *mut u8 { let result0 = T::get_temperature( - super::super::super::super::sketch::embedded::i2c::I2c::from_handle( - arg0 as u32, - ), + super::super::super::super::wasi::i2c::i2c::I2c::from_handle(arg0 as u32), ); let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); match result0 { @@ -539,7 +615,7 @@ pub mod exports { } Err(e) => { *ptr1.add(0).cast::() = (1i32) as u8; - use super::super::super::super::sketch::embedded::i2c::ErrorCode as V3; + use super::super::super::super::wasi::i2c::i2c::ErrorCode as V3; match e { V3::Bus => { *ptr1.add(4).cast::() = (0i32) as u8; @@ -579,9 +655,7 @@ pub mod exports { #[allow(non_snake_case)] pub unsafe fn _export_get_humidity_cabi(arg0: i32) -> *mut u8 { let result0 = T::get_humidity( - super::super::super::super::sketch::embedded::i2c::I2c::from_handle( - arg0 as u32, - ), + super::super::super::super::wasi::i2c::i2c::I2c::from_handle(arg0 as u32), ); let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); match result0 { @@ -596,7 +670,7 @@ pub mod exports { } Err(e) => { *ptr1.add(0).cast::() = (1i32) as u8; - use super::super::super::super::sketch::embedded::i2c::ErrorCode as V3; + use super::super::super::super::wasi::i2c::i2c::ErrorCode as V3; match e { V3::Bus => { *ptr1.add(4).cast::() = (0i32) as u8; @@ -638,29 +712,29 @@ pub mod exports { } #[doc(hidden)] - macro_rules! __export_sketch_embedded_hts_0_0_0_cabi{ + macro_rules! __export_sketch_implementation_hts_cabi{ ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { - #[export_name = "sketch:embedded/hts@0.0.0#get-temperature"] + #[export_name = "sketch:implementation/hts#get-temperature"] unsafe extern "C" fn export_get_temperature(arg0: i32,) -> *mut u8 { $($path_to_types)*::_export_get_temperature_cabi::<$ty>(arg0) } - #[export_name = "cabi_post_sketch:embedded/hts@0.0.0#get-temperature"] + #[export_name = "cabi_post_sketch:implementation/hts#get-temperature"] unsafe extern "C" fn _post_return_get_temperature(arg0: *mut u8,) { $($path_to_types)*::__post_return_get_temperature::<$ty>(arg0) } - #[export_name = "sketch:embedded/hts@0.0.0#get-humidity"] + #[export_name = "sketch:implementation/hts#get-humidity"] unsafe extern "C" fn export_get_humidity(arg0: i32,) -> *mut u8 { $($path_to_types)*::_export_get_humidity_cabi::<$ty>(arg0) } - #[export_name = "cabi_post_sketch:embedded/hts@0.0.0#get-humidity"] + #[export_name = "cabi_post_sketch:implementation/hts#get-humidity"] unsafe extern "C" fn _post_return_get_humidity(arg0: *mut u8,) { $($path_to_types)*::__post_return_get_humidity::<$ty>(arg0) } };); } #[doc(hidden)] - pub(crate) use __export_sketch_embedded_hts_0_0_0_cabi; + pub(crate) use __export_sketch_implementation_hts_cabi; #[repr(align(4))] struct _RetArea([::core::mem::MaybeUninit; 12]); static mut _RET_AREA: _RetArea = _RetArea([::core::mem::MaybeUninit::uninit(); 12]); @@ -900,21 +974,21 @@ mod _rt { #[allow(unused_macros)] #[doc(hidden)] -macro_rules! __export_sensor_impl { +macro_rules! __export_app_impl { ($ty:ident) => (self::export!($ty with_types_in self);); ($ty:ident with_types_in $($path_to_types_root:tt)*) => ( - $($path_to_types_root)*::exports::sketch::embedded::hts::__export_sketch_embedded_hts_0_0_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::sketch::embedded::hts); + $($path_to_types_root)*::exports::sketch::implementation::hts::__export_sketch_implementation_hts_cabi!($ty with_types_in $($path_to_types_root)*::exports::sketch::implementation::hts); ) } #[doc(inline)] -pub(crate) use __export_sensor_impl as export; +pub(crate) use __export_app_impl as export; #[cfg(target_arch = "wasm32")] -#[link_section = "component-type:wit-bindgen:0.21.0:sensor:encoded world"] +#[link_section = "component-type:wit-bindgen:0.21.0:app:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 787] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x96\x05\x01A\x02\x01\ -A\x06\x01B\x18\x01{\x04\0\x07address\x03\0\0\x01m\x03\x07address\x04data\x07unkn\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 857] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xdf\x05\x01A\x02\x01\ +A\x08\x01B\x18\x01{\x04\0\x07address\x03\0\0\x01m\x03\x07address\x04data\x07unkn\ own\x04\0\x15no-acknowledge-source\x03\0\x02\x01q\x05\x03bus\0\0\x10arbitration-\ loss\0\0\x0eno-acknowledge\x01\x03\0\x07overrun\0\0\x05other\0\0\x04\0\x0aerror-\ code\x03\0\x04\x01p}\x01q\x02\x04read\x01w\0\x05write\x01\x06\0\x04\0\x09operati\ @@ -924,13 +998,15 @@ c.transaction\x01\x0e\x01j\x01\x06\x01\x05\x01@\x03\x04self\x0a\x07address\x01\x lenw\0\x0f\x04\0\x10[method]i2c.read\x01\x10\x01j\0\x01\x05\x01@\x03\x04self\x0a\ \x07address\x01\x04data\x06\0\x11\x04\0\x11[method]i2c.write\x01\x12\x01@\x04\x04\ self\x0a\x07address\x01\x05write\x06\x08read-lenw\0\x0f\x04\0\x16[method]i2c.wri\ -te-read\x01\x13\x03\x01\x19sketch:embedded/i2c@0.0.0\x05\0\x02\x03\0\0\x03i2c\x02\ -\x03\0\0\x0aerror-code\x01B\x09\x02\x03\x02\x01\x01\x04\0\x03i2c\x03\0\0\x02\x03\ -\x02\x01\x02\x04\0\x0aerror-code\x03\0\x02\x01i\x01\x01j\x01s\x01\x03\x01@\x01\x0a\ -connection\x04\0\x05\x04\0\x0fget-temperature\x01\x06\x04\0\x0cget-humidity\x01\x06\ -\x04\x01\x19sketch:embedded/hts@0.0.0\x05\x03\x04\x01\x1csketch:embedded/sensor@\ -0.0.0\x04\0\x0b\x0c\x01\0\x06sensor\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\ -\x0dwit-component\x070.201.0\x10wit-bindgen-rust\x060.21.0"; +te-read\x01\x13\x03\x01\x12wasi:i2c/i2c@0.1.0\x05\0\x01B\x04\x04\0\x05delay\x03\x01\ +\x01h\0\x01@\x02\x04self\x01\x02nsy\x01\0\x04\0\x16[method]delay.delay-ns\x01\x02\ +\x03\x01\x14wasi:i2c/delay@0.1.0\x05\x01\x02\x03\0\0\x03i2c\x02\x03\0\0\x0aerror\ +-code\x01B\x09\x02\x03\x02\x01\x02\x04\0\x03i2c\x03\0\0\x02\x03\x02\x01\x03\x04\0\ +\x0aerror-code\x03\0\x02\x01i\x01\x01j\x01s\x01\x03\x01@\x01\x0aconnection\x04\0\ +\x05\x04\0\x0fget-temperature\x01\x06\x04\0\x0cget-humidity\x01\x06\x04\x01\x19s\ +ketch:implementation/hts\x05\x04\x04\x01\x19sketch:implementation/app\x04\0\x0b\x09\ +\x01\0\x03app\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x07\ +0.201.0\x10wit-bindgen-rust\x060.21.0"; #[inline(never)] #[doc(hidden)] diff --git a/guest/hat/src/lib.rs b/guest/hat/src/lib.rs index 71b1445..0aef848 100644 --- a/guest/hat/src/lib.rs +++ b/guest/hat/src/lib.rs @@ -3,11 +3,11 @@ #[allow(warnings)] mod bindings; -use crate::bindings::exports::sketch::embedded::hts::Guest; +use crate::bindings::exports::sketch::implementation::hts::Guest; use lol_alloc::{AssumeSingleThreaded, FreeListAllocator}; use wasi_embedded_hal::add_i2c_hal; -use crate::bindings::sketch::embedded::i2c; +use bindings::wasi::i2c::i2c; #[macro_use] extern crate alloc; diff --git a/guest/lcd/Cargo.toml b/guest/lcd/Cargo.toml index ab91ec8..fa62521 100644 --- a/guest/lcd/Cargo.toml +++ b/guest/lcd/Cargo.toml @@ -13,15 +13,17 @@ wit-bindgen-rt = { workspace = true } compiler_builtins = { workspace = true } [package.metadata.component] +package = "sketch:implementation" # We don't need an adapter, but cargo-component doesn't yet have an option to # disable the adapter. As a workaround, use an empty adapter. adapter = "../empty.wasm" [package.metadata.component.target] path = "../../wit" -world = "screen" +world = "app" [package.metadata.component.target.dependencies] +"wasi:i2c" = { path = "../../wit/deps/i2c" } [package.metadata.component.bindings] # Enable this to put `std` usage behind a feature, so that we can use `no_std`. diff --git a/guest/lcd/src/bindings.rs b/guest/lcd/src/bindings.rs index 5c9e269..c9aa441 100644 --- a/guest/lcd/src/bindings.rs +++ b/guest/lcd/src/bindings.rs @@ -1,86 +1,8 @@ // Generated by `wit-bindgen` 0.21.0. DO NOT EDIT! // Options used: // * std_feature -pub mod sketch { - pub mod embedded { - #[allow(clippy::all)] - pub mod delay { - #[used] - #[doc(hidden)] - #[cfg(target_arch = "wasm32")] - static __FORCE_SECTION_REF: fn() = - super::super::super::__link_custom_section_describing_imports; - use super::super::super::_rt; - /// Delay with up to nanosecond precision. - - #[derive(Debug)] - #[repr(transparent)] - pub struct Delay { - handle: _rt::Resource, - } - - impl Delay { - #[doc(hidden)] - pub unsafe fn from_handle(handle: u32) -> Self { - Self { - handle: _rt::Resource::from_handle(handle), - } - } - - #[doc(hidden)] - pub fn take_handle(&self) -> u32 { - _rt::Resource::take_handle(&self.handle) - } - - #[doc(hidden)] - pub fn handle(&self) -> u32 { - _rt::Resource::handle(&self.handle) - } - } - - unsafe impl _rt::WasmResource for Delay { - #[inline] - unsafe fn drop(_handle: u32) { - #[cfg(not(target_arch = "wasm32"))] - unreachable!(); - - #[cfg(target_arch = "wasm32")] - { - #[link(wasm_import_module = "sketch:embedded/delay@0.0.0")] - extern "C" { - #[link_name = "[resource-drop]delay"] - fn drop(_: u32); - } - - drop(_handle); - } - } - } - - impl Delay { - #[allow(unused_unsafe, clippy::all)] - /// Pauses execution for at minimum `ns` nanoseconds. Pause can be - /// longer if the implementation requires it due to precision/timing - /// issues. - pub fn delay_ns(&self, ns: u32) { - unsafe { - #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/delay@0.0.0")] - extern "C" { - #[link_name = "[method]delay.delay-ns"] - fn wit_import(_: i32, _: i32); - } - - #[cfg(not(target_arch = "wasm32"))] - fn wit_import(_: i32, _: i32) { - unreachable!() - } - wit_import((self).handle() as i32, _rt::as_i32(&ns)); - } - } - } - } - +pub mod wasi { + pub mod i2c { #[allow(clippy::all)] pub mod i2c { #[used] @@ -232,7 +154,7 @@ pub mod sketch { #[cfg(target_arch = "wasm32")] { - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[resource-drop]i2c"] fn drop(_: u32); @@ -291,7 +213,7 @@ pub mod sketch { } let ptr2 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.transaction"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: *mut u8); @@ -377,7 +299,7 @@ pub mod sketch { let mut ret_area = RetArea([::core::mem::MaybeUninit::uninit(); 12]); let ptr0 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.read"] fn wit_import(_: i32, _: i32, _: i64, _: *mut u8); @@ -448,7 +370,7 @@ pub mod sketch { let len0 = vec0.len(); let ptr1 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.write"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: *mut u8); @@ -520,7 +442,7 @@ pub mod sketch { let len0 = vec0.len(); let ptr1 = ret_area.0.as_mut_ptr().cast::(); #[cfg(target_arch = "wasm32")] - #[link(wasm_import_module = "sketch:embedded/i2c@0.0.0")] + #[link(wasm_import_module = "wasi:i2c/i2c@0.1.0")] extern "C" { #[link_name = "[method]i2c.write-read"] fn wit_import(_: i32, _: i32, _: *mut u8, _: usize, _: i64, _: *mut u8); @@ -581,11 +503,89 @@ pub mod sketch { } } } + + #[allow(clippy::all)] + pub mod delay { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// Delay with up to nanosecond precision. + + #[derive(Debug)] + #[repr(transparent)] + pub struct Delay { + handle: _rt::Resource, + } + + impl Delay { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: _rt::Resource::from_handle(handle), + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + } + + unsafe impl _rt::WasmResource for Delay { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link(wasm_import_module = "wasi:i2c/delay@0.1.0")] + extern "C" { + #[link_name = "[resource-drop]delay"] + fn drop(_: u32); + } + + drop(_handle); + } + } + } + + impl Delay { + #[allow(unused_unsafe, clippy::all)] + /// Pauses execution for at minimum `ns` nanoseconds. Pause can be + /// longer if the implementation requires it due to precision/timing + /// issues. + pub fn delay_ns(&self, ns: u32) { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "wasi:i2c/delay@0.1.0")] + extern "C" { + #[link_name = "[method]delay.delay-ns"] + fn wit_import(_: i32, _: i32); + } + + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32, _: i32) { + unreachable!() + } + wit_import((self).handle() as i32, _rt::as_i32(&ns)); + } + } + } + } } } pub mod exports { pub mod sketch { - pub mod embedded { + pub mod implementation { #[allow(clippy::all)] pub mod lcd { #[used] @@ -593,41 +593,49 @@ pub mod exports { #[cfg(target_arch = "wasm32")] static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; - pub type Delay = super::super::super::super::sketch::embedded::delay::Delay; - pub type I2c = super::super::super::super::sketch::embedded::i2c::I2c; + use super::super::super::super::_rt; + pub type I2c = super::super::super::super::wasi::i2c::i2c::I2c; + pub type Delay = super::super::super::super::wasi::i2c::delay::Delay; #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_write_cabi(arg0: i32, arg1: i32) { + pub unsafe fn _export_write_cabi( + arg0: i32, + arg1: i32, + arg2: *mut u8, + arg3: usize, + ) { + let len0 = arg3; + let bytes0 = _rt::Vec::from_raw_parts(arg2.cast(), len0, len0); T::write( - super::super::super::super::sketch::embedded::i2c::I2c::from_handle( - arg0 as u32, - ), - super::super::super::super::sketch::embedded::delay::Delay::from_handle( + super::super::super::super::wasi::i2c::i2c::I2c::from_handle(arg0 as u32), + super::super::super::super::wasi::i2c::delay::Delay::from_handle( arg1 as u32, ), + _rt::string_lift(bytes0), ); } pub trait Guest { - fn write(connection: I2c, delay: Delay); + fn write(connection: I2c, delay: Delay, message: _rt::String); } #[doc(hidden)] - macro_rules! __export_sketch_embedded_lcd_0_0_0_cabi{ + macro_rules! __export_sketch_implementation_lcd_cabi{ ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { - #[export_name = "sketch:embedded/lcd@0.0.0#write"] - unsafe extern "C" fn export_write(arg0: i32,arg1: i32,) { - $($path_to_types)*::_export_write_cabi::<$ty>(arg0, arg1) + #[export_name = "sketch:implementation/lcd#write"] + unsafe extern "C" fn export_write(arg0: i32,arg1: i32,arg2: *mut u8,arg3: usize,) { + $($path_to_types)*::_export_write_cabi::<$ty>(arg0, arg1, arg2, arg3) } };); } #[doc(hidden)] - pub(crate) use __export_sketch_embedded_lcd_0_0_0_cabi; + pub(crate) use __export_sketch_implementation_lcd_cabi; } } } } mod _rt { + pub use alloc_crate::vec::Vec; use core::fmt; use core::marker; @@ -792,7 +800,6 @@ mod _rt { self as i32 } } - pub use alloc_crate::vec::Vec; pub fn as_i64(t: T) -> i64 { t.as_i64() @@ -836,6 +843,14 @@ mod _rt { core::hint::unreachable_unchecked() } } + pub unsafe fn string_lift(bytes: Vec) -> String { + if cfg!(debug_assertions) { + String::from_utf8(bytes).unwrap() + } else { + String::from_utf8_unchecked(bytes) + } + } + pub use alloc_crate::string::String; extern crate alloc as alloc_crate; } @@ -861,7 +876,7 @@ mod _rt { macro_rules! __export_screen_impl { ($ty:ident) => (self::export!($ty with_types_in self);); ($ty:ident with_types_in $($path_to_types_root:tt)*) => ( - $($path_to_types_root)*::exports::sketch::embedded::lcd::__export_sketch_embedded_lcd_0_0_0_cabi!($ty with_types_in $($path_to_types_root)*::exports::sketch::embedded::lcd); + $($path_to_types_root)*::exports::sketch::implementation::lcd::__export_sketch_implementation_lcd_cabi!($ty with_types_in $($path_to_types_root)*::exports::sketch::implementation::lcd); ) } #[doc(inline)] @@ -870,27 +885,27 @@ pub(crate) use __export_screen_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.21.0:screen:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 844] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xcf\x05\x01A\x02\x01\ -A\x08\x01B\x04\x04\0\x05delay\x03\x01\x01h\0\x01@\x02\x04self\x01\x02nsy\x01\0\x04\ -\0\x16[method]delay.delay-ns\x01\x02\x03\x01\x1bsketch:embedded/delay@0.0.0\x05\0\ -\x01B\x18\x01{\x04\0\x07address\x03\0\0\x01m\x03\x07address\x04data\x07unknown\x04\ -\0\x15no-acknowledge-source\x03\0\x02\x01q\x05\x03bus\0\0\x10arbitration-loss\0\0\ -\x0eno-acknowledge\x01\x03\0\x07overrun\0\0\x05other\0\0\x04\0\x0aerror-code\x03\ -\0\x04\x01p}\x01q\x02\x04read\x01w\0\x05write\x01\x06\0\x04\0\x09operation\x03\0\ -\x07\x04\0\x03i2c\x03\x01\x01h\x09\x01p\x08\x01p\x06\x01j\x01\x0c\x01\x05\x01@\x03\ -\x04self\x0a\x07address\x01\x0aoperations\x0b\0\x0d\x04\0\x17[method]i2c.transac\ -tion\x01\x0e\x01j\x01\x06\x01\x05\x01@\x03\x04self\x0a\x07address\x01\x03lenw\0\x0f\ -\x04\0\x10[method]i2c.read\x01\x10\x01j\0\x01\x05\x01@\x03\x04self\x0a\x07addres\ -s\x01\x04data\x06\0\x11\x04\0\x11[method]i2c.write\x01\x12\x01@\x04\x04self\x0a\x07\ -address\x01\x05write\x06\x08read-lenw\0\x0f\x04\0\x16[method]i2c.write-read\x01\x13\ -\x03\x01\x19sketch:embedded/i2c@0.0.0\x05\x01\x02\x03\0\0\x05delay\x02\x03\0\x01\ -\x03i2c\x01B\x08\x02\x03\x02\x01\x02\x04\0\x05delay\x03\0\0\x02\x03\x02\x01\x03\x04\ -\0\x03i2c\x03\0\x02\x01i\x03\x01i\x01\x01@\x02\x0aconnection\x04\x05delay\x05\x01\ -\0\x04\0\x05write\x01\x06\x04\x01\x19sketch:embedded/lcd@0.0.0\x05\x04\x04\x01\x1c\ -sketch:embedded/screen@0.0.0\x04\0\x0b\x0c\x01\0\x06screen\x03\0\0\0G\x09produce\ -rs\x01\x0cprocessed-by\x02\x0dwit-component\x070.201.0\x10wit-bindgen-rust\x060.\ -21.0"; +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 839] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xca\x05\x01A\x02\x01\ +A\x08\x01B\x18\x01{\x04\0\x07address\x03\0\0\x01m\x03\x07address\x04data\x07unkn\ +own\x04\0\x15no-acknowledge-source\x03\0\x02\x01q\x05\x03bus\0\0\x10arbitration-\ +loss\0\0\x0eno-acknowledge\x01\x03\0\x07overrun\0\0\x05other\0\0\x04\0\x0aerror-\ +code\x03\0\x04\x01p}\x01q\x02\x04read\x01w\0\x05write\x01\x06\0\x04\0\x09operati\ +on\x03\0\x07\x04\0\x03i2c\x03\x01\x01h\x09\x01p\x08\x01p\x06\x01j\x01\x0c\x01\x05\ +\x01@\x03\x04self\x0a\x07address\x01\x0aoperations\x0b\0\x0d\x04\0\x17[method]i2\ +c.transaction\x01\x0e\x01j\x01\x06\x01\x05\x01@\x03\x04self\x0a\x07address\x01\x03\ +lenw\0\x0f\x04\0\x10[method]i2c.read\x01\x10\x01j\0\x01\x05\x01@\x03\x04self\x0a\ +\x07address\x01\x04data\x06\0\x11\x04\0\x11[method]i2c.write\x01\x12\x01@\x04\x04\ +self\x0a\x07address\x01\x05write\x06\x08read-lenw\0\x0f\x04\0\x16[method]i2c.wri\ +te-read\x01\x13\x03\x01\x12wasi:i2c/i2c@0.1.0\x05\0\x01B\x04\x04\0\x05delay\x03\x01\ +\x01h\0\x01@\x02\x04self\x01\x02nsy\x01\0\x04\0\x16[method]delay.delay-ns\x01\x02\ +\x03\x01\x14wasi:i2c/delay@0.1.0\x05\x01\x02\x03\0\0\x03i2c\x02\x03\0\x01\x05del\ +ay\x01B\x08\x02\x03\x02\x01\x02\x04\0\x03i2c\x03\0\0\x02\x03\x02\x01\x03\x04\0\x05\ +delay\x03\0\x02\x01i\x01\x01i\x03\x01@\x03\x0aconnection\x04\x05delay\x05\x07mes\ +sages\x01\0\x04\0\x05write\x01\x06\x04\x01\x19sketch:implementation/lcd\x05\x04\x04\ +\x01\x1csketch:implementation/screen\x04\0\x0b\x0c\x01\0\x06screen\x03\0\0\0G\x09\ +producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.201.0\x10wit-bindgen-rus\ +t\x060.21.0"; #[inline(never)] #[doc(hidden)] diff --git a/guest/lcd/src/lib.rs b/guest/lcd/src/lib.rs index 85b6851..27a6556 100644 --- a/guest/lcd/src/lib.rs +++ b/guest/lcd/src/lib.rs @@ -4,11 +4,15 @@ #[allow(warnings)] mod bindings; -use crate::bindings::exports::sketch::embedded::lcd::Guest; -use crate::bindings::sketch::embedded::delay::Delay; -use crate::bindings::sketch::embedded::i2c::I2c; +use crate::bindings::exports::sketch::implementation::lcd::Guest; +use bindings::wasi::i2c::delay::Delay; +use bindings::wasi::i2c::i2c::I2c; + use lol_alloc::{AssumeSingleThreaded, FreeListAllocator}; +extern crate alloc; +use alloc::string::String; + struct Component; const ADDRESS: u16 = 0x27; diff --git a/host/Cargo.lock b/host/Cargo.lock index a34a34d..dda78c8 100644 --- a/host/Cargo.lock +++ b/host/Cargo.lock @@ -153,9 +153,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cap-fs-ext" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e341d15ac1029aadce600be764a1a1edafe40e03cde23285bc1d261b3a4866" +checksum = "769f8cd02eb04d57f14e2e371ebb533f96817f9b2525d73a5c72b61ca7973747" dependencies = [ "cap-primitives", "cap-std", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cap-net-ext" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434168fe6533055f0f4204039abe3ff6d7db338ef46872a5fa39e9d5ad5ab7a9" +checksum = "59ff6d3fb274292a9af283417e383afe6ded1fe66f6472d2c781216d3d80c218" dependencies = [ "cap-primitives", "cap-std", @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "cap-primitives" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe16767ed8eee6d3f1f00d6a7576b81c226ab917eb54b96e5f77a5216ef67abb" +checksum = "90a0b44fc796b1a84535a63753d50ba3972c4db55c7255c186f79140e63d56d0" dependencies = [ "ambient-authority", "fs-set-times", @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "cap-rand" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e5695565f0cd7106bc3c7170323597540e772bb73e0be2cd2c662a0f8fa4ca" +checksum = "4327f08daac33a99bb03c54ae18c8f32c3ba31c728a33ddf683c6c6a5043de68" dependencies = [ "ambient-authority", "rand", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "cap-std" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "593db20e4c51f62d3284bae7ee718849c3214f93a3b94ea1899ad85ba119d330" +checksum = "266626ce180cf9709f317d0bf9754e3a5006359d87f4bf792f06c9c5f1b63c0f" dependencies = [ "cap-primitives", "io-extras", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "cap-time-ext" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03261630f291f425430a36f38c847828265bc928f517cdd2004c56f4b02f002b" +checksum = "e1353421ba83c19da60726e35db0a89abef984b3be183ff6f58c5b8084fcd0c5" dependencies = [ "ambient-authority", "cap-primitives", @@ -258,9 +258,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpp_demangle" -version = "0.3.5" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" dependencies = [ "cfg-if", ] @@ -276,18 +276,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7c0d51205b863591dd1e7aaa0fb69c2ea7bed48ffa63d6c4a848b07a35a732" +checksum = "6a535eb1cf5a6003197dc569320c40c1cb2d2f97ef5d5348eebf067f20957381" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ffb467cbc25543e4c20d2ad669bf8275598047b03c89652ad5fe2a0f47fc0e1" +checksum = "11b5066db32cec1492573827183af2142d2d88fe85a83cfc9e73f0f63d3788d4" dependencies = [ "bumpalo", "cranelift-bforest", @@ -306,33 +306,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7e74aed5c2b91e38d090653506afbd2cd3be1ff70593e2aa6bb82b3c6b77ff" +checksum = "64942e5774308e835fbad4dd25f253105412c90324631910e1ec27963147bddb" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff2dd24cce0775566da85770cb48aa58fef901cf2bff30275b42e7dbe62cbd5" +checksum = "c39c33db9a86dd6d8d04166a10c53deb477aeea3500eaaefca682e4eda9bb986" [[package]] name = "cranelift-control" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8bcf4d5c73bbca309edf3af2839b5218e5c74cfbf22b0ac492af8a1d11120d9" +checksum = "4b7fc4937613aea3156a0538800a17bf56f345a5da2e79ae3df58488c93d867f" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286754159b1a685475d6a0b4710832f950d6f4846a817002e2c23ff001321a65" +checksum = "f85575e79a153ce1ddbfb7fe1813519b4bfe1eb200cc9c8353b45ad123ae4d36" dependencies = [ "serde", "serde_derive", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67150a1fef9857caba710f8c0c8223d640f02c0e5d1ebbfc75ed62912599cb6b" +checksum = "bbc31d6c0ab2249fe0c21e988256b42f5f401ab2673b4fc40076c82a698bdfb9" dependencies = [ "cranelift-codegen", "log", @@ -352,15 +352,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7ceea70d3e0d7f69df7657f99de902e32016731c5a8d2788c1df0215f00952" +checksum = "dc14f37e3314c0e4c53779c2f46753bf242efff76ee9473757a1fff3b495ad37" [[package]] name = "cranelift-native" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707e5d9384ce4fa3c40af1abf4c3ec49857745cced5187593385f4a2c0b95445" +checksum = "2ea5375f76ab31f9800a23fb2b440810286a6f669a3eb467cdd7ff255ea64268" dependencies = [ "cranelift-codegen", "libc", @@ -369,9 +369,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.104.1" +version = "0.106.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d957e3ff2a14c2f974a66c22bfcedcd2bd0272af8dce4236869c3942f5a471" +checksum = "79851dba01b1fa83fad95134aa27beca88dc4b027121d92ab19788582389dc5f" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -379,7 +379,7 @@ dependencies = [ "itertools", "log", "smallvec", - "wasmparser 0.118.2", + "wasmparser", "wasmtime-types", ] @@ -835,9 +835,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -1347,6 +1347,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serialport" version = "4.3.0" @@ -1452,9 +1461,9 @@ dependencies = [ [[package]] name = "system-interface" -version = "0.26.1" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58" +checksum = "9aef1f9d4c1dbdd1cb3a63be9efd2f04d8ddbc919d46112982c76818ffc2f1a7" dependencies = [ "bitflags 2.4.2", "cap-fs-ext", @@ -1525,11 +1534,36 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] @@ -1538,7 +1572,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1641,49 +1674,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi-cap-std-sync" -version = "17.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025e842ba390587e523785ff58bd54fbbf1781b8d3072bc9aba4dc0b809f69da" -dependencies = [ - "anyhow", - "async-trait", - "cap-fs-ext", - "cap-rand", - "cap-std", - "cap-time-ext", - "fs-set-times", - "io-extras", - "io-lifetimes", - "once_cell", - "rustix", - "system-interface", - "tracing", - "wasi-common", - "windows-sys 0.52.0", -] - -[[package]] -name = "wasi-common" -version = "17.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4d4023cc65b3615590d38db0afb79234de09b3bb89cb0d8f83bdee9f5c28a8" -dependencies = [ - "anyhow", - "bitflags 2.4.2", - "cap-rand", - "cap-std", - "io-extras", - "log", - "rustix", - "thiserror", - "tracing", - "wasmtime", - "wiggle", - "windows-sys 0.52.0", -] - [[package]] name = "wasm-bindgen" version = "0.2.91" @@ -1740,37 +1730,18 @@ checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-encoder" -version = "0.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-encoder" -version = "0.41.2" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972f97a5d8318f908dded23594188a90bcd09365986b1163e66d70170e5287ae" +checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" dependencies = [ "leb128", ] [[package]] name = "wasmparser" -version = "0.118.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" -dependencies = [ - "indexmap", - "semver", -] - -[[package]] -name = "wasmparser" -version = "0.121.2" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" +checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708" dependencies = [ "bitflags 2.4.2", "indexmap", @@ -1779,20 +1750,21 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.80" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e73986a6b7fdfedb7c5bf9e7eb71135486507c8fbc4c0c42cffcb6532988b7" +checksum = "a67e66da702706ba08729a78e3c0079085f6bfcb1a62e4799e97bbf728c2c265" dependencies = [ "anyhow", - "wasmparser 0.121.2", + "wasmparser", ] [[package]] name = "wasmtime" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb6aa966be38f613954c3debe7ba6c7a02ffd0537432be438da0b038955cdf" +checksum = "6a08af88fa3d324cc5cf6d388d90ef396a787b3fb4bbd51ba185f8645dc0f02c" dependencies = [ + "addr2line", "anyhow", "async-trait", "bincode", @@ -1800,27 +1772,33 @@ dependencies = [ "cfg-if", "encoding_rs", "fxprof-processed-profile", + "gimli", "indexmap", + "ittapi", "libc", "log", "object", "once_cell", "paste", "rayon", + "rustix", + "semver", "serde", "serde_derive", "serde_json", "target-lexicon", - "wasm-encoder 0.38.1", - "wasmparser 0.118.2", + "wasm-encoder", + "wasmparser", "wasmtime-cache", "wasmtime-component-macro", "wasmtime-component-util", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-fiber", - "wasmtime-jit", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", "wasmtime-runtime", + "wasmtime-slab", "wasmtime-winch", "wat", "windows-sys 0.52.0", @@ -1828,18 +1806,18 @@ dependencies = [ [[package]] name = "wasmtime-asm-macros" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1495ef4d46aec14f967b672e946e391dd8a14a443cda3d5e0779ff67fb6e28d" +checksum = "16cdbfcf28542bcda0b5fd68d44603e53e5ad126cbe7b9f25c130e1249fd8211" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-cache" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2de1b065bdbaca3df9e7e9f70eb129e326a99d971b16d666acd798d98d47635" +checksum = "546b85be1a1d380ba821aeb0252b656359d0ce027b16fef8fc0e2f2b9159e193" dependencies = [ "anyhow", "base64", @@ -1857,9 +1835,9 @@ dependencies = [ [[package]] name = "wasmtime-component-macro" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f19bcff82f81ba0273c0b68f3909977b0dd54489bc86c630d8aad43dca92f3f" +checksum = "0cdcf690257c623506eeec3a502864b282aab0fdfd6981c1ebb63c7e98f4a23a" dependencies = [ "anyhow", "proc-macro2", @@ -1872,15 +1850,15 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af072b7ad5ac5583e1f9e4737ebf88923de564fb5d4ace0ca9b4b720bdf95a1" +checksum = "ab3ae7bf66e2fae1e332ab3634f332d7422e878a6eecc47c8f8f78cc1f24e501" [[package]] name = "wasmtime-cranelift" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df08a8bd9a68732577bee05ac685e4c247238b5e79ad9c062e2dfb4d04dca132" +checksum = "67ea025c969a09117818732fa6f96848e858a7953d4659dab8081a6eea3c0523" dependencies = [ "anyhow", "cfg-if", @@ -1895,7 +1873,7 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser 0.118.2", + "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", "wasmtime-versioned-export-macros", @@ -1903,9 +1881,9 @@ dependencies = [ [[package]] name = "wasmtime-cranelift-shared" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404201c9e669083f189f01337b3ed0aa0eb081157fb4e170bbfe193df9497771" +checksum = "dcd6dd2f8d8d4860b384f61f89b597633a5b5f0943c546210e5084c5d321fe20" dependencies = [ "anyhow", "cranelift-codegen", @@ -1919,22 +1897,25 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e696b4911c9a69c3c2892ec05eb41bb15436d1a46d8830a755c40f5df47546a" +checksum = "7f60f3f717658dd77745de03b750d5852126e9be6dad465848c77f90387c44c9" dependencies = [ "anyhow", + "bincode", + "cpp_demangle", "cranelift-entity", "gimli", "indexmap", "log", "object", + "rustc-demangle", "serde", "serde_derive", "target-lexicon", "thiserror", - "wasm-encoder 0.38.1", - "wasmparser 0.118.2", + "wasm-encoder", + "wasmparser", "wasmprinter", "wasmtime-component-util", "wasmtime-types", @@ -1942,9 +1923,9 @@ dependencies = [ [[package]] name = "wasmtime-fiber" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a39681c1f6f54d1bf7efe5dc829f8d7fc0e2ca12c346fd7a3efbf726e9681d2" +checksum = "bf8cd22ab1041bf0e54b6283e57824557902e4fed8b1f3a7eef29cbaba89eebf" dependencies = [ "anyhow", "cc", @@ -1955,38 +1936,11 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "wasmtime-jit" -version = "17.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c56519882d936c680bd191d58ac04cff071a470eca2dcc664adcd60f986a731" -dependencies = [ - "addr2line", - "anyhow", - "bincode", - "cfg-if", - "cpp_demangle", - "gimli", - "ittapi", - "log", - "object", - "rustc-demangle", - "rustix", - "serde", - "serde_derive", - "target-lexicon", - "wasmtime-environ", - "wasmtime-jit-debug", - "wasmtime-jit-icache-coherence", - "wasmtime-runtime", - "windows-sys 0.52.0", -] - [[package]] name = "wasmtime-jit-debug" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babc65e64ab0dd4e1ce65624db64e24ed0fbdebb16148729173fa0da9f70e53c" +checksum = "8753654f698354950a557d0d0cbdecf356c973659920091cf3d5fada74183e02" dependencies = [ "object", "once_cell", @@ -1996,9 +1950,9 @@ dependencies = [ [[package]] name = "wasmtime-jit-icache-coherence" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ec5b11c12d9acb09612e7ce04c4c8aea3e8dc79b2591ffdead986a5ce8ec49" +checksum = "2796e4b4989db62899d2117e1e0258b839d088c044591b14e3a0396e7b3ae53a" dependencies = [ "cfg-if", "libc", @@ -2007,9 +1961,9 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e1c31bbdf67cb86f149bcead5193749f23f77c93c5244ec9ac8d192f90966c" +checksum = "4bf2b7745df452a4f41b9aab21d3f7ba1347b12da2fdc5241e59306127884a68" dependencies = [ "anyhow", "cc", @@ -2025,7 +1979,7 @@ dependencies = [ "psm", "rustix", "sptr", - "wasm-encoder 0.38.1", + "wasm-encoder", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", @@ -2035,24 +1989,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "wasmtime-slab" +version = "19.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83448ef600ad95977019ebaea84a5516fdbc9561d0a8e26b1e099351f993b527" + [[package]] name = "wasmtime-types" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e799cff634d30fd042db96b417d515e54f903b95f8c1e0ec60e8f604479485" +checksum = "cf6fe7ed3fd18ed4b1e4465fe5c8674acc9f03523fca5b1b9f975b2560cd741b" dependencies = [ "cranelift-entity", "serde", "serde_derive", "thiserror", - "wasmparser 0.118.2", + "wasmparser", ] [[package]] name = "wasmtime-versioned-export-macros" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10fe166d4e4c95d5d80c5b47e1e12256af2099ac525ddb9a19b1aeb8896e5e1" +checksum = "6d6d967f01032da7d4c6303da32f6a00d5efe1bac124b156e7342d8ace6ffdfc" dependencies = [ "proc-macro2", "quote", @@ -2061,9 +2021,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494f99111a165dcddc69aaa5fa23604f49dcfab479a869edd84581abd6ac569b" +checksum = "371d828b6849ea06d598ae7dd1c316e8dd9e99b76f77d93d5886cb25c7f8e188" dependencies = [ "anyhow", "async-trait", @@ -2078,8 +2038,6 @@ dependencies = [ "futures", "io-extras", "io-lifetimes", - "libc", - "log", "once_cell", "rustix", "system-interface", @@ -2087,8 +2045,6 @@ dependencies = [ "tokio", "tracing", "url", - "wasi-cap-std-sync", - "wasi-common", "wasmtime", "wiggle", "windows-sys 0.52.0", @@ -2096,16 +2052,16 @@ dependencies = [ [[package]] name = "wasmtime-winch" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f5d76d399cb4423e6f178bc154a0e1c314711e28dabaa6e757e56628a083ec" +checksum = "eb8b3fcbc455105760e4a2aa8ee3f39b8357183a62201383b3f72d4836ca2be8" dependencies = [ "anyhow", "cranelift-codegen", "gimli", "object", "target-lexicon", - "wasmparser 0.118.2", + "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", "winch-codegen", @@ -2113,9 +2069,9 @@ dependencies = [ [[package]] name = "wasmtime-wit-bindgen" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb3bc92c031cf4961135bffe055a69c1bd67c253dca20631478189bb05ec27b" +checksum = "96326c9800fb6c099f50d1bd2126d636fc2f96950e1675acf358c0f52516cd38" dependencies = [ "anyhow", "heck", @@ -2125,9 +2081,9 @@ dependencies = [ [[package]] name = "wasmtime-wmemcheck" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da08ab734954e16f57be38423b90c25a0b13420e51cbd0a2e37b86a468a988c" +checksum = "36bd91a4dc55af0bf55e9e2ab0ea13724cfb5c5a1acdf8873039769208f59490" [[package]] name = "wast" @@ -2140,31 +2096,31 @@ dependencies = [ [[package]] name = "wast" -version = "71.0.1" +version = "201.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c3ac4354da32688537e8fc4d2fe6c578df51896298cb64727d98088a1fd26" +checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.41.2", + "wasm-encoder", ] [[package]] name = "wat" -version = "1.0.88" +version = "1.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69c36f634411568a2c6d24828b674961e37ea03340fe1d605c337ed8162d901" +checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32" dependencies = [ - "wast 71.0.1", + "wast 201.0.0", ] [[package]] name = "wiggle" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd5b200b5dd3d5d7cc4093166f4f916d2d2839296cf1b1757b9726635f6425c3" +checksum = "ae1136a209614ace00b0c11f04dc7cf42540773be3b22eff6ad165110aba29c1" dependencies = [ "anyhow", "async-trait", @@ -2177,9 +2133,9 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4dc34a2bc1091599de005e9b854cd1a9ea35b16ca51cac2797274c1a2666e06" +checksum = "4c2bd99ce26046f4246d720a4198f6a8fc95bc5da82ae4ef62263e24641c3076" dependencies = [ "anyhow", "heck", @@ -2192,9 +2148,9 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "17.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ba3b37f402a7513b9ed7973a6e907074987b3afdcede98d3d79939b3e76f1b" +checksum = "512d816dbcd0113103b2eb2402ec9018e7f0755202a5b3e67db726f229d8dcae" dependencies = [ "proc-macro2", "quote", @@ -2226,9 +2182,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "0.15.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d921185084e134e897e0e202e129a422306d0f1391954ecf4928d36defa897d" +checksum = "d285c833af9453c037cd220765f86c5c9961e8906a815829107c8801d535b8e4" dependencies = [ "anyhow", "cranelift-codegen", @@ -2236,7 +2192,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "wasmparser 0.118.2", + "wasmparser", "wasmtime-environ", ] @@ -2381,6 +2337,15 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +[[package]] +name = "winnow" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +dependencies = [ + "memchr", +] + [[package]] name = "winx" version = "0.36.3" @@ -2393,9 +2358,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.13.2" +version = "0.201.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08" +checksum = "196d3ecfc4b759a8573bf86a9b3f8996b304b3732e4c7de81655f875f6efdca6" dependencies = [ "anyhow", "id-arena", @@ -2406,6 +2371,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", + "wasmparser", ] [[package]] @@ -2442,20 +2408,19 @@ dependencies = [ [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" dependencies = [ - "libc", "zstd-sys", ] diff --git a/host/Cargo.toml b/host/Cargo.toml index 483037e..1555d13 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" [dependencies] anyhow = "1.0.75" -wasmtime = "17.0.1" -wasmtime-wasi = "17.0.1" +wasmtime = "19.0.0" +wasmtime-wasi = "19.0.0" embedded-hal = "1.0.0" linux-embedded-hal = "0.4.0" i2cdev = "0.6.0" diff --git a/host/src/device.rs b/host/src/device.rs index 9cbf0ef..a099c21 100644 --- a/host/src/device.rs +++ b/host/src/device.rs @@ -1,9 +1,21 @@ -use wasmtime_wasi::preview2::{ResourceTable, WasiCtx, WasiView}; -pub mod screen; -pub mod sensor; +bindgen!({ + path: "../wit", + world: "app", + with: { + "wasi:i2c/delay/delay": Delay, + "wasi:i2c/i2c/i2c": I2c, + } +}); -// Ideally we would like to define the I2C implementation here so that it is shared across devices, -// but this is currently not possible. (see: https://github.com/bytecodealliance/wit-bindgen/issues/546#issuecomment-1489213305) +use linux_embedded_hal::I2cdev; +use wasi::i2c::*; +use wasmtime::{component::bindgen, Result}; +use wasmtime::{ + component::{Component, Linker}, + Engine, Store, +}; +use wasmtime_wasi::WasiView; +use wasmtime_wasi::{ResourceTable, WasiCtx}; struct HostComponent { table: ResourceTable, @@ -16,16 +28,123 @@ pub struct MyState { // Needed for wasmtime_wasi::preview2 impl WasiView for MyState { - fn table(&self) -> &ResourceTable { - &self.host.table - } - fn table_mut(&mut self) -> &mut ResourceTable { + fn table(&mut self) -> &mut ResourceTable { &mut self.host.table } - fn ctx(&self) -> &WasiCtx { - &self.wasi - } - fn ctx_mut(&mut self) -> &mut WasiCtx { + fn ctx(&mut self) -> &mut WasiCtx { &mut self.wasi } } + +pub struct Delay; +pub struct I2c(I2cdev); + +impl i2c::Host for HostComponent {} +impl i2c::HostI2c for HostComponent { + fn transaction( + &mut self, + self_: wasmtime::component::Resource, + address: i2c::Address, + operations: Vec, + ) -> wasmtime::Result>, i2c::ErrorCode>> { + todo!() + } + + fn read( + &mut self, + self_: wasmtime::component::Resource, + address: i2c::Address, + len: u64, + ) -> wasmtime::Result, i2c::ErrorCode>> { + let self_ = self.table.get_mut(&self_)?; + let mut data = vec![0; len.try_into().unwrap()]; + + match embedded_hal::i2c::I2c::read(&mut self_.0, address, &mut data) { + Ok(()) => Ok(Ok(data)), + Err(_) => Ok(Err(i2c::ErrorCode::Other)), + } + } + + fn write( + &mut self, + self_: wasmtime::component::Resource, + address: i2c::Address, + data: Vec, + ) -> wasmtime::Result> { + let self_ = self.table.get_mut(&self_)?; + + match embedded_hal::i2c::I2c::write(&mut self_.0, address, &data) { + Ok(()) => Ok(Ok(())), + Err(_) => Ok(Err(i2c::ErrorCode::Other)), + } + } + + fn write_read( + &mut self, + self_: wasmtime::component::Resource, + address: i2c::Address, + write: Vec, + read_len: u64, + ) -> wasmtime::Result, i2c::ErrorCode>> { + let self_ = self.table.get_mut(&self_)?; + let mut data = vec![0; read_len.try_into().unwrap()]; + + match embedded_hal::i2c::I2c::write_read(&mut self_.0, address, &write, &mut data) { + Ok(()) => Ok(Ok(data)), + Err(_) => Ok(Err(i2c::ErrorCode::Other)), + } + } + + fn drop(&mut self, self_: wasmtime::component::Resource) -> wasmtime::Result<()> { + self.table.delete(self_)?; + Ok(()) + } +} + +impl delay::Host for HostComponent {} +impl delay::HostDelay for HostComponent { + fn delay_ns( + &mut self, + self_: wasmtime::component::Resource, + ns: u32, + ) -> wasmtime::Result<()> { + let _self_ = self.table.get_mut(&self_)?; + std::thread::sleep(std::time::Duration::from_nanos(ns.into())); + Ok(()) + } + + fn drop(&mut self, self_: wasmtime::component::Resource) -> wasmtime::Result<()> { + self.table.delete(self_)?; + Ok(()) + } +} + +pub fn run( + mut linker: Linker, + engine: Engine, + component: Component, + wasi: WasiCtx, +) -> Result { + // Binding host + wasi::i2c::i2c::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?; + + let mut state = MyState { + host: HostComponent { + table: ResourceTable::new(), + }, + wasi, + }; + + let i2cdev = I2cdev::new(format!("/dev/i2c-{}", 1))?; + + let connection = state.host.table.push(I2c(i2cdev))?; + let delay = state.host.table.push(Delay)?; + + let mut store = Store::new(&engine, state); + + let (bindings, _) = App::instantiate(&mut store, &component, &linker)?; + + Ok(bindings + .interface0 + .call_get_temperature(&mut store, connection)??) +} diff --git a/host/src/device/screen.rs b/host/src/device/screen.rs deleted file mode 100644 index 90fbb02..0000000 --- a/host/src/device/screen.rs +++ /dev/null @@ -1,136 +0,0 @@ -use crate::screen::sketch::embedded::{delay, i2c}; -use linux_embedded_hal::I2cdev; -use wasmtime::{ - component::{bindgen, Component, Linker}, - Engine, Result, Store, -}; -use wasmtime_wasi::preview2::{ResourceTable, WasiCtx}; - -use super::{HostComponent, MyState}; - -bindgen!({ - path: "../wit", - world: "screen", - with: { - "sketch:embedded/delay/delay": Delay, - "sketch:embedded/i2c/i2c": I2c, - } -}); - -pub struct Delay; -pub struct I2c(I2cdev); - -impl i2c::Host for HostComponent {} -impl i2c::HostI2c for HostComponent { - fn transaction( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - operations: Vec, - ) -> wasmtime::Result>, i2c::ErrorCode>> { - todo!() - } - - fn read( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - len: u64, - ) -> wasmtime::Result, i2c::ErrorCode>> { - let self_ = self.table.get_mut(&self_)?; - let mut data = vec![0; len.try_into().unwrap()]; - - match embedded_hal::i2c::I2c::read(&mut self_.0, address, &mut data) { - Ok(()) => Ok(Ok(data)), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn write( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - data: Vec, - ) -> wasmtime::Result> { - let self_ = self.table.get_mut(&self_)?; - - match embedded_hal::i2c::I2c::write(&mut self_.0, address, &data) { - Ok(()) => Ok(Ok(())), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn write_read( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - write: Vec, - read_len: u64, - ) -> wasmtime::Result, i2c::ErrorCode>> { - let self_ = self.table.get_mut(&self_)?; - let mut data = vec![0; read_len.try_into().unwrap()]; - - match embedded_hal::i2c::I2c::write_read(&mut self_.0, address, &write, &mut data) { - Ok(()) => Ok(Ok(data)), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn drop(&mut self, self_: wasmtime::component::Resource) -> wasmtime::Result<()> { - self.table.delete(self_)?; - Ok(()) - } -} - -impl delay::Host for HostComponent {} -impl delay::HostDelay for HostComponent { - fn delay_ns( - &mut self, - self_: wasmtime::component::Resource, - ns: u32, - ) -> wasmtime::Result<()> { - let _self_ = self.table.get_mut(&self_)?; - std::thread::sleep(std::time::Duration::from_nanos(ns.into())); - Ok(()) - } - - fn drop(&mut self, self_: wasmtime::component::Resource) -> wasmtime::Result<()> { - self.table.delete(self_)?; - Ok(()) - } -} - -pub fn run( - mut linker: Linker, - engine: Engine, - component: Component, - wasi: WasiCtx, -) -> Result<()> { - // Binding host - Screen::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?; - - let mut state = MyState { - host: HostComponent { - table: ResourceTable::new(), - }, - wasi, - }; - - let i2cdev = I2cdev::new(format!("/dev/i2c-{}", 1))?; - - let connection = state.host.table.push(I2c(i2cdev))?; - let delay = state.host.table.push(Delay)?; - - let mut store = Store::new(&engine, state); - - let (bindings, _) = Screen::instantiate(&mut store, &component, &linker)?; - - let res = - bindings - .sketch_embedded_lcd() - .call_write(&mut store, connection, delay, "hello world")?; - - println!("{:?}", res); - - Ok::<(), anyhow::Error>(()) -} diff --git a/host/src/device/sensor.rs b/host/src/device/sensor.rs deleted file mode 100644 index 5b34db0..0000000 --- a/host/src/device/sensor.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::sensor::sketch::embedded::i2c; -use linux_embedded_hal::I2cdev; -use wasmtime::{ - component::{bindgen, Component, Linker}, - Engine, Result, Store, -}; -use wasmtime_wasi::preview2::{ResourceTable, WasiCtx}; - -use super::{HostComponent, MyState}; - -bindgen!({ - path: "../wit", - world: "sensor", - with: { - "sketch:embedded/delay/delay": Delay, - "sketch:embedded/i2c/i2c": I2c, - } -}); -#[cfg(target_arch = "wasm32")] -pub struct I2c(I2cdev); - -impl i2c::Host for HostComponent {} -impl i2c::HostI2c for HostComponent { - fn transaction( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - operations: Vec, - ) -> wasmtime::Result>, i2c::ErrorCode>> { - todo!() - } - - fn read( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - len: u64, - ) -> wasmtime::Result, i2c::ErrorCode>> { - let self_ = self.table.get_mut(&self_)?; - let mut data = vec![0; len.try_into().unwrap()]; - - match embedded_hal::i2c::I2c::read(&mut self_.0, address, &mut data) { - Ok(()) => Ok(Ok(data)), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn write( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - data: Vec, - ) -> wasmtime::Result> { - let self_ = self.table.get_mut(&self_)?; - - match embedded_hal::i2c::I2c::write(&mut self_.0, address, &data) { - Ok(()) => Ok(Ok(())), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn write_read( - &mut self, - self_: wasmtime::component::Resource, - address: i2c::Address, - write: Vec, - read_len: u64, - ) -> wasmtime::Result, i2c::ErrorCode>> { - let self_ = self.table.get_mut(&self_)?; - let mut data = vec![0; read_len.try_into().unwrap()]; - - match embedded_hal::i2c::I2c::write_read(&mut self_.0, address, &write, &mut data) { - Ok(()) => Ok(Ok(data)), - Err(_) => Ok(Err(i2c::ErrorCode::Other)), - } - } - - fn drop(&mut self, self_: wasmtime::component::Resource) -> wasmtime::Result<()> { - self.table.delete(self_)?; - Ok(()) - } -} - -pub fn run( - mut linker: Linker, - engine: Engine, - component: Component, - wasi: WasiCtx, -) -> Result<()> { - // Binding host - Sensor::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?; - - let mut state = MyState { - host: HostComponent { - table: ResourceTable::new(), - }, - wasi, - }; - - let i2cdev_1 = I2cdev::new(format!("/dev/i2c-{}", 1))?; - let i2cdev_2 = I2cdev::new(format!("/dev/i2c-{}", 1))?; - - let connection_1 = state.host.table.push(I2c(i2cdev_1))?; - let connection_2 = state.host.table.push(I2c(i2cdev_2))?; - - let mut store = Store::new(&engine, state); - - let (bindings, _) = Sensor::instantiate(&mut store, &component, &linker)?; - - let sensor = bindings.sketch_embedded_hts(); - let temperature = sensor.call_get_temperature(&mut store, connection_1)?; - println!("{}", temperature?); - - let humidity = sensor.call_get_humidity(&mut store, connection_2)?; - println!("{}", humidity?); - - Ok::<(), anyhow::Error>(()) -} diff --git a/host/src/main.rs b/host/src/main.rs index 08de4f3..b460564 100644 --- a/host/src/main.rs +++ b/host/src/main.rs @@ -1,12 +1,10 @@ mod device; -use device::screen; -use device::sensor; use wasmtime::{ component::{Component, Linker}, Config, Engine, Result, }; -use wasmtime_wasi::preview2::WasiCtxBuilder; +use wasmtime_wasi::WasiCtxBuilder; fn main() -> Result<(), anyhow::Error> { let engine = Engine::new(Config::new().wasm_component_model(true))?; @@ -14,29 +12,18 @@ fn main() -> Result<(), anyhow::Error> { let mut linker = Linker::new(&engine); // Bind wasi commmand world - wasmtime_wasi::preview2::command::sync::add_to_linker(&mut linker)?; + wasmtime_wasi::command::sync::add_to_linker(&mut linker)?; let wasi = WasiCtxBuilder::new() .inherit_stdout() .inherit_stdio() .build(); - let run_sensor = true; - let component = Component::from_file( - &engine, - if run_sensor { - "../hat.wasm" - } else { - "../lcd.wasm" - }, - )?; - - // TODO: Choose which one to run via a commandline argument - if run_sensor { - sensor::run(linker, engine, component, wasi)?; - } else { - screen::run(linker, engine, component, wasi)?; - } + let component = Component::from_file(&engine, "hat.wasm")?; + + let res = device::run(linker, engine, component, wasi)?; + + println!("{:?}", res); Ok(()) } diff --git a/wit/deps.lock b/wit/deps.lock new file mode 100644 index 0000000..aea53c8 --- /dev/null +++ b/wit/deps.lock @@ -0,0 +1,4 @@ +[i2c] +url = "https://github.com/Zelzahn/wasi-i2c/archive/main.tar.gz" +sha256 = "d88b22292cee30ebca4598d209c1a273afc81c10cf33def92316b3eb94a4f487" +sha512 = "22505dba5b124e31a0d30fbdc80454e9c31e5766c275cbd40b32aa3412cf6aae9d66a4a366e67dad170afd112001685a9182949a70ace7aeee52137bbc1a0673" diff --git a/wit/deps.toml b/wit/deps.toml new file mode 100644 index 0000000..94e387a --- /dev/null +++ b/wit/deps.toml @@ -0,0 +1 @@ +i2c = "https://github.com/Zelzahn/wasi-i2c/archive/main.tar.gz" diff --git a/wit/deps/i2c/delay.wit b/wit/deps/i2c/delay.wit new file mode 100644 index 0000000..e29fc1d --- /dev/null +++ b/wit/deps/i2c/delay.wit @@ -0,0 +1,12 @@ +package wasi:i2c@0.1.0; + +/// Delays. +interface delay { + /// Delay with up to nanosecond precision. + resource delay { + /// Pauses execution for at minimum `ns` nanoseconds. Pause can be + /// longer if the implementation requires it due to precision/timing + /// issues. + delay-ns: func(ns: u32); + } +} \ No newline at end of file diff --git a/wit/deps/i2c/i2c.wit b/wit/deps/i2c/i2c.wit new file mode 100644 index 0000000..217e1b1 --- /dev/null +++ b/wit/deps/i2c/i2c.wit @@ -0,0 +1,82 @@ +package wasi:i2c@0.1.0; + +/// Inter-Integrated Circuit (I²C) API that is based upon [hello-embedded] and [embedded-hal]. +/// +/// [hello-embedded]: https://github.com/sunfishcode/hello-embedded/tree/main +/// [embedded-hal]: https://github.com/rust-embedded/embedded-hal +interface i2c { + /// An address value, in either 7-bit or 10-bit form, depending on the device. + type address = u16; + + /// Operation errors. + variant error-code { + /// Bus error occurred. e.g. A START or a STOP condition is detected and + /// is not located after a multiple of 9 SCL clock pulses. + bus, + + /// The arbitration was lost, e.g. electrical problems with the clock signal. + arbitration-loss, + + /// A bus operation was not acknowledged, e.g. due to the addressed + /// device not being available on the bus or the device not being ready + /// to process requests at the moment. + no-acknowledge(no-acknowledge-source), + + /// The peripheral receive buffer was overrun. + overrun, + + /// A different error occurred. + other, + } + + /// No-acknowledge error source. + /// + /// In cases where it is possible, a device should indicate if a no + /// acknowledge response was received to an address versus a no acknowledge + /// to a data byte. Where it is not possible to differentiate, Unknown + /// should be indicated. + enum no-acknowledge-source { + /// The device did not acknowledge its address. The device may be + /// missing. + address, + + /// The device did not acknowledge the data. It may not be ready to + /// process requests at the moment. + data, + + /// Either the device did not acknowledge its address or the data, but + /// it is unknown which. + unknown, + } + + /// An operation used by the `transaction` method. + variant operation { + /// Read the give number of bytes. + read(u64), + + /// Write the given bytes. + write(list) + } + + resource i2c { + /// Execute the provided `operation`s on the I²C bus. + transaction: func( + address: address, + operations: list + ) -> result>, error-code>; + + /// Reads `len` bytes from address `address`. + read: func(address: address, len: u64) -> result, error-code>; + + /// Writes bytes to target with address `address`. + write: func(address: address, data: list) -> result<_, error-code>; + + /// Writes bytes to address `address` and then reads `read-len` bytes + /// in a single transaction. + write-read: func( + address: address, + write: list, + read-len: u64, + ) -> result, error-code>; + } +} diff --git a/wit/deps/i2c/world.wit b/wit/deps/i2c/world.wit new file mode 100644 index 0000000..9f0f99a --- /dev/null +++ b/wit/deps/i2c/world.wit @@ -0,0 +1,6 @@ +package wasi:i2c@0.1.0; + +world imports { + import i2c; + import delay; +} diff --git a/wit/device.wit b/wit/device.wit index 1e32166..4546ede 100644 --- a/wit/device.wit +++ b/wit/device.wit @@ -1,32 +1,36 @@ -package sketch:embedded@0.0.0; - -interface lcd { - use delay.{delay}; - use i2c.{i2c}; - - write: func(connection: i2c, delay: delay, message: string); -} +package sketch:implementation; interface hts { - use i2c.{i2c, error-code}; + use wasi:i2c/i2c@0.1.0.{i2c, error-code}; get-temperature: func(connection: i2c) -> result; get-humidity: func(connection: i2c) -> result; } -world connection { - import i2c; +interface lcd { + use wasi:i2c/i2c@0.1.0.{i2c}; + use wasi:i2c/delay@0.1.0.{delay}; + + write: func(connection: i2c, delay: delay, message: string); } world sensor { - include connection; + import wasi:i2c/i2c@0.1.0; export hts; } world screen { - import delay; - include connection; + // As we need both i2c and delay we just include the imports + include wasi:i2c/imports@0.1.0; export lcd; +} + +/// This is a wrapper around devices to give a shared interface to the host +world app { + include wasi:i2c/imports@0.1.0; + + include sensor; + // include screen; } \ No newline at end of file diff --git a/wit/embedded.wit b/wit/embedded.wit deleted file mode 100644 index ab6ae15..0000000 --- a/wit/embedded.wit +++ /dev/null @@ -1,360 +0,0 @@ -/// Embedded APIs. -/// -/// These APIs are based on [embedded-hal]. -/// -/// TODO? -/// - embedded-hal-bus: Sharing SPI and I2C buses -/// - embedded-can: Controller Area Network (CAN) -/// -/// [embedded-hal]: https://crates.io/crates/embedded-hal -package sketch:embedded@0.0.0; - -/// Inter-Integrated Circuit (I²C). -interface i2c { - /// An address value, in either 7-bit or 10-bit form, depending on the device. - type address = u16; - - /// Operation errors. - variant error-code { - /// Bus error occurred. e.g. A START or a STOP condition is detected and - /// is not located after a multiple of 9 SCL clock pulses. - bus, - - /// The arbitration was lost, e.g. electrical problems with the clock signal. - arbitration-loss, - - /// A bus operation was not acknowledged, e.g. due to the addressed - /// device not being available on the bus or the device not being ready - /// to process requests at the moment. - no-acknowledge(no-acknowledge-source), - - /// The peripheral receive buffer was overrun. - overrun, - - /// A different error occurred. - other, - } - - /// No-acknowledge error source. - /// - /// In cases where it is possible, a device should indicate if a no - /// acknowledge response was received to an address versus a no acknowledge - /// to a data byte. Where it is not possible to differentiate, Unknown - /// should be indicated. - enum no-acknowledge-source { - /// The device did not acknowledge its address. The device may be - /// missing. - address, - - /// The device did not acknowledge the data. It may not be ready to - /// process requests at the moment. - data, - - /// Either the device did not acknowledge its address or the data, but - /// it is unknown which. - unknown, - } - - /// An operation used by the `transaction` method. - variant operation { - /// Read the given number of bytes. - read(u64), - - /// Write the given bytes. - write(list) - } - - resource i2c { - /// Execute the provided `operation`s on the I²C bus. - transaction: func( - address: address, - operations: list - ) -> result>, error-code>; - - /// Reads `len` bytes from address `address`. - read: func(address: address, len: u64) -> result, error-code>; - - /// Writes bytes to target with address `address`. - write: func(address: address, data: list) -> result<_, error-code>; - - /// Writes bytes to address `address` and then reads `read-len` bytes - /// in a single transaction. - write-read: func( - address: address, - write: list, - read-len: u64, - ) -> result, error-code>; - } -} - -/// Digital I/O, for example GPIO pins. -interface digital { - /// Operation errors. - enum error-code { - /// An error occurred. - other, - } - - /// Digital output pin state. - enum pin-state { - low, - high, - } - - /// Single digital input pin. - resource input-pin { - /// Is the input pin low? - is-low: func() -> result; - - /// Is the input pin high? - is-high: func() -> result; - - /// Wait until the pin is high. If it is already high, resolve - /// immediately. - wait-for-high: func() -> result<_, error-code>; - - /// Wait until the pin is low. If it is already low, resolve - /// immediately. - wait-for-low: func() -> result<_, error-code>; - - /// Wait for the pin to undergo a transition from low to high. - /// - /// If the pin is already high, this does *not* resolve immediately, - /// it’ll wait for the pin to go low and then high again. - wait-for-rising-edge: func() -> result<_, error-code>; - - /// Wait for the pin to undergo a transition from high to low. - /// - /// If the pin is already low, this does *not* return immediately, - /// it’ll wait for the pin to go high and then low again. - wait-for-falling-edge: func() -> result<_, error-code>; - - /// Wait for the pin to undergo any transition, i.e low to high OR high - /// to low. - wait-for-any-edge: func() -> result<_, error-code>; - } - - /// Single digital input pin. - resource output-pin { - /// Drives the pin low. - set-low: func() -> result<_, error-code>; - - /// Drives the pin high. - set-high: func() -> result<_, error-code>; - - /// Drives the pin high or low depending on the provided value. - set-state: func(state: pin-state) -> result<_, error-code>; - } - - /// Push-pull output pin that can read its output state. - resource stateful-output-pin { - /// Is the pin in drive high mode? - is-set-high: func() -> result; - - /// Is the pin in drive low mode? - is-set-low: func() -> result; - - /// Toggle pin output. - toggle: func() -> result<_, error-code>; - } -} - -/// Delays. -interface delay { - /// Delay with up to nanosecond precision. - resource delay { - /// Pauses execution for at minimum `ns` nanoseconds. Pause can be - /// longer if the implementation requires it due to precision/timing - /// issues. - delay-ns: func(ns: u32); - } -} - -/// Pulse Width Modulation (PWM). -interface pwm { - /// Operation errors. - enum error-code { - /// An error occurred. - other, - } - - /// Single PWM channel / pin. - resource set-duty-cycle { - /// Get the maximum duty cycle value. - /// - /// This value corresponds to a 100% duty cycle. - max-duty-cycle: func() -> u16; - - /// Set the duty cycle to `duty / max_duty`. - /// - /// Traps if the duty cycle value is greater than the maximum duty - /// cycle value, as reported by `max-duty-cycle`. - set-duty-cycle: func(duty: u16) -> result<_, error-code>; - } -} - -/// Serial Peripheral Interface (SPI) controller mode. -/// -/// This specifiation follows [OSHWA's recommended terminology]. -/// -/// [OSHWA's recommended terminology]: https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/ -interface spi { - /// SPI mode. - record mode { - /// Clock polarity. - polarity: polarity, - - // Clock phase. - phase: phase, - } - - /// Clock polarity. - enum polarity { - /// Clock signal low when idle. - idle-low, - - /// Clock signal high when idle. - idle-high, - } - - /// Clock phase. - enum phase { - /// Data in “captured” on the first clock transition. - capture-on-first-transition, - - /// Data in “captured” on the second clock transition. - capture-on-second-transition, - } - - /// SPI error kind. - enum error-code { - /// The peripheral receive buffer was overrun. - overrun, - - /// Multiple devices on the SPI bus are trying to drive the chip - /// select pin. - mode-fault, - - /// Received data does not conform to the peripheral configuration. - frame-format, - - /// An error occurred while asserting or deasserting the - /// Chip Select pin. - chip-select-fault, - - /// A different error occurred. - other, - } - - /// Word size. - /// - /// TODO: Support up to `u16` word sizes? - type word = u8; - - /// SPI transaction operation. - /// - /// This allows composition of SPI operations into a single bus transaction. - variant operation { - /// Read data. - read(u64), - - /// Write data from the provided list, discarding read data. - write(list), - - /// Read data, while writing data from the buffer. - transfer(tuple>), - - /// Delay for at least the specified number of nanoseconds. - delay-ns(u32), - } - - /// Helper for CPOL = 0, CPHA = 0. - mode0: func() -> mode; - - /// Helper for CPOL = 0, CPHA = 1. - mode1: func() -> mode; - - /// Helper for CPOL = 1, CPHA = 0. - mode2: func() -> mode; - - /// Helper for CPOL = 1, CPHA = 1. - mode3: func() -> mode; - - /// SPI bus. - /// - /// `bus` represents exclusive ownership over the whole SPI bus, with - /// serial clock (SCK), peripheral in/controller out (PICO), and - /// peripheral out/controller in (POCI) pins. - resource bus { - /// Read words from the peripheral. - /// - /// The word value sent on PICO during reading is - /// implementation-defined, typically 0x00, 0xFF, or configurable. - /// - /// Implementations are allowed to return before the operation is complete. - read: func(len: u64) -> result, error-code>; - - /// Write `words` to the peripheral, ignoring all the incoming words. - /// - /// Implementations are allowed to return before the operation is complete. - write: func(words: list) -> result<_, error-code>; - - /// Write and read simultaneously. `write` is written to the peripheral - /// on PICO and words received on POCI are returned. - /// - /// It is allowed for `read-len` and `write`'s length to be different, - /// even zero length. The transfer runs for `max(read-len, write.len())` - /// words. If `read-len` is shorter, incoming words after `read-len` has - /// been filled will be discarded. If `write` is shorter, the value of - /// words sent in PICO after all `write` has been sent is - /// implementation-defined, typically `0x00`, `0xFF`, or configurable. - /// - /// Implementations are allowed to return before the operation is complete. - transfer: func( - read-len: u64, - write: list - ) -> result, error-code>; - - /// Wait until all operations have completed and the bus is idle. - flush: func() -> result<_, error-code>; - } - - /// SPI device. - /// - /// `device` represents ownership over a single SPI device on a (possibly - /// shared) bus, selected with a CS (Chip Select) pin. - resource device { - /// Perform a transaction against the device. - /// - /// - Locks the bus - /// - Asserts the CS (Chip Select) pin. - /// - Performs all the operations. - /// - Flushes the bus. - /// - Deasserts the CS pin. - /// - Unlocks the bus. - /// - /// The locking mechanism is implementation-defined. The only - /// requirement is it must prevent two transactions from executing - /// concurrently against the same bus. Examples of implementations are: - /// critical sections, blocking mutexes, returning an error or - /// panicking if the bus is already busy. On bus errors the - /// implementation should try to deassert CS. If an error occurs while - /// deasserting CS the bus error should take priority as the return - /// value. - transaction: func( - operations: list - ) -> result>, error-code>; - - /// Do a read within a transaction. - read: func(len: u64) -> result, error-code>; - - /// Do a write within a transaction. - write: func(buf: list) -> result<_, error-code>; - - /// Do a transfer within a transaction. - transfer: func( - read-len: u64, - write: list - ) -> result, error-code>; - } -}