common/PeripheralMutex: remove unsafe API. (#802)
Following the project's decision that "leak unsafe" APIs are not marked as "unsafe", update PeripheralMutex to accept non-'static state without unsafe. Fixes #801
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							77c7d8f31b
						
					
				
				
					commit
					db344c2bda
				
			@@ -52,33 +52,11 @@ pub(crate) fn can_be_preempted(irq: &impl Interrupt) -> bool {
 | 
			
		||||
impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
 | 
			
		||||
    /// Create a new `PeripheralMutex` wrapping `irq`, with `init` initializing the initial state.
 | 
			
		||||
    ///
 | 
			
		||||
    /// 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`
 | 
			
		||||
    /// state, see [`Self::new_unchecked`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// Registers `on_interrupt` as the `irq`'s handler, and enables it.
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        irq: S::Interrupt,
 | 
			
		||||
        storage: &'a mut StateStorage<S>,
 | 
			
		||||
        init: impl FnOnce() -> S,
 | 
			
		||||
    ) -> Self
 | 
			
		||||
    where
 | 
			
		||||
        'a: 'static,
 | 
			
		||||
    {
 | 
			
		||||
        // safety: safe because state is `'static`.
 | 
			
		||||
        unsafe { Self::new_unchecked(irq, storage, init) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create a `PeripheralMutex` without requiring the state is `'static`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// See also [`Self::new`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    /// The created instance must not be leaked (its `drop` must run).
 | 
			
		||||
    pub unsafe fn new_unchecked(
 | 
			
		||||
        irq: S::Interrupt,
 | 
			
		||||
        storage: &'a mut StateStorage<S>,
 | 
			
		||||
        init: impl FnOnce() -> S,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        if can_be_preempted(&irq) {
 | 
			
		||||
            panic!("`PeripheralMutex` cannot be created in an interrupt with higher priority than the interrupt it wraps");
 | 
			
		||||
@@ -88,10 +66,10 @@ impl<'a, S: PeripheralState> PeripheralMutex<'a, S> {
 | 
			
		||||
 | 
			
		||||
        // Safety: The pointer is valid and not used by anyone else
 | 
			
		||||
        // because we have the `&mut StateStorage`.
 | 
			
		||||
        state_ptr.write(init());
 | 
			
		||||
        unsafe { state_ptr.write(init()) };
 | 
			
		||||
 | 
			
		||||
        irq.disable();
 | 
			
		||||
        irq.set_handler(|p| {
 | 
			
		||||
        irq.set_handler(|p| unsafe {
 | 
			
		||||
            // Safety: it's OK to get a &mut to the state, since
 | 
			
		||||
            // - We checked that the thread owning the `PeripheralMutex` can't preempt us in `new`.
 | 
			
		||||
            //   Interrupts' priorities can only be changed with raw embassy `Interrupts`,
 | 
			
		||||
 
 | 
			
		||||
@@ -164,8 +164,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
 | 
			
		||||
        ppi_ch2.enable();
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            inner: unsafe {
 | 
			
		||||
                PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
 | 
			
		||||
            inner: PeripheralMutex::new(irq, &mut state.0, move || StateInner {
 | 
			
		||||
                phantom: PhantomData,
 | 
			
		||||
                timer,
 | 
			
		||||
                _ppi_ch1: ppi_ch1,
 | 
			
		||||
@@ -178,8 +177,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
 | 
			
		||||
                tx: RingBuffer::new(tx_buffer),
 | 
			
		||||
                tx_state: TxState::Idle,
 | 
			
		||||
                tx_waker: WakerRegistration::new(),
 | 
			
		||||
                })
 | 
			
		||||
            },
 | 
			
		||||
            }),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -146,7 +146,7 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T,
 | 
			
		||||
        config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
 | 
			
		||||
 | 
			
		||||
        // NOTE(unsafe) We are ourselves not leak-safe.
 | 
			
		||||
        let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri));
 | 
			
		||||
        let state = PeripheralMutex::new(interrupt, &mut state.0, || Inner::new(peri));
 | 
			
		||||
 | 
			
		||||
        // NOTE(unsafe) We have exclusive access to the registers
 | 
			
		||||
        let dma = ETH.ethernet_dma();
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T,
 | 
			
		||||
        config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
 | 
			
		||||
 | 
			
		||||
        // NOTE(unsafe) We are ourselves not leak-safe.
 | 
			
		||||
        let state = PeripheralMutex::new_unchecked(interrupt, &mut state.0, || Inner::new(peri));
 | 
			
		||||
        let state = PeripheralMutex::new(interrupt, &mut state.0, || Inner::new(peri));
 | 
			
		||||
 | 
			
		||||
        // NOTE(unsafe) We have exclusive access to the registers
 | 
			
		||||
        let dma = ETH.ethernet_dma();
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ pub struct BufferedUart<'d, T: Instance> {
 | 
			
		||||
impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
 | 
			
		||||
 | 
			
		||||
impl<'d, T: Instance> BufferedUart<'d, T> {
 | 
			
		||||
    pub unsafe fn new(
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        state: &'d mut State<'d, T>,
 | 
			
		||||
        _uart: Uart<'d, T, NoDma, NoDma>,
 | 
			
		||||
        irq: impl Unborrow<Target = T::Interrupt> + 'd,
 | 
			
		||||
@@ -45,13 +45,15 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
 | 
			
		||||
        unborrow!(irq);
 | 
			
		||||
 | 
			
		||||
        let r = T::regs();
 | 
			
		||||
        unsafe {
 | 
			
		||||
            r.cr1().modify(|w| {
 | 
			
		||||
                w.set_rxneie(true);
 | 
			
		||||
                w.set_idleie(true);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner {
 | 
			
		||||
            inner: PeripheralMutex::new(irq, &mut state.0, move || StateInner {
 | 
			
		||||
                phantom: PhantomData,
 | 
			
		||||
                tx: RingBuffer::new(tx_buffer),
 | 
			
		||||
                tx_waker: WakerRegistration::new(),
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
 | 
			
		||||
    let irq = interrupt::take!(USART3);
 | 
			
		||||
    let mut tx_buf = [0u8; 32];
 | 
			
		||||
    let mut rx_buf = [0u8; 32];
 | 
			
		||||
    let mut buf_usart =
 | 
			
		||||
        unsafe { BufferedUart::new(&mut state, usart, irq, &mut tx_buf, &mut rx_buf) };
 | 
			
		||||
    let mut buf_usart = BufferedUart::new(&mut state, usart, irq, &mut tx_buf, &mut rx_buf);
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let buf = buf_usart.fill_buf().await.unwrap();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user