From b06e4a6ab45002f5c1c48523fea6dba7b9c4a668 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 18 Dec 2023 18:44:41 +0100 Subject: [PATCH] stm32/can: docs. --- embassy-stm32/src/can/bxcan.rs | 45 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 78836024..3c663b45 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -21,8 +21,10 @@ use crate::{interrupt, peripherals, Peripheral}; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Envelope { + /// Reception time. #[cfg(feature = "time")] pub ts: embassy_time::Instant, + /// The actual CAN frame. pub frame: bxcan::Frame, } @@ -43,6 +45,7 @@ impl interrupt::typelevel::Handler for TxInterruptH } } +/// RX0 interrupt handler. pub struct Rx0InterruptHandler { _phantom: PhantomData, } @@ -54,6 +57,7 @@ impl interrupt::typelevel::Handler for Rx0Interrup } } +/// RX1 interrupt handler. pub struct Rx1InterruptHandler { _phantom: PhantomData, } @@ -65,6 +69,7 @@ impl interrupt::typelevel::Handler for Rx1Interrup } } +/// SCE interrupt handler. pub struct SceInterruptHandler { _phantom: PhantomData, } @@ -82,10 +87,13 @@ impl interrupt::typelevel::Handler for SceInterrup } } +/// CAN driver pub struct Can<'d, T: Instance> { - pub can: bxcan::Can>, + can: bxcan::Can>, } +/// CAN bus error +#[allow(missing_docs)] #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum BusError { @@ -101,6 +109,7 @@ pub enum BusError { BusWarning, } +/// Error returned by `try_read` #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TryReadError { @@ -110,6 +119,7 @@ pub enum TryReadError { Empty, } +/// Error returned by `try_write` #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TryWriteError { @@ -177,6 +187,7 @@ impl<'d, T: Instance> Can<'d, T> { Self { can } } + /// Set CAN bit rate. pub fn set_bitrate(&mut self, bitrate: u32) { let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); @@ -194,7 +205,9 @@ impl<'d, T: Instance> Can<'d, T> { } } - /// Queues the message to be sent but exerts backpressure + /// Queues the message to be sent. + /// + /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { self.split().0.write(frame).await } @@ -221,12 +234,16 @@ impl<'d, T: Instance> Can<'d, T> { CanTx::::flush_all_inner().await } + /// Read a CAN frame. + /// + /// If no CAN frame is in the RX buffer, this will wait until there is one. + /// /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { self.split().1.read().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. pub fn try_read(&mut self) -> Result { @@ -288,7 +305,7 @@ impl<'d, T: Instance> Can<'d, T> { } } - pub const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option { + const fn calc_bxcan_timings(periph_clock: Hertz, can_bitrate: u32) -> Option { const BS1_MAX: u8 = 16; const BS2_MAX: u8 = 8; const MAX_SAMPLE_POINT_PERMILL: u16 = 900; @@ -379,21 +396,29 @@ impl<'d, T: Instance> Can<'d, T> { Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1)) } + /// Split the CAN driver into transmit and receive halves. + /// + /// Useful for doing separate transmit/receive tasks. pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { let (tx, rx0, rx1) = self.can.split_by_ref(); (CanTx { tx }, CanRx { rx0, rx1 }) } + /// Get mutable access to the lower-level driver from the `bxcan` crate. pub fn as_mut(&mut self) -> &mut bxcan::Can> { &mut self.can } } +/// CAN driver, transmit half. pub struct CanTx<'c, 'd, T: Instance> { tx: &'c mut bxcan::Tx>, } impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { + /// Queues the message to be sent. + /// + /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { poll_fn(|cx| { T::state().tx_waker.register(cx.waker()); @@ -475,6 +500,7 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { } } +/// CAN driver, receive half. #[allow(dead_code)] pub struct CanRx<'c, 'd, T: Instance> { rx0: &'c mut bxcan::Rx0>, @@ -482,6 +508,11 @@ pub struct CanRx<'c, 'd, T: Instance> { } impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { + /// Read a CAN frame. + /// + /// If no CAN frame is in the RX buffer, this will wait until there is one. + /// + /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { poll_fn(|cx| { T::state().err_waker.register(cx.waker()); @@ -590,13 +621,19 @@ pub(crate) mod sealed { } } +/// CAN instance trait. pub trait Instance: sealed::Instance + RccPeripheral + 'static { + /// TX interrupt for this instance. type TXInterrupt: crate::interrupt::typelevel::Interrupt; + /// RX0 interrupt for this instance. type RX0Interrupt: crate::interrupt::typelevel::Interrupt; + /// RX1 interrupt for this instance. type RX1Interrupt: crate::interrupt::typelevel::Interrupt; + /// SCE interrupt for this instance. type SCEInterrupt: crate::interrupt::typelevel::Interrupt; } +/// BXCAN instance newtype. pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>); unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> {