diff --git a/imxrt-hal/Cargo.toml b/imxrt-hal/Cargo.toml index 07779758..77a48e7b 100644 --- a/imxrt-hal/Cargo.toml +++ b/imxrt-hal/Cargo.toml @@ -34,7 +34,7 @@ features = ["device"] bench = false [features] -default = ["embedded-hal/unproven", "imxrt1062"] # Allows us to access the new digital pin traits +default = ["embedded-hal/unproven"] # Allows us to access the new digital pin traits # Device specific feature flags # these need fixes and conditional sections in CCM diff --git a/imxrt-hal/src/can/embedded_hal.rs b/imxrt-hal/src/can/embedded_hal.rs index b10046f3..353a55a2 100644 --- a/imxrt-hal/src/can/embedded_hal.rs +++ b/imxrt-hal/src/can/embedded_hal.rs @@ -1,10 +1,11 @@ //! `embedded_hal` trait impls. -use super::{Data, Frame, NoDataError, CAN}; +use super::{Data, Frame, Error, CAN}; use crate::iomuxc::consts::Unsigned; use embedded_hal::can; pub use embedded_hal::can::{ExtendedId, Id, StandardId}; +pub(crate) use embedded_hal::can::ErrorKind; impl can::Can for CAN where @@ -12,27 +13,31 @@ where { type Frame = Frame; - type Error = NoDataError; + type Error = Error; fn transmit(&mut self, frame: &Self::Frame) -> nb::Result, Self::Error> { match self.transmit(frame) { Ok(_status) => Ok(Some(frame.clone())), Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock), - Err(nb::Error::Other(e)) => match e {}, + Err(nb::Error::Other(e)) => Err(nb::Error::Other(e)), } } fn receive(&mut self) -> nb::Result { match self.read_mailboxes() { Some(d) => Ok(d.frame), - None => Err(nb::Error::Other(NoDataError { _priv: () })), + None => Err(nb::Error::Other(Error::NoRxData)), } } } -impl can::Error for NoDataError { +impl can::Error for Error { fn kind(&self) -> can::ErrorKind { - can::ErrorKind::Overrun + match self { + Self::NoRxData => can::ErrorKind::Other, + Self::NoTxMailbox => can::ErrorKind::Other, + Self::EmbeddedHal(e) => e.kind() + } } } diff --git a/imxrt-hal/src/can/frame.rs b/imxrt-hal/src/can/frame.rs index 2e546438..c85c09c5 100644 --- a/imxrt-hal/src/can/frame.rs +++ b/imxrt-hal/src/can/frame.rs @@ -1,7 +1,6 @@ #[cfg(test)] mod tests; -use core::convert::TryFrom; use core::ops::{Deref, DerefMut}; use super::{ExtendedId, Id, StandardId}; @@ -236,16 +235,27 @@ impl CodeReg { } /// Get the 4 bit code content for a CodeReg. - /// - /// # Panics - /// - /// This function will panic if a matching [`FlexCanMailboxCSCode`] is not found. + /// + /// This may return the variant [`FlexCanMailboxCSCode::Unknown`], + /// which must be handled appropriately for the intended usage. #[inline(always)] pub fn code(&self) -> FlexCanMailboxCSCode { - FlexCanMailboxCSCode::try_from(((self.0 & Self::CODE_MASK) >> Self::CODE_SHIFT) as u8) - .unwrap() + FlexCanMailboxCSCode::from(((self.0 & Self::CODE_MASK) >> Self::CODE_SHIFT) as u8) } + /// The frame timestamp, captured from the peripheral's free-running timer. + /// + /// The timestamp represents the time at which a TX or RX frame appears on + /// the bus. The counter increments at the CAN bus baud rate. The counter pauses + /// when the driver is frozen, or the processor is in debug mode. + /// + /// A frame's timestamp resets to zero when either + /// + /// - the counter wraps around at the 16 bit boundary. + /// - a message is received in mailbox 0. This happens if time sync is enabled, + /// and if the message passed the mailbox filter. + /// + /// Users may also override the timestamp to any specific value. pub fn timestamp(&self) -> u16 { ((self.0 & Self::TIMESTAMP_MASK) >> Self::TIMESTAMP_SHIFT) as u16 } @@ -301,11 +311,9 @@ impl IdReg { const STANDARD_SHIFT: u32 = 18; const EXTENDED_SHIFT: u32 = 0; - /// Creates a new standard identifier (11bit, Range: 0..0x7FF) - /// - /// Panics for IDs outside the allowed range. + /// Creates a new `IdReg` #[inline(always)] - pub fn new(id: u32) -> Self { + fn new(id: u32) -> Self { Self(id) } @@ -315,20 +323,22 @@ impl IdReg { self.0 } - /// Creates a new standard identifier (11bit, Range: 0..0x7FF) + /// Creates a new standard identifier (11bit, Range: 0..=0x7FF) /// /// Panics for IDs outside the allowed range. #[inline(always)] pub fn new_standard(id: StandardId) -> Self { + assert!(id.as_raw() <= StandardId::MAX.as_raw()); let id = u32::from(id.as_raw()) << Self::STANDARD_SHIFT; Self::new(id) } - /// Creates a new extendended identifier (29bit , Range: 0..0x1FFFFFFF). + /// Creates a new extendended identifier (29bit , Range: 0..=0x1FFFFFFF). /// /// Panics for IDs outside the allowed range. #[inline(always)] pub fn new_extended(id: ExtendedId) -> Self { + assert!(id.as_raw() <= ExtendedId::MAX.as_raw()); let id = u32::from(id.as_raw()) << Self::EXTENDED_SHIFT; Self::new(id) } diff --git a/imxrt-hal/src/can/mod.rs b/imxrt-hal/src/can/mod.rs index b37e66fd..81666fb0 100644 --- a/imxrt-hal/src/can/mod.rs +++ b/imxrt-hal/src/can/mod.rs @@ -1,3 +1,44 @@ +//! Flexible Controller Area Network (FlexCAN) +//! +//! The FlexCAN module provides a CanBus peripheral that implements +//! the `embedded_hal::can` traits. +//!//! +//! # Example +//! +//! ```no_run +//! use imxrt_hal; +//! use embedded_hal::serial::{Read, Write}; +//! +//! let mut peripherals = imxrt_hal::Peripherals::take().unwrap(); +//! +//! let (can1_builder, _) = peripherals.can.clock( +//! &mut peripherals.ccm.handle, +//! bsp::hal::ccm::can::ClockSelect::OSC, +//! bsp::hal::ccm::can::PrescalarSelect::DIVIDE_1, +//! ); +//! +//! let mut can1 = can1_builder.build(pins.p22, pins.p23); +//! +//! can1.set_baud_rate(1_000_000); +//! can1.set_max_mailbox(16); +//! can1.enable_fifo(); +//! can1.set_fifo_interrupt(true); +//! can1.set_fifo_accept_all(); +//! +//! // create a `Frame` with `StandardID` 0x00 +//! // and `Data` [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07] +//! let id = imxrt_hal::can::Id::from(imxrt_hal::can::StandardId::new(0x00).unwrap()); +//! let data: [u8; 8] = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; +//! let frame = imxrt_hal::can::Frame::new_data(id, data); +//! +//! // read all available mailboxes for any available frames +//! can1.read_mailboxes(); +//! +//! // transmit the frame +//! can1.transmit(&frame); +//! ``` + + mod embedded_hal; pub mod filter; mod frame; @@ -14,11 +55,18 @@ use crate::ral; use core::convert::Infallible; use core::marker::PhantomData; -/// Error that indicates that no received frames are available -/// in the FlexCAN mailboxes +/// Error from the FlexCan peripheral. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct NoDataError { - _priv: (), +pub enum Error { + /// Error indicating that no received data is + /// available in the mailboxes + NoRxData, + /// Error indicating that no transmit mailboxes + /// are available + NoTxMailbox, + /// A wrapper around the [`embedded_hal::ErrorKind`] + /// enum + EmbeddedHal(embedded_hal::ErrorKind), } /// Unclocked Can modules @@ -247,7 +295,7 @@ where M::USIZE == 2 } - pub fn base_address(&self) -> u32 { + pub(crate) fn base_address(&self) -> u32 { let addr: *const ral::can::RegisterBlock = &*self.reg; addr as u32 } @@ -973,7 +1021,7 @@ where } #[inline(always)] - pub fn transmit(&mut self, frame: &Frame) -> nb::Result<(), Infallible> { + pub fn transmit(&mut self, frame: &Frame) -> nb::Result<(), Error> { for i in self.mailbox_offset()..self.get_max_mailbox() { if let FlexCanMailboxCSCode::TxInactive = FlexCanMailboxCSCode::from_code_reg(self.read_mailbox_code(i)) @@ -982,7 +1030,7 @@ where return Ok(()); } } - Ok(()) + Err(nb::Error::Other(Error::NoTxMailbox)) } }