aboutsummaryrefslogtreecommitdiff
path: root/embassy-hal-common
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-08-02 20:13:41 +0200
committerDario Nieuwenhuis <[email protected]>2021-08-02 20:13:41 +0200
commit3f28bb6c77de3d8ecbb6d401f107586f24e416a4 (patch)
treeda16008285a54746a07bdf7881a4fce4cbf8d23e /embassy-hal-common
parente238079d7d921cab589eb6106059d4fb0b12ce1c (diff)
common: Initialize PeripheralMutex state with closure to ensure it's done in-place.
Diffstat (limited to 'embassy-hal-common')
-rw-r--r--embassy-hal-common/src/peripheral.rs18
-rw-r--r--embassy-hal-common/src/usb/mod.rs5
2 files changed, 13 insertions, 10 deletions
diff --git a/embassy-hal-common/src/peripheral.rs b/embassy-hal-common/src/peripheral.rs
index 46c6ebeee..dcf9d3a27 100644
--- a/embassy-hal-common/src/peripheral.rs
+++ b/embassy-hal-common/src/peripheral.rs
@@ -50,19 +50,23 @@ pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
50} 50}
51 51
52impl<'a, S: PeripheralState> PeripheralMutex<'a, S> { 52impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
53 /// Create a new `PeripheralMutex` wrapping `irq`, with the initial state `state`. 53 /// Create a new `PeripheralMutex` wrapping `irq`, with `init` initializing the initial state.
54 /// 54 ///
55 /// self requires `state` to live for `'static`, because if the `PeripheralMutex` is leaked, the 55 /// self requires `S` to live for `'static`, because if the `PeripheralMutex` is leaked, the
56 /// interrupt won't be disabled, which may try accessing the state at any time. To use non-`'static` 56 /// interrupt won't be disabled, which may try accessing the state at any time. To use non-`'static`
57 /// state, see [`Self::new_unchecked`]. 57 /// state, see [`Self::new_unchecked`].
58 /// 58 ///
59 /// Registers `on_interrupt` as the `irq`'s handler, and enables it. 59 /// Registers `on_interrupt` as the `irq`'s handler, and enables it.
60 pub fn new(storage: &'a mut StateStorage<S>, state: S, irq: S::Interrupt) -> Self 60 pub fn new(
61 irq: S::Interrupt,
62 storage: &'a mut StateStorage<S>,
63 init: impl FnOnce() -> S,
64 ) -> Self
61 where 65 where
62 'a: 'static, 66 'a: 'static,
63 { 67 {
64 // safety: safe because state is `'static`. 68 // safety: safe because state is `'static`.
65 unsafe { Self::new_unchecked(storage, state, irq) } 69 unsafe { Self::new_unchecked(irq, storage, init) }
66 } 70 }
67 71
68 /// Create a `PeripheralMutex` without requiring the state is `'static`. 72 /// Create a `PeripheralMutex` without requiring the state is `'static`.
@@ -72,9 +76,9 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
72 /// # Safety 76 /// # Safety
73 /// The created instance must not be leaked (its `drop` must run). 77 /// The created instance must not be leaked (its `drop` must run).
74 pub unsafe fn new_unchecked( 78 pub unsafe fn new_unchecked(
75 storage: &'a mut StateStorage<S>,
76 state: S,
77 irq: S::Interrupt, 79 irq: S::Interrupt,
80 storage: &'a mut StateStorage<S>,
81 init: impl FnOnce() -> S,
78 ) -> Self { 82 ) -> Self {
79 if can_be_preempted(&irq) { 83 if can_be_preempted(&irq) {
80 panic!("`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps"); 84 panic!("`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps");
@@ -84,7 +88,7 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
84 88
85 // Safety: The pointer is valid and not used by anyone else 89 // Safety: The pointer is valid and not used by anyone else
86 // because we have the `&mut StateStorage`. 90 // because we have the `&mut StateStorage`.
87 state_ptr.write(state); 91 state_ptr.write(init());
88 92
89 irq.disable(); 93 irq.disable();
90 irq.set_handler(|p| { 94 irq.set_handler(|p| {
diff --git a/embassy-hal-common/src/usb/mod.rs b/embassy-hal-common/src/usb/mod.rs
index ae9f26075..70a74bd52 100644
--- a/embassy-hal-common/src/usb/mod.rs
+++ b/embassy-hal-common/src/usb/mod.rs
@@ -67,12 +67,11 @@ where
67 class_set: S, 67 class_set: S,
68 irq: I, 68 irq: I,
69 ) -> Self { 69 ) -> Self {
70 let initial_state = StateInner { 70 let mutex = PeripheralMutex::new_unchecked(irq, &mut state.0, || StateInner {
71 device, 71 device,
72 classes: class_set.into_class_set(), 72 classes: class_set.into_class_set(),
73 _interrupt: PhantomData, 73 _interrupt: PhantomData,
74 }; 74 });
75 let mutex = PeripheralMutex::new_unchecked(&mut state.0, initial_state, irq);
76 Self { 75 Self {
77 inner: RefCell::new(mutex), 76 inner: RefCell::new(mutex),
78 } 77 }