common: Initialize PeripheralMutex state with closure to ensure it's done in-place.
This commit is contained in:
parent
e238079d7d
commit
3f28bb6c77
@ -50,19 +50,23 @@ pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
|
impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
|
||||||
/// Create a new `PeripheralMutex` wrapping `irq`, with the initial state `state`.
|
/// Create a new `PeripheralMutex` wrapping `irq`, with `init` initializing the initial state.
|
||||||
///
|
///
|
||||||
/// self requires `state` to live for `'static`, because if the `PeripheralMutex` is leaked, the
|
/// self requires `S` to live for `'static`, because if the `PeripheralMutex` is leaked, the
|
||||||
/// interrupt won't be disabled, which may try accessing the state at any time. To use non-`'static`
|
/// interrupt won't be disabled, which may try accessing the state at any time. To use non-`'static`
|
||||||
/// state, see [`Self::new_unchecked`].
|
/// state, see [`Self::new_unchecked`].
|
||||||
///
|
///
|
||||||
/// Registers `on_interrupt` as the `irq`'s handler, and enables it.
|
/// Registers `on_interrupt` as the `irq`'s handler, and enables it.
|
||||||
pub fn new(storage: &'a mut StateStorage<S>, state: S, irq: S::Interrupt) -> Self
|
pub fn new(
|
||||||
|
irq: S::Interrupt,
|
||||||
|
storage: &'a mut StateStorage<S>,
|
||||||
|
init: impl FnOnce() -> S,
|
||||||
|
) -> Self
|
||||||
where
|
where
|
||||||
'a: 'static,
|
'a: 'static,
|
||||||
{
|
{
|
||||||
// safety: safe because state is `'static`.
|
// safety: safe because state is `'static`.
|
||||||
unsafe { Self::new_unchecked(storage, state, irq) }
|
unsafe { Self::new_unchecked(irq, storage, init) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `PeripheralMutex` without requiring the state is `'static`.
|
/// Create a `PeripheralMutex` without requiring the state is `'static`.
|
||||||
@ -72,9 +76,9 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// The created instance must not be leaked (its `drop` must run).
|
/// The created instance must not be leaked (its `drop` must run).
|
||||||
pub unsafe fn new_unchecked(
|
pub unsafe fn new_unchecked(
|
||||||
storage: &'a mut StateStorage<S>,
|
|
||||||
state: S,
|
|
||||||
irq: S::Interrupt,
|
irq: S::Interrupt,
|
||||||
|
storage: &'a mut StateStorage<S>,
|
||||||
|
init: impl FnOnce() -> S,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if can_be_preempted(&irq) {
|
if can_be_preempted(&irq) {
|
||||||
panic!("`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps");
|
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> {
|
|||||||
|
|
||||||
// Safety: The pointer is valid and not used by anyone else
|
// Safety: The pointer is valid and not used by anyone else
|
||||||
// because we have the `&mut StateStorage`.
|
// because we have the `&mut StateStorage`.
|
||||||
state_ptr.write(state);
|
state_ptr.write(init());
|
||||||
|
|
||||||
irq.disable();
|
irq.disable();
|
||||||
irq.set_handler(|p| {
|
irq.set_handler(|p| {
|
||||||
|
@ -67,12 +67,11 @@ where
|
|||||||
class_set: S,
|
class_set: S,
|
||||||
irq: I,
|
irq: I,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let initial_state = StateInner {
|
let mutex = PeripheralMutex::new_unchecked(irq, &mut state.0, || StateInner {
|
||||||
device,
|
device,
|
||||||
classes: class_set.into_class_set(),
|
classes: class_set.into_class_set(),
|
||||||
_interrupt: PhantomData,
|
_interrupt: PhantomData,
|
||||||
};
|
});
|
||||||
let mutex = PeripheralMutex::new_unchecked(&mut state.0, initial_state, irq);
|
|
||||||
Self {
|
Self {
|
||||||
inner: RefCell::new(mutex),
|
inner: RefCell::new(mutex),
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||||||
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
|
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
|
||||||
ppi_ch2.enable();
|
ppi_ch2.enable();
|
||||||
|
|
||||||
let initial_state = StateInner {
|
Self {
|
||||||
|
inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
timer,
|
timer,
|
||||||
_ppi_ch1: ppi_ch1,
|
_ppi_ch1: ppi_ch1,
|
||||||
@ -168,10 +169,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||||||
tx: RingBuffer::new(tx_buffer),
|
tx: RingBuffer::new(tx_buffer),
|
||||||
tx_state: TxState::Idle,
|
tx_state: TxState::Idle,
|
||||||
tx_waker: WakerRegistration::new(),
|
tx_waker: WakerRegistration::new(),
|
||||||
};
|
}),
|
||||||
|
|
||||||
Self {
|
|
||||||
inner: PeripheralMutex::new_unchecked(&mut state.0, initial_state, irq),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +78,8 @@ impl<'d, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, P, TX, RX> {
|
|||||||
tx_d1.configure();
|
tx_d1.configure();
|
||||||
tx_en.configure();
|
tx_en.configure();
|
||||||
|
|
||||||
let inner = Inner::new(peri);
|
|
||||||
|
|
||||||
// NOTE(unsafe) We are ourselves not leak-safe.
|
// NOTE(unsafe) We are ourselves not leak-safe.
|
||||||
let state = PeripheralMutex::new_unchecked(&mut state.0, inner, interrupt);
|
let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri));
|
||||||
|
|
||||||
// NOTE(unsafe) We have exclusive access to the registers
|
// NOTE(unsafe) We have exclusive access to the registers
|
||||||
let dma = ETH.ethernet_dma();
|
let dma = ETH.ethernet_dma();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user