stm32/can: implement more convenience methods
This commit is contained in:
		
							parent
							
								
									44c8db2911
								
							
						
					
					
						commit
						38b5d1ee2b
					
				| @ -77,6 +77,7 @@ pub struct Can<'d, T: Instance> { | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum BusError { | ||||
|     Stuff, | ||||
|     Form, | ||||
| @ -90,6 +91,22 @@ pub enum BusError { | ||||
|     BusWarning, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum TryReadError { | ||||
|     /// Bus error
 | ||||
|     BusError(BusError), | ||||
|     /// Receive buffer is empty
 | ||||
|     Empty, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum TryWriteError { | ||||
|     /// All transmit mailboxes are full
 | ||||
|     Full, | ||||
| } | ||||
| 
 | ||||
| impl<'d, T: Instance> Can<'d, T> { | ||||
|     /// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
 | ||||
|     /// You must call [Can::enable_non_blocking] to use the peripheral.
 | ||||
| @ -175,56 +192,46 @@ impl<'d, T: Instance> Can<'d, T> { | ||||
| 
 | ||||
|     /// Queues the message to be sent but exerts backpressure
 | ||||
|     pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().tx_waker.register(cx.waker()); | ||||
|             if let Ok(status) = self.can.borrow_mut().transmit(frame) { | ||||
|                 return Poll::Ready(status); | ||||
|             } | ||||
| 
 | ||||
|             Poll::Pending | ||||
|         }) | ||||
|         .await | ||||
|         CanTx { can: &self.can }.write(frame).await | ||||
|     } | ||||
| 
 | ||||
|     pub async fn flush(&self, mb: bxcan::Mailbox) { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().tx_waker.register(cx.waker()); | ||||
|             if T::regs().tsr().read().tme(mb.index()) { | ||||
|                 return Poll::Ready(()); | ||||
|             } | ||||
|     /// Attempts to transmit a frame without blocking.
 | ||||
|     ///
 | ||||
|     /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
 | ||||
|     pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> { | ||||
|         CanTx { can: &self.can }.try_write(frame) | ||||
|     } | ||||
| 
 | ||||
|             Poll::Pending | ||||
|         }) | ||||
|         .await; | ||||
|     /// Waits for a specific transmit mailbox to become empty
 | ||||
|     pub async fn flush(&self, mb: bxcan::Mailbox) { | ||||
|         CanTx { can: &self.can }.flush(mb).await | ||||
|     } | ||||
| 
 | ||||
|     /// Waits until any of the transmit mailboxes become empty
 | ||||
|     pub async fn flush_any(&self) { | ||||
|         CanTx { can: &self.can }.flush_any().await | ||||
|     } | ||||
| 
 | ||||
|     /// Waits until all of the transmit mailboxes become empty
 | ||||
|     pub async fn flush_all(&self) { | ||||
|         CanTx { can: &self.can }.flush_all().await | ||||
|     } | ||||
| 
 | ||||
|     /// Returns a tuple of the time the message was received and the message frame
 | ||||
|     pub async fn read(&mut self) -> Result<(u16, bxcan::Frame), BusError> { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().err_waker.register(cx.waker()); | ||||
|             if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) { | ||||
|                 return Poll::Ready(Ok((time, frame))); | ||||
|             } else if let Some(err) = self.curr_error() { | ||||
|                 return Poll::Ready(Err(err)); | ||||
|             } | ||||
| 
 | ||||
|             Poll::Pending | ||||
|         }) | ||||
|         .await | ||||
|         CanRx { can: &self.can }.read().await | ||||
|     } | ||||
| 
 | ||||
|     fn curr_error(&self) -> Option<BusError> { | ||||
|         let err = { T::regs().esr().read() }; | ||||
|         if err.boff() { | ||||
|             return Some(BusError::BusOff); | ||||
|         } else if err.epvf() { | ||||
|             return Some(BusError::BusPassive); | ||||
|         } else if err.ewgf() { | ||||
|             return Some(BusError::BusWarning); | ||||
|         } else if let Some(err) = err.lec().into_bus_err() { | ||||
|             return Some(err); | ||||
|         } | ||||
|         None | ||||
|     /// 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<(u16, bxcan::Frame), TryReadError> { | ||||
|         CanRx { can: &self.can }.try_read() | ||||
|     } | ||||
| 
 | ||||
