Skip to content

Commit 7558350

Browse files
committed
Traits for CAN (Controller Area Network)
1 parent 683e41e commit 7558350

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

src/can/blocking.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! Blocking CAN API
2+
3+
/// A blocking CAN interface that is able to transmit and receive frames.
4+
pub trait Can {
5+
/// Associated frame type.
6+
type Frame: crate::can::Frame;
7+
8+
/// Associated error type.
9+
type Error;
10+
11+
/// Puts a frame in the transmit buffer. Blocks until space is available in
12+
/// the transmit buffer.
13+
fn write(&mut self, frame: &Self::Frame) -> Result<(), Self::Error>;
14+
15+
/// Blocks until a frame was received or an error occured.
16+
fn read(&mut self) -> Result<Self::Frame, Self::Error>;
17+
}

src/can/id.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! CAN Identifiers.
2+
3+
/// Standard 11-bit CAN Identifier (`0..=0x7FF`).
4+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
5+
pub struct StandardId(u16);
6+
7+
impl StandardId {
8+
/// CAN ID `0`, the highest priority.
9+
pub const ZERO: Self = Self(0);
10+
11+
/// CAN ID `0x7FF`, the lowest priority.
12+
pub const MAX: Self = Self(0x7FF);
13+
14+
/// Tries to create a `StandardId` from a raw 16-bit integer.
15+
///
16+
/// This will return `None` if `raw` is out of range of an 11-bit integer (`> 0x7FF`).
17+
#[inline]
18+
pub const fn new(raw: u16) -> Option<Self> {
19+
if raw <= 0x7FF {
20+
Some(Self(raw))
21+
} else {
22+
None
23+
}
24+
}
25+
26+
/// Creates a new `StandardId` without checking if it is inside the valid range.
27+
#[inline]
28+
pub const unsafe fn new_unchecked(raw: u16) -> Self {
29+
Self(raw)
30+
}
31+
32+
/// Returns this CAN Identifier as a raw 16-bit integer.
33+
#[inline]
34+
pub fn as_raw(&self) -> u16 {
35+
self.0
36+
}
37+
}
38+
39+
/// Extended 29-bit CAN Identifier (`0..=1FFF_FFFF`).
40+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
41+
pub struct ExtendedId(u32);
42+
43+
impl ExtendedId {
44+
/// CAN ID `0`, the highest priority.
45+
pub const ZERO: Self = Self(0);
46+
47+
/// CAN ID `0x1FFFFFFF`, the lowest priority.
48+
pub const MAX: Self = Self(0x1FFF_FFFF);
49+
50+
/// Tries to create a `ExtendedId` from a raw 32-bit integer.
51+
///
52+
/// This will return `None` if `raw` is out of range of an 29-bit integer (`> 0x1FFF_FFFF`).
53+
#[inline]
54+
pub const fn new(raw: u32) -> Option<Self> {
55+
if raw <= 0x1FFF_FFFF {
56+
Some(Self(raw))
57+
} else {
58+
None
59+
}
60+
}
61+
62+
/// Creates a new `ExtendedId` without checking if it is inside the valid range.
63+
#[inline]
64+
pub const unsafe fn new_unchecked(raw: u32) -> Self {
65+
Self(raw)
66+
}
67+
68+
/// Returns this CAN Identifier as a raw 32-bit integer.
69+
#[inline]
70+
pub fn as_raw(&self) -> u32 {
71+
self.0
72+
}
73+
74+
/// Returns the Base ID part of this extended identifier.
75+
pub fn standard_id(&self) -> StandardId {
76+
// ID-28 to ID-18
77+
StandardId((self.0 >> 18) as u16)
78+
}
79+
}
80+
81+
/// A CAN Identifier (standard or extended).
82+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
83+
pub enum Id {
84+
/// Standard 11-bit Identifier (`0..=0x7FF`).
85+
Standard(StandardId),
86+
87+
/// Extended 29-bit Identifier (`0..=0x1FFF_FFFF`).
88+
Extended(ExtendedId),
89+
}
90+
91+
impl From<StandardId> for Id {
92+
#[inline]
93+
fn from(id: StandardId) -> Self {
94+
Id::Standard(id)
95+
}
96+
}
97+
98+
impl From<ExtendedId> for Id {
99+
#[inline]
100+
fn from(id: ExtendedId) -> Self {
101+
Id::Extended(id)
102+
}
103+
}

src/can/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//! Controller Area Network
2+
3+
pub mod blocking;
4+
pub mod nb;
5+
6+
mod id;
7+
8+
pub use id::*;
9+
10+
/// A CAN2.0 Frame
11+
pub trait Frame: Sized {
12+
/// Creates a new frame.
13+
/// Returns an error when the data slice is too long.
14+
fn new(id: impl Into<Id>, data: &[u8]) -> Result<Self, ()>;
15+
16+
/// Creates a new remote frame (RTR bit set).
17+
/// Returns an error when the data length code (DLC) is not valid.
18+
fn new_remote(id: impl Into<Id>, dlc: usize) -> Result<Self, ()>;
19+
20+
/// Returns true if this frame is a extended frame.
21+
fn is_extended(&self) -> bool;
22+
23+
/// Returns true if this frame is a standard frame.
24+
fn is_standard(&self) -> bool {
25+
!self.is_extended()
26+
}
27+
28+
/// Returns true if this frame is a remote frame.
29+
fn is_remote_frame(&self) -> bool;
30+
31+
/// Returns true if this frame is a data frame.
32+
fn is_data_frame(&self) -> bool {
33+
!self.is_remote_frame()
34+
}
35+
36+
/// Returns the frame identifier.
37+
fn id(&self) -> Id;
38+
39+
/// Returns the data length code (DLC) which is in the range 0..8.
40+
///
41+
/// For data frames the DLC value always matches the length of the data.
42+
/// Remote frames do not carry any data, yet the DLC can be greater than 0.
43+
fn dlc(&self) -> usize;
44+
45+
/// Returns the frame data (0..8 bytes in length).
46+
fn data(&self) -> &[u8];
47+
}

src/can/nb.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//! Non-blocking CAN API
2+
3+
/// A CAN interface that is able to transmit and receive frames.
4+
pub trait Can {
5+
/// Associated frame type.
6+
type Frame: crate::can::Frame;
7+
8+
/// Associated error type.
9+
type Error;
10+
11+
/// Puts a frame in the transmit buffer to be sent on the bus.
12+
///
13+
/// If the transmit buffer is full, this function will try to replace a pending
14+
/// lower priority frame and return the frame that was replaced.
15+
/// Returns `Err(WouldBlock)` if the transmit buffer is full and no frame can be
16+
/// replaced.
17+
///
18+
/// # Notes for implementers
19+
///
20+
/// * Frames of equal identifier shall be transmited in FIFO fashion when more
21+
/// than one transmit buffer is available.
22+
/// * When replacing pending frames make sure the frame is not in the process of
23+
/// being send to the bus.
24+
fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error>;
25+
26+
/// Returns a received frame if available.
27+
fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;
28+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@
409409
pub mod fmt;
410410
pub use nb;
411411
pub mod adc;
412+
pub mod can;
412413
pub mod capture;
413414
pub mod delay;
414415
pub mod digital;

0 commit comments

Comments
 (0)