embassy-executor

Crates

git

Versions

riscv32

Flavors

Crate embassy_executor

Source
Expand description

§embassy-executor

An async/await executor designed for embedded usage.

  • No alloc, no heap needed.
  • With nightly Rust, task futures can be fully statically allocated.
  • No “fixed capacity” data structures, executor works with 1 or 1000 tasks without needing config/tuning.
  • Integrated timer queue: sleeping is easy, just do Timer::after_secs(1).await;.
  • No busy-loop polling: CPU sleeps when there’s no work to do, using interrupts or WFE/SEV.
  • Efficient polling: a wake will only poll the woken task, not all of them.
  • Fair: a task can’t monopolize CPU time even if it’s constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
  • Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks.

§Task arena

When the nightly Cargo feature is not enabled, embassy-executor allocates tasks out of an arena (a very simple bump allocator).

If the task arena gets full, the program will panic at runtime. To guarantee this doesn’t happen, you must set the size to the sum of sizes of all tasks.

Tasks are allocated from the arena when spawned for the first time. If the task exists, the allocation is not released to the arena, but can be reused to spawn the task again. For multiple-instance tasks (like #[embassy_executor::task(pool_size = 4)]), the first spawn will allocate memory for all instances. This is done for performance and to increase predictability (for example, spawning at least 1 instance of every task at boot guarantees an immediate panic if the arena is too small, while allocating instances on-demand could delay the panic to only when the program is under load).

The arena size can be configured in two ways:

  • Via Cargo features: enable a Cargo feature like task-arena-size-8192. Only a selection of values is available, see Task Area Sizes for reference.
  • Via environment variables at build time: set the variable named EMBASSY_EXECUTOR_TASK_ARENA_SIZE. For example EMBASSY_EXECUTOR_TASK_ARENA_SIZE=4321 cargo build. You can also set them in the [env] section of .cargo/config.toml. Any value can be set, unlike with Cargo features.

Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting with different values, compilation fails.

§Statically allocating tasks

When using nightly Rust, enable the nightly Cargo feature. This will make embassy-executor use the type_alias_impl_trait feature to allocate all tasks in statics. Each task gets its own static, with the exact size to hold the task (or multiple instances of it, if using pool_size) calculated automatically at compile time. If tasks don’t fit in RAM, this is detected at compile time by the linker. Runtime panics due to running out of memory are not possible.

The configured arena size is ignored, no arena is used at all.

§Feature flags

  • nightly — Enable nightly-only features
  • integrated-timers — Use the executor-integrated embassy-time timer queue.

§Architecture

  • arch-std — std
  • arch-cortex-m — Cortex-M
  • arch-riscv32 — RISC-V 32
  • arch-wasm — WASM
  • arch-avr — AVR
  • arch-spin — spin (architecture agnostic; never sleeps)

§Executor

  • executor-thread — Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
  • executor-interrupt — Enable the interrupt-mode executor (available in Cortex-M only)

§Task Arena Size

Sets the task arena size. Necessary if you’re not using nightly.

Preconfigured Task Arena Sizes:
  • task-arena-size-64 — 64
  • task-arena-size-128 — 128
  • task-arena-size-192 — 192
  • task-arena-size-256 — 256
  • task-arena-size-320 — 320
  • task-arena-size-384 — 384
  • task-arena-size-512 — 512
  • task-arena-size-640 — 640
  • task-arena-size-768 — 768
  • task-arena-size-1024 — 1024
  • task-arena-size-1280 — 1280
  • task-arena-size-1536 — 1536
  • task-arena-size-2048 — 2048
  • task-arena-size-2560 — 2560
  • task-arena-size-3072 — 3072
  • task-arena-size-4096 — 4096 (default)
  • task-arena-size-5120 — 5120
  • task-arena-size-6144 — 6144
  • task-arena-size-8192 — 8192
  • task-arena-size-10240 — 10240
  • task-arena-size-12288 — 12288
  • task-arena-size-16384 — 16384
  • task-arena-size-20480 — 20480
  • task-arena-size-24576 — 24576
  • task-arena-size-32768 — 32768
  • task-arena-size-40960 — 40960
  • task-arena-size-49152 — 49152
  • task-arena-size-65536 — 65536
  • task-arena-size-81920 — 81920
  • task-arena-size-98304 — 98304
  • task-arena-size-131072 — 131072
  • task-arena-size-163840 — 163840
  • task-arena-size-196608 — 196608
  • task-arena-size-262144 — 262144
  • task-arena-size-327680 — 327680
  • task-arena-size-393216 — 393216
  • task-arena-size-524288 — 524288
  • task-arena-size-655360 — 655360
  • task-arena-size-786432 — 786432
  • task-arena-size-1048576 — 1048576

Modules§

  • Raw executor.

Structs§

  • RISCV32 Executor
  • Handle to spawn tasks into an executor from any thread.
  • Token to spawn a newly-created task in an executor.
  • Handle to spawn tasks into an executor.

Enums§

Attribute Macros§

  • Creates a new executor instance and declares an application entry point for RISC-V spawning the corresponding function body as an async task.
  • Declares an async task that can be run by embassy-executor. The optional pool_size parameter can be used to specify how many concurrent tasks can be spawned (default is 1) for the function.