aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-06-16 07:18:43 +0000
committerGitHub <[email protected]>2022-06-16 07:18:43 +0000
commit23177ba7eb800d32a48f70fe568ae9bf6b2cde98 (patch)
treef259b15d26428b8a448e5c14f055a975138470c0
parenta8920bced5e72ca130e92c7680c2d839794d31f6 (diff)
parent25ddb26be815ec3029ea9d28ba812bd541a0face (diff)
Merge #813
813: Document remaining public APIs in embassy crate r=lulf a=lulf This also includes the README.md in the toplevel crate documentation, fixing a few formatting issues with it as well. Please review the mutex in detail in case I've misunderstood/missed a few things there. Co-authored-by: Ulf Lilleengen <[email protected]>
-rw-r--r--README.md17
-rw-r--r--embassy/src/blocking_mutex/mod.rs34
-rw-r--r--embassy/src/blocking_mutex/raw.rs23
-rw-r--r--embassy/src/channel/mpmc.rs2
-rw-r--r--embassy/src/channel/signal.rs1
-rw-r--r--embassy/src/executor/raw/mod.rs8
-rw-r--r--embassy/src/lib.rs1
-rw-r--r--embassy/src/mutex.rs24
-rw-r--r--embassy/src/util/steal.rs10
-rw-r--r--embassy/src/waitqueue/waker.rs9
10 files changed, 105 insertions, 24 deletions
diff --git a/README.md b/README.md
index f9b7486bc..a7a7ccd54 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
2 2
3Embassy 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. 3Embassy 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.
4 4
5## [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) 5## <a href="https://embassy.dev/embassy/dev/index.html">Documentation</a> - <a href="https://docs.embassy.dev/">API reference</a> - <a href="https://embassy.dev/">Website</a> - <a href="https://matrix.to/#/#embassy-rs:matrix.org">Chat</a>
6## Rust + async ❤️ embedded 6## Rust + async ❤️ embedded
7 7
8The 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. 8The 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 <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> cr
42 42
43## Sneak peek 43## Sneak peek
44 44
45```rust 45```rust,ignore
46use defmt::info; 46use defmt::info;
47use embassy::executor::Spawner; 47use embassy::executor::Spawner;
48use embassy::time::{Duration, Timer}; 48use embassy::time::{Duration, Timer};
@@ -93,20 +93,21 @@ Examples are found in the `examples/` folder seperated by the chip manufacturer
93### Running examples 93### Running examples
94 94
95- Setup git submodules (needed for STM32 examples) 95- Setup git submodules (needed for STM32 examples)
96``` 96
97```bash
97git submodule init 98git submodule init
98git submodule update 99git submodule update
99``` 100```
100 101
101- Install `probe-run` with defmt support. 102- Install `probe-run` with defmt support.
102 103
103``` 104```bash
104cargo install probe-run 105cargo install probe-run
105``` 106```
106 107
107- Change directory to the sample's base directory. For example: 108- Change directory to the sample's base directory. For example:
108 109
109``` 110```bash
110cd examples/nrf 111cd examples/nrf
111``` 112```
112 113
@@ -114,7 +115,7 @@ cd examples/nrf
114 115
115For example: 116For example:
116 117
117``` 118```bash
118cargo run --bin blinky 119cargo run --bin blinky
119``` 120```
120 121
@@ -145,8 +146,8 @@ EMBedded ASYnc! :)
145This work is licensed under either of 146This work is licensed under either of
146 147
147- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or 148- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
148 http://www.apache.org/licenses/LICENSE-2.0) 149 <http://www.apache.org/licenses/LICENSE-2.0>)
149- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 150- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
150 151
151at your option. 152at your option.
152 153
diff --git a/embassy/src/blocking_mutex/mod.rs b/embassy/src/blocking_mutex/mod.rs
index eb3cd9392..602ec8a07 100644
--- a/embassy/src/blocking_mutex/mod.rs
+++ b/embassy/src/blocking_mutex/mod.rs
@@ -1,14 +1,27 @@
1//! Blocking mutex (not async) 1//! Blocking mutex.
2 2//!
3//! This module provides a blocking mutex that can be used to synchronize data.
3pub mod raw; 4pub mod raw;
4 5
5use core::cell::UnsafeCell; 6use core::cell::UnsafeCell;
6 7
7use self::raw::RawMutex; 8use self::raw::RawMutex;
8 9
9/// Any object implementing this trait guarantees exclusive access to the data contained 10/// Blocking mutex (not async)
10/// within the mutex for the duration of the lock. 11///
11/// Adapted from <https://github.com/rust-embedded/mutex-trait>. 12/// Provides a blocking mutual exclusion primitive backed by an implementation of [`raw::RawMutex`].
13///
14/// Which implementation you select depends on the context in which you're using the mutex, and you can choose which kind
15/// of interior mutability fits your use case.
16///
17/// Use [`CriticalSectionMutex`] when data can be shared between threads and interrupts.
18///
19/// Use [`NoopMutex`] when data is only shared between tasks running on the same executor.
20///
21/// Use [`ThreadModeMutex`] when data is shared between tasks running on the same executor but you want a global singleton.
22///
23/// In all cases, the blocking mutex is intended to be short lived and not held across await points.
24/// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points.
12pub struct Mutex<R, T: ?Sized> { 25pub struct Mutex<R, T: ?Sized> {
13 // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets 26 // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets
14 // to run BEFORE dropping `data`. 27 // to run BEFORE dropping `data`.
@@ -78,7 +91,18 @@ impl<R, T> Mutex<R, T> {
78 } 91 }
79} 92}
80 93
94/// A mutex that allows borrowing data across executors and interrupts.
95///
96/// # Safety
97///
98/// This mutex is safe to share between different executors and interrupts.
81pub type CriticalSectionMutex<T> = Mutex<raw::CriticalSectionRawMutex, T>; 99pub type CriticalSectionMutex<T> = Mutex<raw::CriticalSectionRawMutex, T>;
100
101/// A mutex that allows borrowing data in the context of a single executor.
102///
103/// # Safety
104///
105/// **This Mutex is only safe within a single executor.**
82pub type NoopMutex<T> = Mutex<raw::NoopRawMutex, T>; 106pub type NoopMutex<T> = Mutex<raw::NoopRawMutex, T>;
83 107
84impl<T> Mutex<raw::CriticalSectionRawMutex, T> { 108impl<T> Mutex<raw::CriticalSectionRawMutex, T> {
diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs
index f9d249b08..bdb443e4d 100644
--- a/embassy/src/blocking_mutex/raw.rs
+++ b/embassy/src/blocking_mutex/raw.rs
@@ -1,11 +1,22 @@
1//! Mutex primitives.
2//!
3//! This module provides a trait for mutexes that can be used in different contexts.
1use core::marker::PhantomData; 4use core::marker::PhantomData;
2 5
6/// Any object implementing this trait guarantees exclusive access to the data contained
7/// within the mutex for the duration of the lock.
8/// Adapted from <https://github.com/rust-embedded/mutex-trait>.
3pub trait RawMutex { 9pub trait RawMutex {
4 const INIT: Self; 10 const INIT: Self;
5 11
6 fn lock<R>(&self, f: impl FnOnce() -> R) -> R; 12 fn lock<R>(&self, f: impl FnOnce() -> R) -> R;
7} 13}
8 14
15/// A mutex that allows borrowing data across executors and interrupts.
16///
17/// # Safety
18///
19/// This mutex is safe to share between different executors and interrupts.
9pub struct CriticalSectionRawMutex { 20pub struct CriticalSectionRawMutex {
10 _phantom: PhantomData<()>, 21 _phantom: PhantomData<()>,
11} 22}
@@ -28,6 +39,11 @@ impl RawMutex for CriticalSectionRawMutex {
28 39
29// ================ 40// ================
30 41
42/// A mutex that allows borrowing data in the context of a single executor.
43///
44/// # Safety
45///
46/// **This Mutex is only safe within a single executor.**
31pub struct NoopRawMutex { 47pub struct NoopRawMutex {
32 _phantom: PhantomData<*mut ()>, 48 _phantom: PhantomData<*mut ()>,
33} 49}
@@ -53,6 +69,13 @@ impl RawMutex for NoopRawMutex {
53mod thread_mode { 69mod thread_mode {
54 use super::*; 70 use super::*;
55 71
72 /// A "mutex" that only allows borrowing from thread mode.
73 ///
74 /// # Safety
75 ///
76 /// **This Mutex is only safe on single-core systems.**
77 ///
78 /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access.
56 pub struct ThreadModeRawMutex { 79 pub struct ThreadModeRawMutex {
57 _phantom: PhantomData<()>, 80 _phantom: PhantomData<()>,
58 } 81 }
diff --git a/embassy/src/channel/mpmc.rs b/embassy/src/channel/mpmc.rs
index 48056cd8f..1d03eef19 100644
--- a/embassy/src/channel/mpmc.rs
+++ b/embassy/src/channel/mpmc.rs
@@ -433,7 +433,7 @@ where
433 433
434 /// Attempt to immediately send a message. 434 /// Attempt to immediately send a message.
435 /// 435 ///
436 /// This method differs from [`send`] by returning immediately if the channel's 436 /// This method differs from [`send`](Channel::send) by returning immediately if the channel's
437 /// buffer is full, instead of waiting. 437 /// buffer is full, instead of waiting.
438 /// 438 ///
439 /// # Errors 439 /// # Errors
diff --git a/embassy/src/channel/signal.rs b/embassy/src/channel/signal.rs
index 5a2c9d47a..cf78dad8b 100644
--- a/embassy/src/channel/signal.rs
+++ b/embassy/src/channel/signal.rs
@@ -1,3 +1,4 @@
1//! A synchronization primitive for passing the latest value to a task.
1use core::cell::UnsafeCell; 2use core::cell::UnsafeCell;
2use core::future::Future; 3use core::future::Future;
3use core::mem; 4use core::mem;
diff --git a/embassy/src/executor/raw/mod.rs b/embassy/src/executor/raw/mod.rs
index 09429c19a..b8455442e 100644
--- a/embassy/src/executor/raw/mod.rs
+++ b/embassy/src/executor/raw/mod.rs
@@ -5,7 +5,7 @@
5//! ## WARNING: here be dragons! 5//! ## WARNING: here be dragons!
6//! 6//!
7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe 7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
8//! executor wrappers in [`crate::executor`] and the [`crate::task`] macro, which are fully safe. 8//! executor wrappers in [`executor`](crate::executor) and the [`embassy::task`](embassy_macros::task) macro, which are fully safe.
9 9
10mod run_queue; 10mod run_queue;
11#[cfg(feature = "time")] 11#[cfg(feature = "time")]
@@ -115,7 +115,7 @@ impl TaskHeader {
115/// A `TaskStorage` must live forever, it may not be deallocated even after the task has finished 115/// A `TaskStorage` must live forever, it may not be deallocated even after the task has finished
116/// running. Hence the relevant methods require `&'static self`. It may be reused, however. 116/// running. Hence the relevant methods require `&'static self`. It may be reused, however.
117/// 117///
118/// Internally, the [embassy::task](crate::task) macro allocates an array of `TaskStorage`s 118/// Internally, the [embassy::task](embassy_macros::task) macro allocates an array of `TaskStorage`s
119/// in a `static`. The most common reason to use the raw `Task` is to have control of where 119/// in a `static`. The most common reason to use the raw `Task` is to have control of where
120/// the memory for the task is allocated: on the stack, or on the heap with e.g. `Box::leak`, etc. 120/// the memory for the task is allocated: on the stack, or on the heap with e.g. `Box::leak`, etc.
121 121
@@ -158,7 +158,7 @@ impl<F: Future + 'static> TaskStorage<F> {
158 /// 158 ///
159 /// This function will fail if the task is already spawned and has not finished running. 159 /// This function will fail if the task is already spawned and has not finished running.
160 /// In this case, the error is delayed: a "poisoned" SpawnToken is returned, which will 160 /// In this case, the error is delayed: a "poisoned" SpawnToken is returned, which will
161 /// cause [`Spawner::spawn()`] to return the error. 161 /// cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
162 /// 162 ///
163 /// Once the task has finished running, you may spawn it again. It is allowed to spawn it 163 /// Once the task has finished running, you may spawn it again. It is allowed to spawn it
164 /// on a different executor. 164 /// on a different executor.
@@ -230,7 +230,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
230 /// 230 ///
231 /// This will loop over the pool and spawn the task in the first storage that 231 /// This will loop over the pool and spawn the task in the first storage that
232 /// is currently free. If none is free, a "poisoned" SpawnToken is returned, 232 /// is currently free. If none is free, a "poisoned" SpawnToken is returned,
233 /// which will cause [`Spawner::spawn()`] to return the error. 233 /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
234 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> { 234 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> {
235 for task in &self.pool { 235 for task in &self.pool {
236 if task.spawn_mark_used() { 236 if task.spawn_mark_used() {
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index 1b6ff2d4b..c3b2726aa 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -1,6 +1,7 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] 2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))]
3#![allow(clippy::new_without_default)] 3#![allow(clippy::new_without_default)]
4#![doc = include_str!("../../README.md")]
4 5
5// This mod MUST go first, so that the others see its macros. 6// This mod MUST go first, so that the others see its macros.
6pub(crate) mod fmt; 7pub(crate) mod fmt;
diff --git a/embassy/src/mutex.rs b/embassy/src/mutex.rs
index 7b6bcb147..9cfaaa845 100644
--- a/embassy/src/mutex.rs
+++ b/embassy/src/mutex.rs
@@ -1,9 +1,6 @@
1/// Async mutex. 1//! Async mutex.
2/// 2//!
3/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex). 3//! This module provides a mutex that can be used to synchronize data between asynchronous tasks.
4/// The raw mutex is used to guard access to the internal "is locked" flag. It
5/// is held for very short periods only, while locking and unlocking. It is *not* held
6/// for the entire time the async Mutex is locked.
7use core::cell::{RefCell, UnsafeCell}; 4use core::cell::{RefCell, UnsafeCell};
8use core::ops::{Deref, DerefMut}; 5use core::ops::{Deref, DerefMut};
9use core::task::Poll; 6use core::task::Poll;
@@ -24,6 +21,21 @@ struct State {
24 waker: WakerRegistration, 21 waker: WakerRegistration,
25} 22}
26 23
24/// Async mutex.
25///
26/// The mutex is generic over a blocking [`RawMutex`](crate::blocking_mutex::raw::RawMutex).
27/// The raw mutex is used to guard access to the internal "is locked" flag. It
28/// is held for very short periods only, while locking and unlocking. It is *not* held
29/// for the entire time the async Mutex is locked.
30///
31/// Which implementation you select depends on the context in which you're using the mutex.
32///
33/// Use [`CriticalSectionRawMutex`](crate::blocking_mutex::raw::CriticalSectionRawMutex) when data can be shared between threads and interrupts.
34///
35/// Use [`NoopRawMutex`](crate::blocking_mutex::raw::NoopRawMutex) when data is only shared between tasks running on the same executor.
36///
37/// Use [`ThreadModeRawMutex`](crate::blocking_mutex::raw::ThreadModeRawMutex) when data is shared between tasks running on the same executor but you want a singleton.
38///
27pub struct Mutex<M, T> 39pub struct Mutex<M, T>
28where 40where
29 M: RawMutex, 41 M: RawMutex,
diff --git a/embassy/src/util/steal.rs b/embassy/src/util/steal.rs
index a0d5f1359..07eb5fffd 100644
--- a/embassy/src/util/steal.rs
+++ b/embassy/src/util/steal.rs
@@ -1,3 +1,13 @@
1/// A type that can retrieved unsafely from anywhere.
1pub trait Steal { 2pub trait Steal {
3 /// Retrieve and instance of this type.
4 ///
5 /// # Safety
6 ///
7 /// It is the responsibility of the application to ensure that the
8 /// usage of the returned instance is not in conflict with other uses
9 /// of this instance.
10 ///
11 /// The implementation may panic if the instance is already in use.
2 unsafe fn steal() -> Self; 12 unsafe fn steal() -> Self;
3} 13}
diff --git a/embassy/src/waitqueue/waker.rs b/embassy/src/waitqueue/waker.rs
index 1ac6054f9..da907300a 100644
--- a/embassy/src/waitqueue/waker.rs
+++ b/embassy/src/waitqueue/waker.rs
@@ -6,6 +6,10 @@ use atomic_polyfill::{compiler_fence, AtomicPtr, Ordering};
6use crate::executor::raw::{task_from_waker, wake_task, TaskHeader}; 6use crate::executor::raw::{task_from_waker, wake_task, TaskHeader};
7 7
8/// Utility struct to register and wake a waker. 8/// Utility struct to register and wake a waker.
9///
10/// # Safety
11///
12/// This type is optimized for (and only works with) embassy tasks.
9#[derive(Debug)] 13#[derive(Debug)]
10pub struct WakerRegistration { 14pub struct WakerRegistration {
11 waker: Option<NonNull<TaskHeader>>, 15 waker: Option<NonNull<TaskHeader>>,
@@ -53,6 +57,11 @@ impl WakerRegistration {
53unsafe impl Send for WakerRegistration {} 57unsafe impl Send for WakerRegistration {}
54unsafe impl Sync for WakerRegistration {} 58unsafe impl Sync for WakerRegistration {}
55 59
60/// Utility struct to atomically register and wake a waker.
61///
62/// # Safety
63///
64/// This type is optimized for (and only works with) embassy tasks.
56pub struct AtomicWaker { 65pub struct AtomicWaker {
57 waker: AtomicPtr<TaskHeader>, 66 waker: AtomicPtr<TaskHeader>,
58} 67}