forked from imxrt-rs/imxrt-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dc9581c
commit 6362ad6
Showing
10 changed files
with
2,017 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
//! `embedded_hal` trait impls. | ||
use super::{Data, ExtendedId, Frame, Id, IdReg, OverrunError, StandardId, CAN}; | ||
|
||
use crate::iomuxc::consts::Unsigned; | ||
use embedded_hal::can; | ||
|
||
impl<M> can::Can for CAN<M> | ||
where | ||
M: Unsigned, | ||
{ | ||
type Frame = Frame; | ||
|
||
type Error = OverrunError; | ||
|
||
fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> { | ||
let data: [u8; 8] = [255, 255, 255, 255, 255, 255, 255, 255]; | ||
let id = StandardId::new(0).unwrap(); | ||
|
||
match self.transmit(frame) { | ||
Ok(status) => Ok(Some(Frame::new_data(id, Data::new(&data).unwrap()))), | ||
Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock), | ||
Err(nb::Error::Other(e)) => match e {}, | ||
} | ||
} | ||
|
||
fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> { | ||
let data: [u8; 8] = [255, 255, 255, 255, 255, 255, 255, 255]; | ||
let id = StandardId::new(0).unwrap(); | ||
|
||
Ok(Frame::new_data(id, Data::new(&data).unwrap())) | ||
} | ||
} | ||
|
||
impl can::Error for OverrunError { | ||
fn kind(&self) -> can::ErrorKind { | ||
can::ErrorKind::Overrun | ||
} | ||
} | ||
|
||
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 { | ||
&[] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
//! Filter bank API. | ||
use core::marker::PhantomData; | ||
|
||
use super::{ExtendedId, Fifo, Id, StandardId}; | ||
|
||
const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames | ||
const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers | ||
const F16_RTR: u16 = 0b10000; | ||
const F16_IDE: u16 = 0b01000; | ||
|
||
/// A 16-bit filter list entry. | ||
/// | ||
/// This can match data and remote frames using standard IDs. | ||
#[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] | ||
pub struct ListEntry16(u16); | ||
|
||
/// A 32-bit filter list entry. | ||
/// | ||
/// This can match data and remote frames using extended or standard IDs. | ||
#[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] | ||
pub struct ListEntry32(u32); | ||
|
||
/// A 16-bit identifier mask. | ||
#[derive(Debug, Copy, Clone)] | ||
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] | ||
pub struct Mask16 { | ||
id: u16, | ||
mask: u16, | ||
} | ||
|
||
/// A 32-bit identifier mask. | ||
#[derive(Debug, Copy, Clone)] | ||
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] | ||
pub struct Mask32 { | ||
id: u32, | ||
mask: u32, | ||
} | ||
|
||
impl ListEntry16 { | ||
/// Creates a filter list entry that accepts data frames with the given standard ID. | ||
/// | ||
/// This entry will *not* accept remote frames with the same ID. | ||
pub fn data_frames_with_id(id: StandardId) -> Self { | ||
Self(id.as_raw() << 5) | ||
} | ||
|
||
/// Creates a filter list entry that accepts remote frames with the given standard ID. | ||
pub fn remote_frames_with_id(id: StandardId) -> Self { | ||
Self(id.as_raw() << 5 | F16_RTR) | ||
} | ||
} | ||
|
||
impl ListEntry32 { | ||
/// Creates a filter list entry that accepts data frames with the given ID. | ||
/// | ||
/// This entry will *not* accept remote frames with the same ID. | ||
/// | ||
/// The filter will only accept *either* standard *or* extended frames, depending on `id`. | ||
pub fn data_frames_with_id(id: impl Into<Id>) -> Self { | ||
match id.into() { | ||
Id::Standard(id) => Self(u32::from(id.as_raw()) << 21), | ||
Id::Extended(id) => Self(id.as_raw() << 3 | F32_IDE), | ||
} | ||
} | ||
|
||
/// Creates a filter list entry that accepts remote frames with the given ID. | ||
pub fn remote_frames_with_id(id: impl Into<Id>) -> Self { | ||
match id.into() { | ||
Id::Standard(id) => Self(u32::from(id.as_raw()) << 21 | F32_RTR), | ||
Id::Extended(id) => Self(id.as_raw() << 3 | F32_IDE | F32_RTR), | ||
} | ||
} | ||
} | ||
|
||
impl Mask16 { | ||
/// Creates a 16-bit identifier mask that accepts all frames. | ||
/// | ||
/// This will accept both standard and extended data and remote frames with any ID. | ||
pub fn accept_all() -> Self { | ||
Self { id: 0, mask: 0 } | ||
} | ||
|
||
/// Creates a 16-bit identifier mask that accepts all frames with the given standard | ||
/// ID and mask combination. | ||
/// | ||
/// Filter logic: `frame_accepted = (incoming_id & mask) == (id & mask)` | ||
/// | ||
/// A mask of all all ones (`0x7FF`) matches an exact ID, a mask of 0 matches all IDs. | ||
/// | ||
/// Both data and remote frames with `id` will be accepted. Any extended frames will be | ||
/// rejected. | ||
pub fn frames_with_std_id(id: StandardId, mask: StandardId) -> Self { | ||
Self { | ||
id: id.as_raw() << 5, | ||
mask: mask.as_raw() << 5 | F16_IDE, // also require IDE = 0 | ||
} | ||
} | ||
|
||
/// Make the filter accept data frames only. | ||
pub fn data_frames_only(&mut self) -> &mut Self { | ||
self.id &= !F16_RTR; // RTR = 0 | ||
self.mask |= F16_RTR; | ||
self | ||
} | ||
|
||
/// Make the filter accept remote frames only. | ||
pub fn remote_frames_only(&mut self) -> &mut Self { | ||
self.id |= F16_RTR; // RTR = 1 | ||
self.mask |= F16_RTR; | ||
self | ||
} | ||
} | ||
|
||
impl Mask32 { | ||
/// Creates a 32-bit identifier mask that accepts all frames. | ||
/// | ||
/// This will accept both standard and extended data and remote frames with any ID. | ||
pub fn accept_all() -> Self { | ||
Self { id: 0, mask: 0 } | ||
} | ||
|
||
/// Creates a 32-bit identifier mask that accepts all frames with the given extended | ||
/// ID and mask combination. | ||
/// | ||
/// Filter logic: `frame_accepted = (incoming_id & mask) == (id & mask)` | ||
/// | ||
/// A mask of all all ones (`0x1FFF_FFFF`) matches an exact ID, a mask of 0 matches all IDs. | ||
/// | ||
/// Both data and remote frames with `id` will be accepted. Standard frames will be rejected. | ||
pub fn frames_with_ext_id(id: ExtendedId, mask: ExtendedId) -> Self { | ||
Self { | ||
id: id.as_raw() << 3 | F32_IDE, | ||
mask: mask.as_raw() << 3 | F32_IDE, // also require IDE = 1 | ||
} | ||
} | ||
|
||
/// Creates a 32-bit identifier mask that accepts all frames with the given standard | ||
/// ID and mask combination. | ||
/// | ||
/// Filter logic: `frame_accepted = (incoming_id & mask) == (id & mask)` | ||
/// | ||
/// A mask of all all ones (`0x7FF`) matches the exact ID, a mask of 0 matches all IDs. | ||
/// | ||
/// Both data and remote frames with `id` will be accepted. Extended frames will be rejected. | ||
pub fn frames_with_std_id(id: StandardId, mask: StandardId) -> Self { | ||
Self { | ||
id: u32::from(id.as_raw()) << 21, | ||
mask: u32::from(mask.as_raw()) << 21 | F32_IDE, // also require IDE = 0 | ||
} | ||
} | ||
|
||
/// Make the filter accept data frames only. | ||
pub fn data_frames_only(&mut self) -> &mut Self { | ||
self.id &= !F32_RTR; // RTR = 0 | ||
self.mask |= F32_RTR; | ||
self | ||
} | ||
|
||
/// Make the filter accept remote frames only. | ||
pub fn remote_frames_only(&mut self) -> &mut Self { | ||
self.id |= F32_RTR; // RTR = 1 | ||
self.mask |= F32_RTR; | ||
self | ||
} | ||
} | ||
|
||
/// The configuration of a filter bank. | ||
#[derive(Debug, Copy, Clone)] | ||
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))] | ||
pub enum BankConfig { | ||
List16([ListEntry16; 4]), | ||
List32([ListEntry32; 2]), | ||
Mask16([Mask16; 2]), | ||
Mask32(Mask32), | ||
} | ||
|
||
impl From<[ListEntry16; 4]> for BankConfig { | ||
#[inline] | ||
fn from(entries: [ListEntry16; 4]) -> Self { | ||
Self::List16(entries) | ||
} | ||
} | ||
|
||
impl From<[ListEntry32; 2]> for BankConfig { | ||
#[inline] | ||
fn from(entries: [ListEntry32; 2]) -> Self { | ||
Self::List32(entries) | ||
} | ||
} | ||
|
||
impl From<[Mask16; 2]> for BankConfig { | ||
#[inline] | ||
fn from(entries: [Mask16; 2]) -> Self { | ||
Self::Mask16(entries) | ||
} | ||
} | ||
|
||
impl From<Mask32> for BankConfig { | ||
#[inline] | ||
fn from(filter: Mask32) -> Self { | ||
Self::Mask32(filter) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
|
||
} |
Oops, something went wrong.