|     /// Waits while receive queue is empty.
 | ||||
|     pub async fn wait_not_empty(&mut self) { | ||||
|         CanRx { can: &self.can }.wait_not_empty().await | ||||
|     } | ||||
| 
 | ||||
|     unsafe fn receive_fifo(fifo: RxFifo) { | ||||
| @ -386,6 +393,14 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { | ||||
|         .await | ||||
|     } | ||||
| 
 | ||||
|     /// Attempts to transmit a frame without blocking.
 | ||||
|     ///
 | ||||
|     /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
 | ||||
|     pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> { | ||||
|         self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full) | ||||
|     } | ||||
| 
 | ||||
|     /// Waits for a specific transmit mailbox to become empty
 | ||||
|     pub async fn flush(&self, mb: bxcan::Mailbox) { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().tx_waker.register(cx.waker()); | ||||
| @ -397,6 +412,42 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { | ||||
|         }) | ||||
|         .await; | ||||
|     } | ||||
| 
 | ||||
|     /// Waits until any of the transmit mailboxes become empty
 | ||||
|     pub async fn flush_any(&self) { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().tx_waker.register(cx.waker()); | ||||
| 
 | ||||
|             let tsr = T::regs().tsr().read(); | ||||
|             if tsr.tme(bxcan::Mailbox::Mailbox0.index()) | ||||
|                 || tsr.tme(bxcan::Mailbox::Mailbox1.index()) | ||||
|                 || tsr.tme(bxcan::Mailbox::Mailbox2.index()) | ||||
|             { | ||||
|                 return Poll::Ready(()); | ||||
|             } | ||||
| 
 | ||||
|             Poll::Pending | ||||
|         }) | ||||
|         .await; | ||||
|     } | ||||
| 
 | ||||
|     /// Waits until all of the transmit mailboxes become empty
 | ||||
|     pub async fn flush_all(&self) { | ||||
|         poll_fn(|cx| { | ||||
|             T::state().tx_waker.register(cx.waker()); | ||||
| 
 | ||||
|             let tsr = T::regs().tsr().read(); | ||||
|             if tsr.tme(bxcan::Mailbox::Mailbox0.index()) | ||||
|                 && tsr.tme(bxcan::Mailbox::Mailbox1.index()) | ||||
|                 && tsr.tme(bxcan::Mailbox::Mailbox2.index()) | ||||
|             { | ||||
|                 return Poll::Ready(()); | ||||
|             } | ||||
| 
 | ||||
|             Poll::Pending | ||||
|         }) | ||||
|         .await; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[allow(dead_code)] | ||||
| @ -419,6 +470,33 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { | ||||
|         .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<(u16, bxcan::Frame), TryReadError> { | ||||
|         if let Ok(envelope) = T::state().rx_queue.try_recv() { | ||||
|             return Ok(envelope); | ||||
|         } | ||||
| 
 | ||||
|         if let Some(err) = self.curr_error() { | ||||
|             return Err(TryReadError::BusError(err)); | ||||
|         } | ||||
| 
 | ||||
|         Err(TryReadError::Empty) | ||||
|     } | ||||
| 
 | ||||
|     /// Waits while receive queue is empty.
 | ||||
|     pub async fn wait_not_empty(&mut self) { | ||||
|         poll_fn(|cx| { | ||||
|             if T::state().rx_queue.poll_ready_to_receive(cx) { | ||||
|                 Poll::Ready(()) | ||||
|             } else { | ||||
|                 Poll::Pending | ||||
|             } | ||||
|         }) | ||||
|         .await | ||||
|     } | ||||
| 
 | ||||
|     fn curr_error(&self) -> Option<BusError> { | ||||
|         let err = { T::regs().esr().read() }; | ||||
|         if err.boff() { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user