aboutsummaryrefslogtreecommitdiff
path: root/embassy-extras
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-26 23:20:27 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:58 +0200
commiteedb51bbb63677f53cfdfb4d0e342981a4866df7 (patch)
tree6185d8cad32b63c3a3611a40a1bf82fabe310fe0 /embassy-extras
parent53645d9d38bcb5904f1deba2cfa4e6719da2bc58 (diff)
extras: add Peripheral with shared state (like PeripheralMutex but without mutex)
Diffstat (limited to 'embassy-extras')
-rw-r--r--embassy-extras/src/lib.rs1
-rw-r--r--embassy-extras/src/peripheral_shared.rs68
2 files changed, 69 insertions, 0 deletions
diff --git a/embassy-extras/src/lib.rs b/embassy-extras/src/lib.rs
index 5dafba702..be08ddf1e 100644
--- a/embassy-extras/src/lib.rs
+++ b/embassy-extras/src/lib.rs
@@ -5,6 +5,7 @@ pub(crate) mod fmt;
5 5
6mod macros; 6mod macros;
7pub mod peripheral; 7pub mod peripheral;
8pub mod peripheral_shared;
8pub mod ring_buffer; 9pub mod ring_buffer;
9pub mod usb; 10pub mod usb;
10 11
diff --git a/embassy-extras/src/peripheral_shared.rs b/embassy-extras/src/peripheral_shared.rs
new file mode 100644
index 000000000..73906698e
--- /dev/null
+++ b/embassy-extras/src/peripheral_shared.rs
@@ -0,0 +1,68 @@
1use core::cell::UnsafeCell;
2use core::marker::{PhantomData, PhantomPinned};
3use core::pin::Pin;
4use core::sync::atomic::{compiler_fence, Ordering};
5
6use embassy::interrupt::{Interrupt, InterruptExt};
7
8pub trait PeripheralState {
9 type Interrupt: Interrupt;
10 fn on_interrupt(&self);
11}
12
13pub struct Peripheral<S: PeripheralState> {
14 state: UnsafeCell<S>,
15
16 irq_setup_done: bool,
17 irq: S::Interrupt,
18
19 _not_send: PhantomData<*mut ()>,
20 _pinned: PhantomPinned,
21}
22
23impl<S: PeripheralState> Peripheral<S> {
24 pub fn new(irq: S::Interrupt, state: S) -> Self {
25 Self {
26 irq,
27 irq_setup_done: false,
28
29 state: UnsafeCell::new(state),
30 _not_send: PhantomData,
31 _pinned: PhantomPinned,
32 }
33 }
34
35 pub fn register_interrupt(self: Pin<&mut Self>) {
36 let this = unsafe { self.get_unchecked_mut() };
37 if this.irq_setup_done {
38 return;
39 }
40
41 this.irq.disable();
42 compiler_fence(Ordering::SeqCst);
43
44 this.irq.set_handler(|p| {
45 let state = unsafe { &*(p as *const S) };
46 state.on_interrupt();
47 });
48 this.irq
49 .set_handler_context((&this.state) as *const _ as *mut ());
50
51 compiler_fence(Ordering::SeqCst);
52 this.irq.enable();
53
54 this.irq_setup_done = true;
55 }
56
57 pub fn state(self: Pin<&mut Self>) -> &S {
58 let this = unsafe { self.get_unchecked_mut() };
59 unsafe { &*this.state.get() }
60 }
61}
62
63impl<S: PeripheralState> Drop for Peripheral<S> {
64 fn drop(&mut self) {
65 self.irq.disable();
66 self.irq.remove_handler();
67 }
68}