diff --git a/README.md b/README.md
index f9b7486b..a7a7ccd5 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Embassy is the next-generation framework for embedded applications. Write safe, correct and energy-efficient embedded code faster, using the Rust programming language, its async facilities, and the Embassy libraries.
-## [Documentation](https://embassy.dev/embassy/dev/index.html) - [API reference](https://docs.embassy.dev/) - [Website](https://embassy.dev/) - [Chat](https://matrix.to/#/#embassy-rs:matrix.org)
+## Documentation - API reference - Website - Chat
## Rust + async ❤️ embedded
The Rust programming language is blazingly fast and memory-efficient, with no runtime, garbage collector or OS. It catches a wide variety of bugs at compile time, thanks to its full memory- and thread-safety, and expressive type system.
@@ -42,7 +42,7 @@ The nrf-softdevice cr
## Sneak peek
-```rust
+```rust,ignore
use defmt::info;
use embassy::executor::Spawner;
use embassy::time::{Duration, Timer};
@@ -93,20 +93,21 @@ Examples are found in the `examples/` folder seperated by the chip manufacturer
### Running examples
- Setup git submodules (needed for STM32 examples)
-```
+
+```bash
git submodule init
git submodule update
```
- Install `probe-run` with defmt support.
-```
+```bash
cargo install probe-run
```
- Change directory to the sample's base directory. For example:
-```
+```bash
cd examples/nrf
```
@@ -114,7 +115,7 @@ cd examples/nrf
For example:
-```
+```bash
cargo run --bin blinky
```
@@ -145,8 +146,8 @@ EMBedded ASYnc! :)
This work is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
- http://www.apache.org/licenses/LICENSE-2.0)
-- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+ )
+- MIT license ([LICENSE-MIT](LICENSE-MIT) or )
at your option.
diff --git a/embassy/src/blocking_mutex/mod.rs b/embassy/src/blocking_mutex/mod.rs
index eb3cd939..602ec8a0 100644
--- a/embassy/src/blocking_mutex/mod.rs
+++ b/embassy/src/blocking_mutex/mod.rs
@@ -1,14 +1,27 @@
-//! Blocking mutex (not async)
-
+//! Blocking mutex.
+//!
+//! This module provides a blocking mutex that can be used to synchronize data.
pub mod raw;
use core::cell::UnsafeCell;
use self::raw::RawMutex;
-/// Any object implementing this trait guarantees exclusive access to the data contained
-/// within the mutex for the duration of the lock.
-/// Adapted from .
+/// Blocking mutex (not async)
+///
+/// Provides a blocking mutual exclusion primitive backed by an implementation of [`raw::RawMutex`].
+///
+/// Which implementation you select depends on the context in which you're using the mutex, and you can choose which kind
+/// of interior mutability fits your use case.
+///
+/// Use [`CriticalSectionMutex`] when data can be shared between threads and interrupts.
+///
+/// Use [`NoopMutex`] when data is only shared between tasks running on the same executor.
+///
+/// Use [`ThreadModeMutex`] when data is shared between tasks running on the same executor but you want a global singleton.
+///
+/// In all cases, the blocking mutex is intended to be short lived and not held across await points.
+/// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points.
pub struct Mutex {
// NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets
// to run BEFORE dropping `data`.
@@ -78,7 +91,18 @@ impl Mutex {
}
}
+/// A mutex that allows borrowing data across executors and interrupts.
+///
+/// # Safety
+///
+/// This mutex is safe to share between different executors and interrupts.
pub type CriticalSectionMutex = Mutex;
+
+/// A mutex that allows borrowing data in the context of a single executor.
+///
+/// # Safety
+///
+/// **This Mutex is only safe within a single executor.**
pub type NoopMutex = Mutex;
impl Mutex {
diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs
index f9d249b0..bdb443e4 100644
--- a/embassy/src/blocking_mutex/raw.rs
+++ b/embassy/src/blocking_mutex/raw.rs
@@ -1,11 +1,22 @@
+//! Mutex primitives.
+//!
+//! This module provides a trait for mutexes that can be used in different contexts.
use core::marker::PhantomData;
+/// Any object implementing this trait guarantees exclusive access to the data contained
+/// within the mutex for the duration of the lock.
+/// Adapted from .
pub trait RawMutex {
const INIT: Self;
fn lock(&self, f: impl FnOnce() -> R) -> R;
}
+/// A mutex that allows borrowing data across executors and interrupts.
+///
+/// # Safety
+///
+/// This mutex is safe to share between different executors and interrupts.
pub struct CriticalSectionRawMutex {
_phantom: PhantomData<()>,
}
@@ -28,6 +39,11 @@ impl RawMutex for CriticalSectionRawMutex {
// ================
+/// A mutex that allows borrowing data in the context of a single executor.
+///
+/// # Safety
+///
+/// **This Mutex is only safe within a single executor.**
pub struct NoopRawMutex {
_phantom: PhantomData<*mut ()>,
}
@@ -53,6 +69,13 @@ impl RawMutex for NoopRawMutex {
mod thread_mode {
use super::*;
+ /// A "mutex" that only allows borrowing from thread mode.
+ ///
+ /// # Safety
+ ///
+ /// **This Mutex is only safe on single-core systems.**
+ ///
+ /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access.
pub struct ThreadModeRawMutex {
_phantom: PhantomData<()>,
}
diff --git a/embassy/src/channel/mpmc.rs b/embassy/src/channel/mpmc.rs
index 48056cd8..1d03eef1 100644
--- a/embassy/src/channel/mpmc.rs
+++ b/embassy/src/channel/mpmc.rs
@@ -433,7 +433,7 @@ where
/// Attempt to immediately send a message.
///
- /// This method differs from [`send`] by returning immediately if the channel's
+ /// This method differs from [`send`](Channel::send) by returning immediately if the channel's
/// buffer is full, instead of waiting.
///
/// # Errors
diff --git a/embassy/src/channel/signal.rs b/embassy/src/channel/signal.rs
index 5a2c9d47..cf78dad8 100644
--- a/embassy/src/channel/signal.rs
+++ b/embassy/src/channel/signal.rs
@@ -1,3 +1,4 @@
+//! A synchronization primitive for passing the latest value to a task.
use core::cell::UnsafeCell;
use core::future::Future;
use core::mem;
diff --git a/embassy/src/executor/raw/mod.rs b/embassy/src/executor/raw/mod.rs
index 09429c19..b8455442 100644
--- a/embassy/src/executor/raw/mod.rs
+++ b/embassy/src/executor/raw/mod.rs
@@ -5,7 +5,7 @@
//! ## WARNING: here be dragons!
//!
//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
-//! executor wrappers in [`crate::executor`] and the [`crate::task`] macro, which are fully safe.
+//! executor wrappers in [`executor`](crate::executor) and the [`embassy::task`](embassy_macros::task) macro, which are fully safe.
mod run_queue;
#[cfg(feature = "time")]
@@ -115,7 +115,7 @@ impl TaskHeader {
/// A `TaskStorage` must live forever, it may not be deallocated even after the task has finished
/// running. Hence the relevant methods require `&'static self`. It may be reused, however.
///
-/// Internally, the [embassy::task](crate::task) macro allocates an array of `TaskStorage`s
+/// Internally, the [embassy::task](embassy_macros::task) macro allocates an array of `TaskStorage`s
/// in a `static`. The most common reason to use the raw `Task` is to have control of where
/// the memory for the task is allocated: on the stack, or on the heap with e.g. `Box::leak`, etc.
@@ -158,7 +158,7 @@ impl TaskStorage {
///
/// This function will fail if the task is already spawned and has not finished running.
/// In this case, the error is delayed: a "poisoned" SpawnToken is returned, which will
- /// cause [`Spawner::spawn()`] to return the error.
+ /// cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
///
/// Once the task has finished running, you may spawn it again. It is allowed to spawn it
/// on a different executor.
@@ -230,7 +230,7 @@ impl TaskPool {
///
/// This will loop over the pool and spawn the task in the first storage that
/// is currently free. If none is free, a "poisoned" SpawnToken is returned,
- /// which will cause [`Spawner::spawn()`] to return the error.
+ /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken {
for task in &self.pool {
if task.spawn_mark_used() {
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index 1b6ff2d4..c3b2726a 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -1,6 +1,7 @@
#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))]
#![allow(clippy::new_without_default)]
+#![doc = include_str!("../../README.md")]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
diff --git a/embassy/src/mutex.rs b/embassy/src/mutex.rs
index 7b6bcb14..9cfaaa84 100644
--- a/embassy/src/mutex.rs
+++ b/embassy/src/mutex.rs
@@ -1,9 +1,6 @@
-/// Async mutex.
-///
-/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex).
-/// The raw mutex is used to guard access to the internal "is locked" flag. It
-/// is held for very short periods only, while locking and unlocking. It is *not* held
-/// for the entire time the async Mutex is locked.
+//! Async mutex.
+//!
+//! This module provides a mutex that can be used to synchronize data between asynchronous tasks.
use core::cell::{RefCell, UnsafeCell};
use core::ops::{Deref, DerefMut};
use core::task::Poll;
@@ -24,6 +21,21 @@ struct State {
waker: WakerRegistration,
}
+/// Async mutex.
+///
+/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex).
+/// The raw mutex is used to guard access to the internal "is locked" flag. It
+/// is held for very short periods only, while locking and unlocking. It is *not* held
+/// for the entire time the async Mutex is locked.
+///
+/// Which implementation you select depends on the context in which you're using the mutex.
+///
+/// Use [`CriticalSectionRawMutex`](crate::blocking_mutex::raw::CriticalSectionRawMutex) when data can be shared between threads and interrupts.
+///
+/// Use [`NoopRawMutex`](crate::blocking_mutex::raw::NoopRawMutex) when data is only shared between tasks running on the same executor.
+///
+/// Use [`ThreadModeRawMutex`](crate::blocking_mutex::raw::ThreadModeRawMutex) when data is shared between tasks running on the same executor but you want a singleton.
+///
pub struct Mutex
where
M: RawMutex,
diff --git a/embassy/src/util/steal.rs b/embassy/src/util/steal.rs
index a0d5f135..07eb5fff 100644
--- a/embassy/src/util/steal.rs
+++ b/embassy/src/util/steal.rs
@@ -1,3 +1,13 @@
+/// A type that can retrieved unsafely from anywhere.
pub trait Steal {
+ /// Retrieve and instance of this type.
+ ///
+ /// # Safety
+ ///
+ /// It is the responsibility of the application to ensure that the
+ /// usage of the returned instance is not in conflict with other uses
+ /// of this instance.
+ ///
+ /// The implementation may panic if the instance is already in use.
unsafe fn steal() -> Self;
}
diff --git a/embassy/src/waitqueue/waker.rs b/embassy/src/waitqueue/waker.rs
index 1ac6054f..da907300 100644
--- a/embassy/src/waitqueue/waker.rs
+++ b/embassy/src/waitqueue/waker.rs
@@ -6,6 +6,10 @@ use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering};
use crate::executor::raw::{task_from_waker, wake_task, TaskHeader};
/// Utility struct to register and wake a waker.
+///
+/// # Safety
+///
+/// This type is optimized for (and only works with) embassy tasks.
#[derive(Debug)]
pub struct WakerRegistration {
waker: Option>,
@@ -53,6 +57,11 @@ impl WakerRegistration {
unsafe impl Send for WakerRegistration {}
unsafe impl Sync for WakerRegistration {}
+/// Utility struct to atomically register and wake a waker.
+///
+/// # Safety
+///
+/// This type is optimized for (and only works with) embassy tasks.
pub struct AtomicWaker {
waker: AtomicPtr,
}