diff options
| author | xoviat <[email protected]> | 2021-03-25 08:33:17 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-03-25 08:33:17 -0500 |
| commit | 0de274800844ba9aa30bd21aa217642f109e8e7e (patch) | |
| tree | ab990afab3b1465b110f390dc3f5777568172a7a | |
| parent | 08990b2f6dcd0edad9b3feb4b993390738c49989 (diff) | |
| parent | ea650b684c54fa5e1639e80e5f6300d640b3c9d3 (diff) | |
Merge pull request #108 from theunkn0wn1/doc/util
Document embassy::util
| -rw-r--r-- | embassy/src/util/drop_bomb.rs | 7 | ||||
| -rw-r--r-- | embassy/src/util/forever.rs | 24 | ||||
| -rw-r--r-- | embassy/src/util/mod.rs | 1 | ||||
| -rw-r--r-- | embassy/src/util/signal.rs | 25 |
4 files changed, 57 insertions, 0 deletions
diff --git a/embassy/src/util/drop_bomb.rs b/embassy/src/util/drop_bomb.rs index b2b0684e5..388209a23 100644 --- a/embassy/src/util/drop_bomb.rs +++ b/embassy/src/util/drop_bomb.rs | |||
| @@ -1,6 +1,12 @@ | |||
| 1 | use crate::fmt::panic; | 1 | use crate::fmt::panic; |
| 2 | use core::mem; | 2 | use core::mem; |
| 3 | 3 | ||
| 4 | /// An explosive ordinance that panics if it is improperly disposed of. | ||
| 5 | /// | ||
| 6 | /// This is to forbid dropping futures, when there is absolutely no other choice. | ||
| 7 | /// | ||
| 8 | /// To correctly dispose of this device, call the [defuse](struct.DropBomb.html#method.defuse) | ||
| 9 | /// method before this object is dropped. | ||
| 4 | pub struct DropBomb { | 10 | pub struct DropBomb { |
| 5 | _private: (), | 11 | _private: (), |
| 6 | } | 12 | } |
| @@ -10,6 +16,7 @@ impl DropBomb { | |||
| 10 | Self { _private: () } | 16 | Self { _private: () } |
| 11 | } | 17 | } |
| 12 | 18 | ||
| 19 | /// Diffuses the bomb, rendering it safe to drop. | ||
| 13 | pub fn defuse(self) { | 20 | pub fn defuse(self) { |
| 14 | mem::forget(self) | 21 | mem::forget(self) |
| 15 | } | 22 | } |
diff --git a/embassy/src/util/forever.rs b/embassy/src/util/forever.rs index ac23a3ce3..efa96f30e 100644 --- a/embassy/src/util/forever.rs +++ b/embassy/src/util/forever.rs | |||
| @@ -3,6 +3,25 @@ use core::mem::MaybeUninit; | |||
| 3 | 3 | ||
| 4 | use atomic_polyfill::{AtomicBool, Ordering}; | 4 | use atomic_polyfill::{AtomicBool, Ordering}; |
| 5 | 5 | ||
| 6 | /// Type with static lifetime that may be written to once at runtime. | ||
| 7 | /// | ||
| 8 | /// This may be used to initialize static objects at runtime, typically in the init routine. | ||
| 9 | /// This is useful for objects such as Embassy's RTC, which cannot be initialized in a const | ||
| 10 | /// context. | ||
| 11 | /// | ||
| 12 | /// Note: IF a global mutable variable is desired, use a CriticalSectionMutex or ThreadModeMutex instead. | ||
| 13 | /// | ||
| 14 | /// ``` | ||
| 15 | /// use embassy::util::Forever; | ||
| 16 | /// // Using an integer for the sake of keeping this example self-contained, | ||
| 17 | /// // see https://github.com/embassy-rs/embassy/wiki/Getting-Started for a more "proper" example. | ||
| 18 | /// static SOME_INT: Forever<u32> =Forever::new(); | ||
| 19 | /// | ||
| 20 | /// // put returns a mutable pointer to the object stored in the forever, which may then be passed | ||
| 21 | /// // around. | ||
| 22 | /// let mut x = SOME_INT.put(42); | ||
| 23 | /// assert_eq!(*x, 42); | ||
| 24 | /// ``` | ||
| 6 | pub struct Forever<T> { | 25 | pub struct Forever<T> { |
| 7 | used: AtomicBool, | 26 | used: AtomicBool, |
| 8 | t: UnsafeCell<MaybeUninit<T>>, | 27 | t: UnsafeCell<MaybeUninit<T>>, |
| @@ -19,6 +38,11 @@ impl<T> Forever<T> { | |||
| 19 | } | 38 | } |
| 20 | } | 39 | } |
| 21 | 40 | ||
| 41 | /// Gives this `Forever` a value. | ||
| 42 | /// | ||
| 43 | /// Panics if this `Forever` already has a value. | ||
| 44 | /// | ||
| 45 | /// Returns a mutable reference to the stored value. | ||
| 22 | pub fn put(&'static self, val: T) -> &'static mut T { | 46 | pub fn put(&'static self, val: T) -> &'static mut T { |
| 23 | if self | 47 | if self |
| 24 | .used | 48 | .used |
diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs index e64e7f1f1..6917e9993 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | //! Async utilities | ||
| 1 | mod drop_bomb; | 2 | mod drop_bomb; |
| 2 | mod forever; | 3 | mod forever; |
| 3 | mod mutex; | 4 | mod mutex; |
diff --git a/embassy/src/util/signal.rs b/embassy/src/util/signal.rs index 41e27d4ca..0fd5c9275 100644 --- a/embassy/src/util/signal.rs +++ b/embassy/src/util/signal.rs | |||
| @@ -10,6 +10,9 @@ use crate::executor; | |||
| 10 | use crate::fmt::panic; | 10 | use crate::fmt::panic; |
| 11 | use crate::interrupt::{Interrupt, InterruptExt}; | 11 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 12 | 12 | ||
| 13 | /// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. | ||
| 14 | /// | ||
| 15 | /// For more advanced use cases, please consider [futures-intrusive](https://crates.io/crates/futures-intrusive) channels or mutexes. | ||
| 13 | pub struct Signal<T> { | 16 | pub struct Signal<T> { |
| 14 | state: UnsafeCell<State<T>>, | 17 | state: UnsafeCell<State<T>>, |
| 15 | } | 18 | } |
| @@ -30,6 +33,7 @@ impl<T: Send> Signal<T> { | |||
| 30 | } | 33 | } |
| 31 | } | 34 | } |
| 32 | 35 | ||
| 36 | /// Mark this Signal as completed. | ||
| 33 | pub fn signal(&self, val: T) { | 37 | pub fn signal(&self, val: T) { |
| 34 | cortex_m::interrupt::free(|_| unsafe { | 38 | cortex_m::interrupt::free(|_| unsafe { |
| 35 | let state = &mut *self.state.get(); | 39 | let state = &mut *self.state.get(); |
| @@ -64,10 +68,12 @@ impl<T: Send> Signal<T> { | |||
| 64 | }) | 68 | }) |
| 65 | } | 69 | } |
| 66 | 70 | ||
| 71 | /// Future that completes when this Signal has been signaled. | ||
| 67 | pub fn wait(&self) -> impl Future<Output = T> + '_ { | 72 | pub fn wait(&self) -> impl Future<Output = T> + '_ { |
| 68 | futures::future::poll_fn(move |cx| self.poll_wait(cx)) | 73 | futures::future::poll_fn(move |cx| self.poll_wait(cx)) |
| 69 | } | 74 | } |
| 70 | 75 | ||
| 76 | /// non-blocking method to check whether this signal has been signaled. | ||
| 71 | pub fn signaled(&self) -> bool { | 77 | pub fn signaled(&self) -> bool { |
| 72 | cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) | 78 | cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) |
| 73 | } | 79 | } |
| @@ -80,6 +86,25 @@ unsafe impl cortex_m::interrupt::Nr for NrWrap { | |||
| 80 | } | 86 | } |
| 81 | } | 87 | } |
| 82 | 88 | ||
| 89 | /// Creates a future that completes when the specified Interrupt is triggered. | ||
| 90 | /// | ||
| 91 | /// The input handler is unregistered when this Future is dropped. | ||
| 92 | /// | ||
| 93 | /// Example: | ||
| 94 | /// ``` no_compile | ||
| 95 | /// use embassy::traits::*; | ||
| 96 | /// use embassy::util::InterruptFuture; | ||
| 97 | /// use embassy::executor::task; | ||
| 98 | /// use embassy_stm32f4::interrupt; // Adjust this to your MCU's embassy HAL. | ||
| 99 | /// #[task] | ||
| 100 | /// async fn demo_interrupt_future() { | ||
| 101 | /// // Using STM32f446 interrupt names, adjust this to your application as necessary. | ||
| 102 | /// // Wait for TIM2 to tick. | ||
| 103 | /// let mut tim2_interrupt = interrupt::take!(TIM2); | ||
| 104 | /// InterruptFuture::new(&mut tim2_interrupt).await; | ||
| 105 | /// // TIM2 interrupt went off, do something... | ||
| 106 | /// } | ||
| 107 | /// ``` | ||
| 83 | pub struct InterruptFuture<'a, I: Interrupt> { | 108 | pub struct InterruptFuture<'a, I: Interrupt> { |
| 84 | interrupt: &'a mut I, | 109 | interrupt: &'a mut I, |
| 85 | } | 110 | } |
