BXCAN: Create RxMode enum and move reader methods into it, laying foundations for different Rx buffering modes.
This commit is contained in:
		
							parent
							
								
									3bdaad39e8
								
							
						
					
					
						commit
						26c739c2f9
					
				@ -585,6 +585,16 @@ impl Registers {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn receive_frame_available(&self) -> bool {
 | 
				
			||||||
 | 
					        if self.canregs.rfr(0).read().fmp() != 0 {
 | 
				
			||||||
 | 
					            true
 | 
				
			||||||
 | 
					        } else if self.canregs.rfr(1).read().fmp() != 0 {
 | 
				
			||||||
 | 
					            true
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
 | 
					    pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
 | 
				
			||||||
        // Generate timestamp as early as possible
 | 
					        // Generate timestamp as early as possible
 | 
				
			||||||
        #[cfg(feature = "time")]
 | 
					        #[cfg(feature = "time")]
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,6 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
 | 
				
			|||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 | 
					use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 | 
				
			||||||
use embassy_sync::channel::Channel;
 | 
					use embassy_sync::channel::Channel;
 | 
				
			||||||
use embassy_sync::waitqueue::AtomicWaker;
 | 
					use embassy_sync::waitqueue::AtomicWaker;
 | 
				
			||||||
use futures::FutureExt;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::gpio::AFType;
 | 
					use crate::gpio::AFType;
 | 
				
			||||||
use crate::interrupt::typelevel::Interrupt;
 | 
					use crate::interrupt::typelevel::Interrupt;
 | 
				
			||||||
@ -22,6 +21,9 @@ use enums::*;
 | 
				
			|||||||
pub mod frame;
 | 
					pub mod frame;
 | 
				
			||||||
pub mod util;
 | 
					pub mod util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod common;
 | 
				
			||||||
 | 
					pub use self::common::{BufferedCanReceiver, BufferedCanSender, Timestamp};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Contains CAN frame and additional metadata.
 | 
					/// Contains CAN frame and additional metadata.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Timestamp is available if `time` feature is enabled.
 | 
					/// Timestamp is available if `time` feature is enabled.
 | 
				
			||||||
@ -59,8 +61,7 @@ pub struct Rx0InterruptHandler<T: Instance> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
 | 
					impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
 | 
				
			||||||
    unsafe fn on_interrupt() {
 | 
					    unsafe fn on_interrupt() {
 | 
				
			||||||
        // info!("rx0 irq");
 | 
					        T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo0);
 | 
				
			||||||
        Can::<T>::receive_fifo(RxFifo::Fifo0);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -71,8 +72,7 @@ pub struct Rx1InterruptHandler<T: Instance> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
 | 
					impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
 | 
				
			||||||
    unsafe fn on_interrupt() {
 | 
					    unsafe fn on_interrupt() {
 | 
				
			||||||
        // info!("rx1 irq");
 | 
					        T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo1);
 | 
				
			||||||
        Can::<T>::receive_fifo(RxFifo::Fifo1);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,16 +99,6 @@ pub struct Can<'d, T: Instance> {
 | 
				
			|||||||
    can: crate::can::bx::Can<BxcanInstance<'d, T>>,
 | 
					    can: crate::can::bx::Can<BxcanInstance<'d, T>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Error returned by `try_read`
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					 | 
				
			||||||
pub enum TryReadError {
 | 
					 | 
				
			||||||
    /// Bus error
 | 
					 | 
				
			||||||
    BusError(BusError),
 | 
					 | 
				
			||||||
    /// Receive buffer is empty
 | 
					 | 
				
			||||||
    Empty,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Error returned by `try_write`
 | 
					/// Error returned by `try_write`
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
@ -226,34 +216,19 @@ impl<'d, T: Instance> Can<'d, T> {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// Returns a tuple of the time the message was received and the message frame
 | 
					    /// Returns a tuple of the time the message was received and the message frame
 | 
				
			||||||
    pub async fn read(&mut self) -> Result<Envelope, BusError> {
 | 
					    pub async fn read(&mut self) -> Result<Envelope, BusError> {
 | 
				
			||||||
        self.split().1.read().await
 | 
					        T::state().rx_mode.read::<T>().await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Attempts to read a CAN frame without blocking.
 | 
					    /// Attempts to read a CAN frame without blocking.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
 | 
					    /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
 | 
				
			||||||
    pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
 | 
					    pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
 | 
				
			||||||
        self.split().1.try_read()
 | 
					        T::state().rx_mode.try_read::<T>()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Waits while receive queue is empty.
 | 
					    /// Waits while receive queue is empty.
 | 
				
			||||||
    pub async fn wait_not_empty(&mut self) {
 | 
					    pub async fn wait_not_empty(&mut self) {
 | 
				
			||||||
        self.split().1.wait_not_empty().await
 | 
					        T::state().rx_mode.wait_not_empty::<T>().await
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unsafe fn receive_fifo(fifo: RxFifo) {
 | 
					 | 
				
			||||||
        let state = T::state();
 | 
					 | 
				
			||||||
        let regsisters = crate::can::bx::Registers { canregs: T::regs() };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        loop {
 | 
					 | 
				
			||||||
            match regsisters.receive_fifo(fifo) {
 | 
					 | 
				
			||||||
                Some(envelope) => {
 | 
					 | 
				
			||||||
                    // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
 | 
					 | 
				
			||||||
                    let _ = state.rx_queue.try_send(envelope);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                None => return,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Split the CAN driver into transmit and receive halves.
 | 
					    /// Split the CAN driver into transmit and receive halves.
 | 
				
			||||||
@ -375,51 +350,95 @@ impl<'d, T: Instance> CanRx<'d, T> {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// Returns a tuple of the time the message was received and the message frame
 | 
					    /// Returns a tuple of the time the message was received and the message frame
 | 
				
			||||||
    pub async fn read(&mut self) -> Result<Envelope, BusError> {
 | 
					    pub async fn read(&mut self) -> Result<Envelope, BusError> {
 | 
				
			||||||
        poll_fn(|cx| {
 | 
					        T::state().rx_mode.read::<T>().await
 | 
				
			||||||
            T::state().err_waker.register(cx.waker());
 | 
					 | 
				
			||||||
            if let Poll::Ready(envelope) = T::state().rx_queue.receive().poll_unpin(cx) {
 | 
					 | 
				
			||||||
                return Poll::Ready(Ok(envelope));
 | 
					 | 
				
			||||||
            } else if let Some(err) = self.curr_error() {
 | 
					 | 
				
			||||||
                return Poll::Ready(Err(err));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Poll::Pending
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Attempts to read a CAN frame without blocking.
 | 
					    /// Attempts to read a CAN frame without blocking.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
 | 
					    /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
 | 
				
			||||||
    pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
 | 
					    pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
 | 
				
			||||||
        if let Ok(envelope) = T::state().rx_queue.try_receive() {
 | 
					        T::state().rx_mode.try_read::<T>()
 | 
				
			||||||
            return Ok(envelope);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if let Some(err) = self.curr_error() {
 | 
					 | 
				
			||||||
            return Err(TryReadError::BusError(err));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Err(TryReadError::Empty)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Waits while receive queue is empty.
 | 
					    /// Waits while receive queue is empty.
 | 
				
			||||||
    pub async fn wait_not_empty(&mut self) {
 | 
					    pub async fn wait_not_empty(&mut self) {
 | 
				
			||||||
        poll_fn(|cx| T::state().rx_queue.poll_ready_to_receive(cx)).await
 | 
					        T::state().rx_mode.wait_not_empty::<T>().await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn curr_error(&self) -> Option<BusError> {
 | 
					    /// Return a buffered instance of driver without CAN FD support. User must supply Buffers
 | 
				
			||||||
        let err = { T::regs().esr().read() };
 | 
					    pub fn buffered<const RX_BUF_SIZE: usize>(
 | 
				
			||||||
        if err.boff() {
 | 
					        self,
 | 
				
			||||||
            return Some(BusError::BusOff);
 | 
					        rxb: &'static mut RxBuf<RX_BUF_SIZE>,
 | 
				
			||||||
        } else if err.epvf() {
 | 
					    ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
 | 
				
			||||||
            return Some(BusError::BusPassive);
 | 
					        BufferedCanRx::new(self.rx, rxb)
 | 
				
			||||||
        } else if err.ewgf() {
 | 
					    }
 | 
				
			||||||
            return Some(BusError::BusWarning);
 | 
					}
 | 
				
			||||||
        } else if let Some(err) = err.lec().into_bus_err() {
 | 
					
 | 
				
			||||||
            return Some(err);
 | 
					/// User supplied buffer for RX Buffering
 | 
				
			||||||
 | 
					pub type RxBuf<const BUF_SIZE: usize> =
 | 
				
			||||||
 | 
					    Channel<CriticalSectionRawMutex, Result<(Frame, Timestamp), BusError>, BUF_SIZE>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// CAN driver, receive half in Buffered mode.
 | 
				
			||||||
 | 
					pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
 | 
				
			||||||
 | 
					    _rx: crate::can::bx::Rx<BxcanInstance<'d, T>>,
 | 
				
			||||||
 | 
					    rx_buf: &'static RxBuf<RX_BUF_SIZE>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
 | 
				
			||||||
 | 
					    fn new(_rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
 | 
				
			||||||
 | 
					        BufferedCanRx { _rx, rx_buf }.setup()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn setup(self) -> Self {
 | 
				
			||||||
 | 
					        // We don't want interrupts being processed while we change modes.
 | 
				
			||||||
 | 
					        critical_section::with(|_| unsafe {
 | 
				
			||||||
 | 
					            let rx_inner = self::common::ClassicBufferedRxInner {
 | 
				
			||||||
 | 
					                rx_sender: self.rx_buf.sender().into(),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Async read frame from RX buffer.
 | 
				
			||||||
 | 
					    pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> {
 | 
				
			||||||
 | 
					        self.rx_buf.receive().await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Attempts to read a CAN frame without blocking.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
 | 
				
			||||||
 | 
					    pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
 | 
				
			||||||
 | 
					        match &T::state().rx_mode {
 | 
				
			||||||
 | 
					            RxMode::Buffered(_) => {
 | 
				
			||||||
 | 
					                if let Ok(result) = self.rx_buf.try_receive() {
 | 
				
			||||||
 | 
					                    match result {
 | 
				
			||||||
 | 
					                        Ok((frame, ts)) => Ok(Envelope { ts, frame }),
 | 
				
			||||||
 | 
					                        Err(e) => Err(TryReadError::BusError(e)),
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    let registers = crate::can::bx::Registers { canregs: T::regs() };
 | 
				
			||||||
 | 
					                    if let Some(err) = registers.curr_error() {
 | 
				
			||||||
 | 
					                        return Err(TryReadError::BusError(err));
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Err(TryReadError::Empty)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {
 | 
				
			||||||
 | 
					                panic!("Bad Mode")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        None
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Waits while receive queue is empty.
 | 
				
			||||||
 | 
					    pub async fn wait_not_empty(&mut self) {
 | 
				
			||||||
 | 
					        poll_fn(|cx| self.rx_buf.poll_ready_to_receive(cx)).await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
 | 
				
			||||||
 | 
					    pub fn reader(&self) -> BufferedCanReceiver {
 | 
				
			||||||
 | 
					        self.rx_buf.receiver().into()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -448,10 +467,111 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::can::enums::{BusError, TryReadError};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) enum RxMode {
 | 
				
			||||||
 | 
					    NonBuffered(AtomicWaker),
 | 
				
			||||||
 | 
					    Buffered(crate::can::_version::common::ClassicBufferedRxInner),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl RxMode {
 | 
				
			||||||
 | 
					    pub fn on_interrupt<T: Instance>(&self, fifo: crate::can::_version::bx::RxFifo) {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::NonBuffered(waker) => {
 | 
				
			||||||
 | 
					                // Disable interrupts until read
 | 
				
			||||||
 | 
					                let fifo_idx = match fifo {
 | 
				
			||||||
 | 
					                    crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
 | 
				
			||||||
 | 
					                    crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                T::regs().ier().write(|w| {
 | 
				
			||||||
 | 
					                    w.set_fmpie(fifo_idx, false);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                waker.wake();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Self::Buffered(buf) => {
 | 
				
			||||||
 | 
					                let regsisters = crate::can::bx::Registers { canregs: T::regs() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                loop {
 | 
				
			||||||
 | 
					                    match regsisters.receive_fifo(fifo) {
 | 
				
			||||||
 | 
					                        Some(envelope) => {
 | 
				
			||||||
 | 
					                            // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
 | 
				
			||||||
 | 
					                            let _ = buf.rx_sender.try_send(Ok((envelope.frame, envelope.ts)));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        None => return,
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::NonBuffered(waker) => {
 | 
				
			||||||
 | 
					                poll_fn(|cx| {
 | 
				
			||||||
 | 
					                    T::state().err_waker.register(cx.waker());
 | 
				
			||||||
 | 
					                    waker.register(cx.waker());
 | 
				
			||||||
 | 
					                    match self.try_read::<T>() {
 | 
				
			||||||
 | 
					                        Ok(result) => Poll::Ready(Ok(result)),
 | 
				
			||||||
 | 
					                        Err(TryReadError::Empty) => Poll::Pending,
 | 
				
			||||||
 | 
					                        Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .await
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {
 | 
				
			||||||
 | 
					                panic!("Bad Mode")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::NonBuffered(_) => {
 | 
				
			||||||
 | 
					                let registers = crate::can::bx::Registers { canregs: T::regs() };
 | 
				
			||||||
 | 
					                if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo0) {
 | 
				
			||||||
 | 
					                    T::regs().ier().write(|w| {
 | 
				
			||||||
 | 
					                        w.set_fmpie(0, true);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    Ok(msg)
 | 
				
			||||||
 | 
					                } else if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo1) {
 | 
				
			||||||
 | 
					                    T::regs().ier().write(|w| {
 | 
				
			||||||
 | 
					                        w.set_fmpie(1, true);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    Ok(msg)
 | 
				
			||||||
 | 
					                } else if let Some(err) = registers.curr_error() {
 | 
				
			||||||
 | 
					                    Err(TryReadError::BusError(err))
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Err(TryReadError::Empty)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {
 | 
				
			||||||
 | 
					                panic!("Bad Mode")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub async fn wait_not_empty<T: Instance>(&self) {
 | 
				
			||||||
 | 
					        match &T::state().rx_mode {
 | 
				
			||||||
 | 
					            Self::NonBuffered(waker) => {
 | 
				
			||||||
 | 
					                poll_fn(|cx| {
 | 
				
			||||||
 | 
					                    waker.register(cx.waker());
 | 
				
			||||||
 | 
					                    let registers = crate::can::bx::Registers { canregs: T::regs() };
 | 
				
			||||||
 | 
					                    if registers.receive_frame_available() {
 | 
				
			||||||
 | 
					                        Poll::Ready(())
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Poll::Pending
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .await
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {
 | 
				
			||||||
 | 
					                panic!("Bad Mode")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
struct State {
 | 
					struct State {
 | 
				
			||||||
    pub tx_waker: AtomicWaker,
 | 
					    pub tx_waker: AtomicWaker,
 | 
				
			||||||
    pub err_waker: AtomicWaker,
 | 
					    pub err_waker: AtomicWaker,
 | 
				
			||||||
    pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>,
 | 
					    pub(crate) rx_mode: RxMode,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl State {
 | 
					impl State {
 | 
				
			||||||
@ -459,7 +579,7 @@ impl State {
 | 
				
			|||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            tx_waker: AtomicWaker::new(),
 | 
					            tx_waker: AtomicWaker::new(),
 | 
				
			||||||
            err_waker: AtomicWaker::new(),
 | 
					            err_waker: AtomicWaker::new(),
 | 
				
			||||||
            rx_queue: Channel::new(),
 | 
					            rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -467,6 +587,7 @@ impl State {
 | 
				
			|||||||
trait SealedInstance {
 | 
					trait SealedInstance {
 | 
				
			||||||
    fn regs() -> crate::pac::can::Can;
 | 
					    fn regs() -> crate::pac::can::Can;
 | 
				
			||||||
    fn state() -> &'static State;
 | 
					    fn state() -> &'static State;
 | 
				
			||||||
 | 
					    unsafe fn mut_state() -> &'static mut State;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// CAN instance trait.
 | 
					/// CAN instance trait.
 | 
				
			||||||
@ -495,9 +616,12 @@ foreach_peripheral!(
 | 
				
			|||||||
                crate::pac::$inst
 | 
					                crate::pac::$inst
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            unsafe fn mut_state() -> & 'static mut State {
 | 
				
			||||||
 | 
					                static mut STATE: State = State::new();
 | 
				
			||||||
 | 
					                &mut *core::ptr::addr_of_mut!(STATE)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            fn state() -> &'static State {
 | 
					            fn state() -> &'static State {
 | 
				
			||||||
                static STATE: State = State::new();
 | 
					                unsafe { peripherals::$inst::mut_state() }
 | 
				
			||||||
                &STATE
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -561,5 +685,3 @@ impl Index for crate::can::bx::Mailbox {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -18,9 +18,13 @@ pub(crate) struct ClassicBufferedTxInner {
 | 
				
			|||||||
    pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
 | 
					    pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) struct FdBufferedRxInner {
 | 
					pub(crate) struct FdBufferedRxInner {
 | 
				
			||||||
    pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
 | 
					    pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
 | 
				
			||||||
pub(crate) struct FdBufferedTxInner {
 | 
					pub(crate) struct FdBufferedTxInner {
 | 
				
			||||||
    pub tx_receiver: DynamicReceiver<'static, FdFrame>,
 | 
					    pub tx_receiver: DynamicReceiver<'static, FdFrame>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -40,3 +40,13 @@ pub enum FrameCreateError {
 | 
				
			|||||||
    /// Invalid ID.
 | 
					    /// Invalid ID.
 | 
				
			||||||
    InvalidCanId,
 | 
					    InvalidCanId,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Error returned by `try_read`
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
				
			||||||
 | 
					pub enum TryReadError {
 | 
				
			||||||
 | 
					    /// Bus error
 | 
				
			||||||
 | 
					    BusError(BusError),
 | 
				
			||||||
 | 
					    /// Receive buffer is empty
 | 
				
			||||||
 | 
					    Empty,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user