Skip to content

Commit

Permalink
Prototype a FlexCAN peripheral
Browse files Browse the repository at this point in the history
Implementation of the FlexCAN1 and FlexCAN2 peripherals for the  NXP i.MX RT 1060 processor.

Includes APIs for initializing the peripherals, setting the clock source, setting mailbox receive filters, setting mailbox FIFO functionality, and receiving and transmitting frames.

The FlexCAN3 peripheral is not implemented.
  • Loading branch information
dstric-aqueduct authored and mciantyre committed Dec 29, 2022
1 parent 9986ebc commit a87433c
Show file tree
Hide file tree
Showing 9 changed files with 1,845 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
target
.idea
.vscode
Cargo.lock
6 changes: 3 additions & 3 deletions imxrt-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ log = "0.4.8"
rand_core = { version = "0.5", default-features = false, optional = true }

[dependencies.imxrt-iomuxc]
version = "0.1.2"
git = "https://github.com/imxrt-rs/imxrt-iomuxc.git"
branch = "v0.1"
features = ["imxrt106x"]
git = "https://github.com/dstric-aqueduct/imxrt-iomuxc.git"
tag = "v0.1.5-can"

[dev-dependencies.cortex-m-rt]
version = "0.6"
Expand Down
110 changes: 110 additions & 0 deletions imxrt-hal/src/can/embedded_hal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//! `embedded_hal` trait impls.
use super::{Data, Error, Frame, CAN};
use crate::iomuxc::consts::Unsigned;

use embedded_hal::can;
pub(crate) use embedded_hal::can::ErrorKind;
pub use embedded_hal::can::{ExtendedId, Id, StandardId};

impl<M> can::Can for CAN<M>
where
M: Unsigned,
{
type Frame = Frame;

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)) => 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(Error::NoRxData)),
}
}
}

impl can::Error for Error {
fn kind(&self) -> can::ErrorKind {
match self {
Self::NoRxData => can::ErrorKind::Other,
Self::NoTxMailbox => can::ErrorKind::Other,
Self::EmbeddedHal(e) => e.kind(),
}
}
}

impl can::Frame for Frame {
fn new(id: impl Into<can::Id>, data: &[u8]) -> Option<Self> {
let id = match id.into() {
can::Id::Standard(id) => unsafe {
Id::Standard(StandardId::new_unchecked(id.as_raw()))
},
can::Id::Extended(id) => unsafe {
Id::Extended(ExtendedId::new_unchecked(id.as_raw()))
},
};

let data = Data::new(data)?;
Some(Frame::new_data(id, data))
}

fn new_remote(id: impl Into<can::Id>, dlc: usize) -> Option<Self> {
let id = match id.into() {
can::Id::Standard(id) => unsafe {
Id::Standard(StandardId::new_unchecked(id.as_raw()))
},
can::Id::Extended(id) => unsafe {
Id::Extended(ExtendedId::new_unchecked(id.as_raw()))
},
};

if dlc <= 8 {
Some(Frame::new_remote(id, dlc as u8))
} else {
None
}
}

#[inline]
fn is_extended(&self) -> bool {
self.is_extended()
}

#[inline]
fn is_remote_frame(&self) -> bool {
self.is_remote_frame()
}

#[inline]
fn id(&self) -> can::Id {
match self.id() {
Id::Standard(id) => unsafe {
can::Id::Standard(can::StandardId::new_unchecked(id.as_raw()))
},
Id::Extended(id) => unsafe {
can::Id::Extended(can::ExtendedId::new_unchecked(id.as_raw()))
},
}
}

#[inline]
fn dlc(&self) -> usize {
self.dlc().into()
}

fn data(&self) -> &[u8] {
if let Some(data) = self.data() {
data
} else {
&[]
}
}
}
38 changes: 38 additions & 0 deletions imxrt-hal/src/can/filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! Filter bank API.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub enum FlexCanIde {
#[default]
None = 0,
Ext = 1,
Rtr = 2,
Std = 3,
Inactive,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub enum FlexCanFlten {
AcceptAll = 0,
#[default]
RejectAll = 1,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub struct FlexCanFilter {
pub filter_id: u8,
pub id: u32,
pub ide: FlexCanIde,
pub remote: FlexCanIde,
}

impl FlexCanFilter {
/// Create a new [`FlexCanFilter`].
pub fn new(filter_id: u8, id: u32, ide: FlexCanIde, remote: FlexCanIde) -> Self {
Self {
filter_id,
id,
ide,
remote,
}
}
}
Loading

0 comments on commit a87433c

Please sign in to comment.