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