diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb9f6c5..0c20dbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,25 +9,29 @@ on: - cron: '50 4 * * *' workflow_dispatch: -env: - rust_toolchain: nightly - jobs: compile: name: Compile runs-on: ubuntu-latest + + strategy: + matrix: + rust_toolchain: + - nightly + - 1.83 # MSRV + steps: - name: Setup | Checkout uses: actions/checkout@v2 - name: Setup | Rust uses: actions-rs/toolchain@v1 with: - toolchain: ${{ env.rust_toolchain }} + toolchain: ${{ matrix.rust_toolchain }} components: rustfmt, clippy - name: Setup | Std - run: rustup component add rust-src --toolchain ${{ env.rust_toolchain }}-x86_64-unknown-linux-gnu + run: rustup component add rust-src --toolchain ${{ matrix.rust_toolchain }}-x86_64-unknown-linux-gnu - name: Setup | Set default toolchain - run: rustup default ${{ env.rust_toolchain }} + run: rustup default ${{ matrix.rust_toolchain }} - name: Build | Fmt Check run: cargo fmt -- --check - name: Build | Clippy diff --git a/Cargo.toml b/Cargo.toml index 86ae014..cbe91be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "async-io-mini" -version = "0.2.0" +version = "0.3.0" authors = ["Stjepan Glavina ", "Ivan Markov"] edition = "2021" -rust-version = "1.77" +rust-version = "1.83" description = "Async I/O fork for embedded systems" license = "Apache-2.0 OR MIT" repository = "https://github.com/ivmarkov/async-io-mini" @@ -13,7 +13,7 @@ exclude = ["/.*"] [features] default = ["futures-io", "futures-lite", "embassy-time"] -embassy-time = ["embassy-time-driver", "embassy-time-queue-driver", "dep:embassy-time"] +embassy-time = ["embassy-time-driver", "dep:embassy-time"] [dependencies] libc = "0.2" @@ -22,14 +22,14 @@ heapless = "0.8" log = { version = "0.4", default-features = false } futures-io = { version = "0.3", default-features = false, optional = true, features = ["std"] } futures-lite = { version = "2", default-features = false, optional = true } -embassy-time-driver = { version = "0.1", optional = true } -embassy-time-queue-driver = { version = "0.1", optional = true } -embassy-time = { version = "0.3", optional = true } +embassy-time-driver = { version = "0.2", optional = true } +embassy-time = { version = "0.4", optional = true } [dev-dependencies] futures-io = "0.3" futures-lite = "2" -embassy-time = { version = "0.3", features = ["std", "generic-queue"] } +embassy-time = { version = "0.4", features = ["std"] } +embassy-time-queue-utils = { version = "0.1", features = ["generic-queue-64"] } async-channel = "2" env_logger = "0.10" diff --git a/README.md b/README.md index eab2d3b..d732d45 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This crate is a fork of the splendid [`async-io`](https://github.com/smol-rs/asy ## How to use? -`async-io-mini` is a drop-in, API-compatible replacement for the `Async` and `Timer` types from `async-io`. +`async-io-mini` is an API-compatible replacement for the `Async` and `Timer` types from `async-io`. So either: * Just replace all `use async_io` occurances in your crate with `use async_io_mini` @@ -19,6 +19,8 @@ So either: * `async-io = "..."` * with `async-io = { package = "async-io-mini", ... }` +Additionally, you need to provide an `embassy-time-driver` implementation. This is either done by the HAL of your MCU, or `embassy-time` provides you with a `std`-specific implementation. If you are not using `embassy-executor`, you will also need to select one of the `embassy-time/generic-queue-*` features. + ## Justification While `async-io` supports a ton of operating systems - _including ESP-IDF for the Espressif MCU chips_ - it does have a non-trivial memory consumption in the hidden thread named `async-io`. Since its hidden `Reactor` object is initialized lazily, it so happens that it is first allocated on-stack, and then it is moved into the static context. This requires the `async-io` thread (as well as _any_ thread from where you are polling sockets) to have at least 8K stack, which - by MCU standards! - is relatively large if you are memory-constrained. @@ -39,7 +41,7 @@ Further, `async-io` has a non-trivial set of dependencies (again - for MCUs; for ## Enhancements -The `Timer` type of `async_io_mini` is based on the `embassy-time` crate, and as such should offer a higher resolution on embedded operating systems like the ESP-IDF than what can be normally achieved by implementing timers using the `timeout` parameter of the `select` syscall (as `async-io` does). +The `Timer` type of `async_io_mini` is based on the `embassy-time` crate, and as such should offer a higher resolution on embedded operating systems like the ESP-IDF than what can be normally achieved by implementing timers using the `timeout` parameter of the `select` syscall (as `async-io` does). The reason for this is that on the ESP-IDF, the `timeout` parameter of `select` provides a resolution of 10ms (one FreeRTOS sys-tick), while `embassy-time` is implemented using the [ESP-IDF Timer service](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/esp_timer.html), which provides resolutions up to 1 microsecond. diff --git a/src/timer.rs b/src/timer.rs index 4372e8a..ba27642 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -283,7 +283,7 @@ impl Timer { self.period = Duration::MAX; if let Some(waker) = self.waker.as_ref() { - embassy_time_queue_driver::schedule_wake(ticks, waker); + embassy_time_driver::schedule_wake(ticks, waker); } } else { self.set_never(); @@ -347,7 +347,7 @@ impl Timer { self.period = period; if let Some(waker) = self.waker.as_ref() { - embassy_time_queue_driver::schedule_wake(ticks, waker); + embassy_time_driver::schedule_wake(ticks, waker); } } else { // Overflow to never going off. @@ -375,7 +375,7 @@ impl Timer { .unwrap_or(true) { self.waker = Some(cx.waker().clone()); - embassy_time_queue_driver::schedule_wake(ticks, cx.waker()); + embassy_time_driver::schedule_wake(ticks, cx.waker()); } } else { self.set_never();