diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-07-29 17:22:25 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-07-29 17:22:25 +0200 |
| commit | 1ed65cb9e0f495ede0976f83f87b4a987478d466 (patch) | |
| tree | 089a6e1c472b46818c9da1d63941942b2e66196e | |
| parent | 01e0a3928ff612654ece7fc4fac720e30736fee4 (diff) | |
| parent | e13774574f71ffa3f77197592780c102b2a83e25 (diff) | |
Merge pull request #328 from embassy-rs/remove_peripehral_shared
Remove embassy_hal_common::peripheral_shared
| -rw-r--r-- | embassy-hal-common/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-hal-common/src/peripheral_shared.rs | 122 |
2 files changed, 0 insertions, 123 deletions
diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-common/src/lib.rs index 7036986ef..b62ae8b98 100644 --- a/embassy-hal-common/src/lib.rs +++ b/embassy-hal-common/src/lib.rs | |||
| @@ -6,7 +6,6 @@ pub(crate) mod fmt; | |||
| 6 | pub mod interrupt; | 6 | pub mod interrupt; |
| 7 | mod macros; | 7 | mod macros; |
| 8 | pub mod peripheral; | 8 | pub mod peripheral; |
| 9 | pub mod peripheral_shared; | ||
| 10 | pub mod ring_buffer; | 9 | pub mod ring_buffer; |
| 11 | pub mod usb; | 10 | pub mod usb; |
| 12 | 11 | ||
diff --git a/embassy-hal-common/src/peripheral_shared.rs b/embassy-hal-common/src/peripheral_shared.rs deleted file mode 100644 index 71d746341..000000000 --- a/embassy-hal-common/src/peripheral_shared.rs +++ /dev/null | |||
| @@ -1,122 +0,0 @@ | |||
| 1 | use core::marker::{PhantomData, PhantomPinned}; | ||
| 2 | use core::pin::Pin; | ||
| 3 | |||
| 4 | use embassy::interrupt::{Interrupt, InterruptExt}; | ||
| 5 | |||
| 6 | use crate::peripheral::can_be_preempted; | ||
| 7 | |||
| 8 | /// A type which can be used as state with `Peripheral`. | ||
| 9 | /// | ||
| 10 | /// It needs to be `Sync` because references are shared between the 'thread' which owns the `Peripheral` and the interrupt. | ||
| 11 | /// | ||
| 12 | /// It also requires `'static` to be used safely with `Peripheral::register_interrupt`, | ||
| 13 | /// because although `Pin` guarantees that the memory of the state won't be invalidated, | ||
| 14 | /// it doesn't guarantee that the lifetime will last. | ||
| 15 | pub trait PeripheralState: Sync { | ||
| 16 | type Interrupt: Interrupt; | ||
| 17 | fn on_interrupt(&self); | ||
| 18 | } | ||
| 19 | |||
| 20 | pub struct Peripheral<S: PeripheralState> { | ||
| 21 | state: S, | ||
| 22 | |||
| 23 | irq_setup_done: bool, | ||
| 24 | irq: S::Interrupt, | ||
| 25 | |||
| 26 | _not_send: PhantomData<*mut ()>, | ||
| 27 | _pinned: PhantomPinned, | ||
| 28 | } | ||
| 29 | |||
| 30 | impl<S: PeripheralState + 'static> Peripheral<S> { | ||
| 31 | /// Registers `on_interrupt` as the wrapped interrupt's interrupt handler and enables it. | ||
| 32 | /// | ||
| 33 | /// This requires this `Peripheral`'s `PeripheralState` to live for `'static`, | ||
| 34 | /// because `Pin` only guarantees that it's memory won't be repurposed, | ||
| 35 | /// not that it's lifetime will last. | ||
| 36 | /// | ||
| 37 | /// To use non-`'static` `PeripheralState`, use the unsafe `register_interrupt_unchecked`. | ||
| 38 | /// | ||
| 39 | /// Note: `'static` doesn't mean it _has_ to live for the entire program, like an `&'static T`; | ||
| 40 | /// it just means it _can_ live for the entire program - for example, `u8` lives for `'static`. | ||
| 41 | pub fn register_interrupt(self: Pin<&mut Self>) { | ||
| 42 | // SAFETY: `S: 'static`, so there's no way it's lifetime can expire. | ||
| 43 | unsafe { self.register_interrupt_unchecked() } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | impl<S: PeripheralState> Peripheral<S> { | ||
| 48 | pub fn new(irq: S::Interrupt, state: S) -> Self { | ||
| 49 | if can_be_preempted(&irq) { | ||
| 50 | panic!("`Peripheral` cannot be created in an interrupt with higher priority than the interrupt it wraps"); | ||
| 51 | } | ||
| 52 | |||
| 53 | Self { | ||
| 54 | irq, | ||
| 55 | irq_setup_done: false, | ||
| 56 | |||
| 57 | state, | ||
| 58 | _not_send: PhantomData, | ||
| 59 | _pinned: PhantomPinned, | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Registers `on_interrupt` as the wrapped interrupt's interrupt handler and enables it. | ||
| 64 | /// | ||
| 65 | /// # Safety | ||
| 66 | /// The lifetime of any data in `PeripheralState` that is accessed by the interrupt handler | ||
| 67 | /// must not end without `Drop` being called on this `Peripheral`. | ||
| 68 | /// | ||
| 69 | /// This can be accomplished by either not accessing any data with a lifetime in `on_interrupt`, | ||
| 70 | /// or making sure that nothing like `mem::forget` is used on the `Peripheral`. | ||
| 71 | pub unsafe fn register_interrupt_unchecked(self: Pin<&mut Self>) { | ||
| 72 | let this = self.get_unchecked_mut(); | ||
| 73 | if this.irq_setup_done { | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | |||
| 77 | this.irq.disable(); | ||
| 78 | this.irq.set_handler(|p| { | ||
| 79 | // The state can't have been dropped, otherwise the interrupt would have been disabled. | ||
| 80 | // We checked in `new` that the thread owning the `Peripheral` can't preempt the interrupt, | ||
| 81 | // so someone can't have preempted us before this point and dropped the `Peripheral`. | ||
| 82 | let state = unsafe { &*(p as *const S) }; | ||
| 83 | state.on_interrupt(); | ||
| 84 | }); | ||
| 85 | this.irq | ||
| 86 | .set_handler_context((&this.state) as *const _ as *mut ()); | ||
| 87 | this.irq.enable(); | ||
| 88 | |||
| 89 | this.irq_setup_done = true; | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn state(self: Pin<&mut Self>) -> &S { | ||
| 93 | &self.into_ref().get_ref().state | ||
| 94 | } | ||
| 95 | |||
| 96 | /// Returns whether the wrapped interrupt is currently in a pending state. | ||
| 97 | pub fn is_pending(&self) -> bool { | ||
| 98 | self.irq.is_pending() | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Forces the wrapped interrupt into a pending state. | ||
| 102 | pub fn pend(&self) { | ||
| 103 | self.irq.pend() | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Forces the wrapped interrupt out of a pending state. | ||
| 107 | pub fn unpend(&self) { | ||
| 108 | self.irq.unpend() | ||
| 109 | } | ||
| 110 | |||
| 111 | /// Gets the priority of the wrapped interrupt. | ||
| 112 | pub fn priority(&self) -> <S::Interrupt as Interrupt>::Priority { | ||
| 113 | self.irq.get_priority() | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | impl<S: PeripheralState> Drop for Peripheral<S> { | ||
| 118 | fn drop(&mut self) { | ||
| 119 | self.irq.disable(); | ||
| 120 | self.irq.remove_handler(); | ||
| 121 | } | ||
| 122 | } | ||
