diff --git a/va416xx-hal/src/can/mod.rs b/va416xx-hal/src/can/mod.rs index 3943a12..e7e9a46 100644 --- a/va416xx-hal/src/can/mod.rs +++ b/va416xx-hal/src/can/mod.rs @@ -1,6 +1,22 @@ -//! CAN driver. +//! CAN peripheral driver. //! //! The VA416xx CAN module is based on the CP3UB26 module. +//! +//! Using the CAN bus generally involves the following steps: +//! +//! 1. Create a [Can] instance +//! 2. The [CanChannels] resource management singleton can be retrieved by using +//! [Can::take_channels]. +//! 3. Individual [CanRx] and [CanTx] channels can be created using the [CanChannels::take] +//! function. These allow to send or receive CAN frames on individual channels. +//! 4. The [asynch::CanTxAsync] structure can be created to transmit frames asynchronously. +//! The [asynch::on_interrupt_can] function should be called in the user interrupt handler +//! for CAN0 and CAN1 for this to work properly. The interrupt handler can also take care of +//! receiving frames on [CanRx] channels with enabled interrupts. +//! +//! # Example +//! +//! - [CAN example](https://egit.irs.uni-stuttgart.de/rust/va416xx-rs/src/branch/main/examples/embassy/src/bin/can.rs) use core::sync::atomic::AtomicBool; use arbitrary_int::{u11, u15, u2, u3, u4, u7, Number}; @@ -319,6 +335,7 @@ pub enum ClockConfigError { CanNotFindPrescaler, } +/// The main CAN peripheral driver. pub struct Can { regs: regs::MmioCan<'static>, id: CanId, @@ -358,6 +375,7 @@ impl Can { self.regs.write_gmskb(BaseId::new_with_raw_value(0)); } + /// Retrieve a resource management singleton for the 15 CAN channels. pub fn take_channels(&self) -> Option { if CHANNELS_TAKEN[self.id() as usize].swap(true, core::sync::atomic::Ordering::SeqCst) { return None; @@ -412,11 +430,13 @@ impl Can { &mut self.regs } + /// Clear all interrupts. #[inline] pub fn clear_interrupts(&mut self) { self.regs .write_iclr(regs::InterruptClear::new_with_raw_value(0xFFFF_FFFF)); } + /// This function only enable the CAN interrupt vector in the NVIC. /// /// The interrupts for the individual channels or errors still need to be enabled @@ -518,6 +538,7 @@ pub enum RxState { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct InvalidRxStateError(pub RxState); +/// Driver instance to use an individual CAN channel as a transmission channel. #[derive(Debug)] pub struct CanTx { ll: CanChannelLowLevel, @@ -646,6 +667,7 @@ impl CanTx { } } +/// Driver instance to use an individual CAN channel as a reception channel. pub struct CanRx { ll: CanChannelLowLevel, mode: RxState, @@ -760,6 +782,7 @@ impl CanChannels { self.id } + /// Take the indidivual CAN channel low level driver instance. pub fn take(&mut self, idx: usize) -> Option { if idx > 14 { return None; diff --git a/va416xx-hal/src/can/regs.rs b/va416xx-hal/src/can/regs.rs index e3bd3e8..5e19e4d 100644 --- a/va416xx-hal/src/can/regs.rs +++ b/va416xx-hal/src/can/regs.rs @@ -261,7 +261,7 @@ pub struct ExtendedId { #[bitbybit::bitfield(u32, default = 0x0)] #[derive(Debug)] pub struct BaseId { - /// This will contain ID\[10:0\] for standard frames and bits [28:18] for extended frames. + /// This will contain ID\[10:0\] for standard frames and bits \[28:18\] for extended frames. #[bits(5..=15, rw)] mask_28_18: u11, /// This is the RTR bit for standard frames, and the SRR bit for extended frames.