Skip to content

Commit

Permalink
PR updates
Browse files Browse the repository at this point in the history
- added bounds checks on StandardID and ExtendedID for creation of IdReg

- improved Error descriptiveness

- added docs to Frame timestamp field

- Update Cargo.toml
  • Loading branch information
dstric-aqueduct committed Dec 21, 2022
1 parent df48822 commit f73b2b8
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 27 deletions.
2 changes: 1 addition & 1 deletion imxrt-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 11 additions & 6 deletions imxrt-hal/src/can/embedded_hal.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
//! `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<M> can::Can for CAN<M>
where
M: Unsigned,
{
type Frame = Frame;

type Error = NoDataError;
type Error = Error;

fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, 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<Self::Frame, Self::Error> {
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()
}
}
}

Expand Down
36 changes: 23 additions & 13 deletions imxrt-hal/src/can/frame.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#[cfg(test)]
mod tests;

use core::convert::TryFrom;
use core::ops::{Deref, DerefMut};

use super::{ExtendedId, Id, StandardId};
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}

Expand All @@ -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)
}
Expand Down
62 changes: 55 additions & 7 deletions imxrt-hal/src/can/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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))
Expand All @@ -982,7 +1030,7 @@ where
return Ok(());
}
}
Ok(())
Err(nb::Error::Other(Error::NoTxMailbox))
}
}

Expand Down

0 comments on commit f73b2b8

Please sign in to comment.