Merge pull request #108 from theunkn0wn1/doc/util
Document embassy::util
This commit is contained in:
commit
0de2748008
4 changed files with 57 additions and 0 deletions
|
@ -1,6 +1,12 @@
|
|||
use crate::fmt::panic;
|
||||
use core::mem;
|
||||
|
||||
/// An explosive ordinance that panics if it is improperly disposed of.
|
||||
///
|
||||
/// This is to forbid dropping futures, when there is absolutely no other choice.
|
||||
///
|
||||
/// To correctly dispose of this device, call the [defuse](struct.DropBomb.html#method.defuse)
|
||||
/// method before this object is dropped.
|
||||
pub struct DropBomb {
|
||||
_private: (),
|
||||
}
|
||||
|
@ -10,6 +16,7 @@ impl DropBomb {
|
|||
Self { _private: () }
|
||||
}
|
||||
|
||||
/// Diffuses the bomb, rendering it safe to drop.
|
||||
pub fn defuse(self) {
|
||||
mem::forget(self)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,25 @@ use core::mem::MaybeUninit;
|
|||
|
||||
use atomic_polyfill::{AtomicBool, Ordering};
|
||||
|
||||
/// Type with static lifetime that may be written to once at runtime.
|
||||
///
|
||||
/// This may be used to initialize static objects at runtime, typically in the init routine.
|
||||
/// This is useful for objects such as Embassy's RTC, which cannot be initialized in a const
|
||||
/// context.
|
||||
///
|
||||
/// Note: IF a global mutable variable is desired, use a CriticalSectionMutex or ThreadModeMutex instead.
|
||||
///
|
||||
/// ```
|
||||
/// use embassy::util::Forever;
|
||||
/// // Using an integer for the sake of keeping this example self-contained,
|
||||
/// // see https://github.com/embassy-rs/embassy/wiki/Getting-Started for a more "proper" example.
|
||||
/// static SOME_INT: Forever<u32> =Forever::new();
|
||||
///
|
||||
/// // put returns a mutable pointer to the object stored in the forever, which may then be passed
|
||||
/// // around.
|
||||
/// let mut x = SOME_INT.put(42);
|
||||
/// assert_eq!(*x, 42);
|
||||
/// ```
|
||||
pub struct Forever<T> {
|
||||
used: AtomicBool,
|
||||
t: UnsafeCell<MaybeUninit<T>>,
|
||||
|
@ -19,6 +38,11 @@ impl<T> Forever<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gives this `Forever` a value.
|
||||
///
|
||||
/// Panics if this `Forever` already has a value.
|
||||
///
|
||||
/// Returns a mutable reference to the stored value.
|
||||
pub fn put(&'static self, val: T) -> &'static mut T {
|
||||
if self
|
||||
.used
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//! Async utilities
|
||||
mod drop_bomb;
|
||||
mod forever;
|
||||
mod mutex;
|
||||
|
|
|
@ -10,6 +10,9 @@ use crate::executor;
|
|||
use crate::fmt::panic;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
|
||||
/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks.
|
||||
///
|
||||
/// For more advanced use cases, please consider [futures-intrusive](https://crates.io/crates/futures-intrusive) channels or mutexes.
|
||||
pub struct Signal<T> {
|
||||
state: UnsafeCell<State<T>>,
|
||||
}
|
||||
|
@ -30,6 +33,7 @@ impl<T: Send> Signal<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Mark this Signal as completed.
|
||||
pub fn signal(&self, val: T) {
|
||||
cortex_m::interrupt::free(|_| unsafe {
|
||||
let state = &mut *self.state.get();
|
||||
|
@ -64,10 +68,12 @@ impl<T: Send> Signal<T> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Future that completes when this Signal has been signaled.
|
||||
pub fn wait(&self) -> impl Future<Output = T> + '_ {
|
||||
futures::future::poll_fn(move |cx| self.poll_wait(cx))
|
||||
}
|
||||
|
||||
/// non-blocking method to check whether this signal has been signaled.
|
||||
pub fn signaled(&self) -> bool {
|
||||
cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
|
||||
}
|
||||
|
@ -80,6 +86,25 @@ unsafe impl cortex_m::interrupt::Nr for NrWrap {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a future that completes when the specified Interrupt is triggered.
|
||||
///
|
||||
/// The input handler is unregistered when this Future is dropped.
|
||||
///
|
||||
/// Example:
|
||||
/// ``` no_compile
|
||||
/// use embassy::traits::*;
|
||||
/// use embassy::util::InterruptFuture;
|
||||
/// use embassy::executor::task;
|
||||
/// use embassy_stm32f4::interrupt; // Adjust this to your MCU's embassy HAL.
|
||||
/// #[task]
|
||||
/// async fn demo_interrupt_future() {
|
||||
/// // Using STM32f446 interrupt names, adjust this to your application as necessary.
|
||||
/// // Wait for TIM2 to tick.
|
||||
/// let mut tim2_interrupt = interrupt::take!(TIM2);
|
||||
/// InterruptFuture::new(&mut tim2_interrupt).await;
|
||||
/// // TIM2 interrupt went off, do something...
|
||||
/// }
|
||||
/// ```
|
||||
pub struct InterruptFuture<'a, I: Interrupt> {
|
||||
interrupt: &'a mut I,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue