diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d91586..71d153a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.1] - 2023-11-09 +* Update to heapless 0.8, and use heapless `MpMcQueue` for targets that do not have atomics, as `crossbeam` does not support such targets yet + ## [0.4.0] - 2023-10-17 * Crate goals clarified * Crate redesigned to follow the API of `async-executor` diff --git a/Cargo.toml b/Cargo.toml index b154025..d8a4083 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "edge-executor" -version = "0.4.0" +version = "0.4.1" authors = ["Ivan Markov "] edition = "2021" categories = ["embedded", "hardware-support"] @@ -10,20 +10,16 @@ repository = "https://github.com/ivmarkov/edge-executor" license = "MIT OR Apache-2.0" readme = "README.md" -[patch.crates-io] -heapless = { git = "https://github.com/rust-embedded/heapless" } -crossbeam-utils = { git = "https://github.com/crossbeam-rs/crossbeam" } - [features] default = ["std"] std = ["futures-lite/std", "once_cell/std"] -critical-section = ["once_cell/critical-section"] -portable-atomic = ["dep:portable-atomic", "portable-atomic-util", "heapless?/portable-atomic", "atomic-waker/portable-atomic", "async-task/portable-atomic"] +critical-section = ["once_cell/critical-section", "portable-atomic?/critical-section"] +portable-atomic = ["heapless", "dep:portable-atomic", "portable-atomic-util", "heapless?/portable-atomic", "atomic-waker/portable-atomic", "async-task/portable-atomic"] unbounded = [] [dependencies] heapless = { version = "0.8", default-features = false, optional = true } -portable-atomic = { version = "1.4", features = ["critical-section"], optional = true } +portable-atomic = { version = "1.4", optional = true } portable-atomic-util = { version = "0.1", default-features = false, features = ["alloc"], optional = true } crossbeam-queue = { version = "0.3", default-features = false, features = ["alloc"] } async-task = { version = "4.4.5", default-features = false } diff --git a/README.md b/README.md index 1a22483..0c2bed2 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ This crate ships a minimal async executor suitable for microcontrollers and embe A `no_std` drop-in replacement for [smol](https://github.com/smol-rs/smol)'s [async-executor](https://github.com/smol-rs/async-executor), with the implementation being a thin wrapper around [smol](https://github.com/smol-rs/smol)'s [async-task](https://github.com/smol-rs/async-task) as well. +## Examples + ```rust // ESP-IDF example, local execution, local borrows. // With STD enabled, you can also just use `edge_executor::block_on` @@ -92,22 +94,27 @@ fn main() { } ``` -**Highlights** +## Highlights - `no_std` (but does need `alloc`): - The executor uses allocations in a controlled way: only when a new task is being spawn, as well as during the construction of the executor itself; - For a `no_std` *and* "no_alloc" executor, look at [embassy-executor](https://github.com/embassy-rs/embassy/tree/main/embassy-executor), which statically pre-allocates all tasks. - - Works on targets which have no `core::sync::atomic` support, thanks to [portable-atomic](https://github.com/taiki-e/portable-atomic); - - Does not assume an RTOS and can run completely bare-metal too; - - Lockless, atomic-based, bounded task queue by default, which works well for waking the executor directly from an ISR on e.g. FreeRTOS or ESP-IDF (unbounded also an option with feature `unbounded`, yet that might mean potential allocations in an ISR context, which should be avoided). -**Great features carried over from [async-executor](https://github.com/smol-rs/async-executor)**: +### Great features carried over from [async-executor](https://github.com/smol-rs/async-executor): - Stack borrows: futures spawned on the executor need to live only as long as the executor itself. No `F: Future + 'static` constraints; - - Completely portable and async. `Executor::run` simply returns a `Future`. Polling this future runs the executor, i.e. `block_on(executor.run(core::future:pending::<()>()))`; - - `const new` constructor function. + +--- +**NOTE**: +To compile on `no_std` targets that do **not** have atomics in Rust `core` (i.e. `riscv32imc-unknown-none-elf` and similar single-core MCUs), +enable features `portable-atomic` and `critical-section`. I.e.: +```sh +cargo build --features portable-atomic,critical-section --no-default-features --target +``` +--- +