Use Result instead of Option for Frame creation.
This commit is contained in:
parent
12a3af5043
commit
242759a600
9 changed files with 78 additions and 100 deletions
|
@ -44,7 +44,6 @@ pub type Data = crate::can::frame::ClassicData;
|
||||||
pub type Frame = crate::can::frame::ClassicFrame;
|
pub type Frame = crate::can::frame::ClassicFrame;
|
||||||
|
|
||||||
use crate::can::bx::filter::MasterFilters;
|
use crate::can::bx::filter::MasterFilters;
|
||||||
use crate::can::frame::ClassicData;
|
|
||||||
|
|
||||||
/// A bxCAN peripheral instance.
|
/// A bxCAN peripheral instance.
|
||||||
///
|
///
|
||||||
|
@ -799,10 +798,7 @@ where
|
||||||
data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
|
data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
|
||||||
let len = mb.tdtr().read().dlc();
|
let len = mb.tdtr().read().dlc();
|
||||||
|
|
||||||
Some(Frame::new(
|
Some(Frame::new(Header::new(id, len, false), &data).unwrap())
|
||||||
Header::new(id, len, false),
|
|
||||||
ClassicData::new(&data).unwrap(),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
// Abort request failed because the frame was already sent (or being sent) on
|
// Abort request failed because the frame was already sent (or being sent) on
|
||||||
// the bus. All mailboxes are now free. This can happen for small prescaler
|
// the bus. All mailboxes are now free. This can happen for small prescaler
|
||||||
|
@ -944,10 +940,7 @@ fn receive_fifo(canregs: crate::pac::can::Can, fifo_nr: usize) -> nb::Result<Fra
|
||||||
// Release the mailbox.
|
// Release the mailbox.
|
||||||
rfr.write(|w| w.set_rfom(true));
|
rfr.write(|w| w.set_rfom(true));
|
||||||
|
|
||||||
Ok(Frame::new(
|
Ok(Frame::new(Header::new(id, len, false), &data).unwrap())
|
||||||
Header::new(id, len, false),
|
|
||||||
ClassicData::new(&data).unwrap(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identifies one of the two receive FIFOs.
|
/// Identifies one of the two receive FIFOs.
|
||||||
|
|
|
@ -274,7 +274,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
|
data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
|
||||||
data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
|
data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
|
||||||
|
|
||||||
let frame = Frame::new(Header::new(id, data_len, false), Data::new(&data).unwrap());
|
let frame = Frame::new(Header::new(id, data_len, false), &data).unwrap();
|
||||||
let envelope = Envelope {
|
let envelope = Envelope {
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
ts,
|
ts,
|
||||||
|
|
|
@ -28,3 +28,15 @@ pub enum BusError {
|
||||||
/// At least one of error counter has reached the Error_Warning limit of 96.
|
/// At least one of error counter has reached the Error_Warning limit of 96.
|
||||||
BusWarning,
|
BusWarning,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Frame Create Errors
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum FrameCreateError {
|
||||||
|
/// Data in header does not match supplied.
|
||||||
|
NotEnoughData,
|
||||||
|
/// Invalid data length not 0-8 for Classic packet or valid for FD.
|
||||||
|
InvalidDataLength,
|
||||||
|
/// Invalid ID.
|
||||||
|
InvalidCanId,
|
||||||
|
}
|
||||||
|
|
|
@ -56,7 +56,10 @@ impl Registers {
|
||||||
match maybe_header {
|
match maybe_header {
|
||||||
Some((header, ts)) => {
|
Some((header, ts)) => {
|
||||||
let data = &buffer[0..header.len() as usize];
|
let data = &buffer[0..header.len() as usize];
|
||||||
Some((F::from_header(header, data)?, ts))
|
match F::from_header(header, data) {
|
||||||
|
Ok(frame) => Some((frame, ts)),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Definition for CAN Frames
|
//! Definition for CAN Frames
|
||||||
use bit_field::BitField;
|
use bit_field::BitField;
|
||||||
|
|
||||||
|
use crate::can::enums::FrameCreateError;
|
||||||
|
|
||||||
/// CAN Header, without meta data
|
/// CAN Header, without meta data
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
|
@ -82,7 +84,7 @@ impl Header {
|
||||||
/// and to retrieve the Header from a frame
|
/// and to retrieve the Header from a frame
|
||||||
pub trait CanHeader: Sized {
|
pub trait CanHeader: Sized {
|
||||||
/// Construct frame from header and payload
|
/// Construct frame from header and payload
|
||||||
fn from_header(header: Header, data: &[u8]) -> Option<Self>;
|
fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError>;
|
||||||
|
|
||||||
/// Get this frame's header struct
|
/// Get this frame's header struct
|
||||||
fn header(&self) -> &Header;
|
fn header(&self) -> &Header;
|
||||||
|
@ -103,15 +105,15 @@ impl ClassicData {
|
||||||
///
|
///
|
||||||
/// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
|
/// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
|
||||||
/// cannot be represented with an FDCAN DLC.
|
/// cannot be represented with an FDCAN DLC.
|
||||||
pub fn new(data: &[u8]) -> Option<Self> {
|
pub fn new(data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if !FdData::is_valid_len(data.len()) {
|
if data.len() > 8 {
|
||||||
return None;
|
return Err(FrameCreateError::InvalidDataLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bytes = [0; 8];
|
let mut bytes = [0; 8];
|
||||||
bytes[..data.len()].copy_from_slice(data);
|
bytes[..data.len()].copy_from_slice(data);
|
||||||
|
|
||||||
Some(Self { bytes })
|
Ok(Self { bytes })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raw read access to data.
|
/// Raw read access to data.
|
||||||
|
@ -134,12 +136,6 @@ impl ClassicData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[u8]> for ClassicData {
|
|
||||||
fn from(d: &[u8]) -> Self {
|
|
||||||
ClassicData::new(d).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Frame with up to 8 bytes of data payload as per Classic CAN
|
/// Frame with up to 8 bytes of data payload as per Classic CAN
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
@ -150,59 +146,42 @@ pub struct ClassicFrame {
|
||||||
|
|
||||||
impl ClassicFrame {
|
impl ClassicFrame {
|
||||||
/// Create a new CAN classic Frame
|
/// Create a new CAN classic Frame
|
||||||
pub fn new(can_header: Header, data: impl Into<ClassicData>) -> ClassicFrame {
|
pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
ClassicFrame {
|
let data = ClassicData::new(raw_data)?;
|
||||||
can_header,
|
Ok(ClassicFrame { can_header, data: data })
|
||||||
data: data.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new data frame.
|
/// Creates a new data frame.
|
||||||
pub fn new_data(id: impl Into<embedded_can::Id>, data: &[u8]) -> Self {
|
pub fn new_data(id: impl Into<embedded_can::Id>, data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
let eid: embedded_can::Id = id.into();
|
let eid: embedded_can::Id = id.into();
|
||||||
let header = Header::new(eid, data.len() as u8, false);
|
let header = Header::new(eid, data.len() as u8, false);
|
||||||
Self::new(header, data)
|
Self::new(header, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new extended frame
|
/// Create new extended frame
|
||||||
pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Option<Self> {
|
pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
|
if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
|
||||||
match ClassicData::new(raw_data) {
|
Self::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data)
|
||||||
Some(data) => Some(ClassicFrame::new(
|
|
||||||
Header::new(id.into(), raw_data.len() as u8, false),
|
|
||||||
data,
|
|
||||||
)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidCanId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new standard frame
|
/// Create new standard frame
|
||||||
pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Option<Self> {
|
pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if let Some(id) = embedded_can::StandardId::new(raw_id) {
|
if let Some(id) = embedded_can::StandardId::new(raw_id) {
|
||||||
match ClassicData::new(raw_data) {
|
Self::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data)
|
||||||
Some(data) => Some(ClassicFrame::new(
|
|
||||||
Header::new(id.into(), raw_data.len() as u8, false),
|
|
||||||
data,
|
|
||||||
)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidCanId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new remote frame
|
/// Create new remote frame
|
||||||
pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Result<Self, FrameCreateError> {
|
||||||
if len <= 8usize {
|
if len <= 8usize {
|
||||||
Some(ClassicFrame::new(
|
Self::new(Header::new(id.into(), len as u8, true), &[0; 8])
|
||||||
Header::new(id.into(), len as u8, true),
|
|
||||||
ClassicData::empty(),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidDataLength)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,20 +208,19 @@ impl ClassicFrame {
|
||||||
|
|
||||||
impl embedded_can::Frame for ClassicFrame {
|
impl embedded_can::Frame for ClassicFrame {
|
||||||
fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
|
fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
|
||||||
match ClassicData::new(raw_data) {
|
let frameopt = ClassicFrame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data);
|
||||||
Some(data) => Some(ClassicFrame::new(
|
match frameopt {
|
||||||
Header::new(id.into(), raw_data.len() as u8, false),
|
Ok(frame) => Some(frame),
|
||||||
data,
|
Err(_) => None,
|
||||||
)),
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
||||||
if len <= 8 {
|
if len <= 8 {
|
||||||
Some(ClassicFrame::new(
|
let frameopt = ClassicFrame::new(Header::new(id.into(), len as u8, true), &[0; 8]);
|
||||||
Header::new(id.into(), len as u8, true),
|
match frameopt {
|
||||||
ClassicData::empty(),
|
Ok(frame) => Some(frame),
|
||||||
))
|
Err(_) => None,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -268,8 +246,8 @@ impl embedded_can::Frame for ClassicFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanHeader for ClassicFrame {
|
impl CanHeader for ClassicFrame {
|
||||||
fn from_header(header: Header, data: &[u8]) -> Option<Self> {
|
fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
Some(Self::new(header, ClassicData::new(data)?))
|
Self::new(header, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header(&self) -> &Header {
|
fn header(&self) -> &Header {
|
||||||
|
@ -290,15 +268,15 @@ impl FdData {
|
||||||
///
|
///
|
||||||
/// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
|
/// Returns `None` if `data` is more than 64 bytes (which is the maximum) or
|
||||||
/// cannot be represented with an FDCAN DLC.
|
/// cannot be represented with an FDCAN DLC.
|
||||||
pub fn new(data: &[u8]) -> Option<Self> {
|
pub fn new(data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if !FdData::is_valid_len(data.len()) {
|
if !FdData::is_valid_len(data.len()) {
|
||||||
return None;
|
return Err(FrameCreateError::InvalidDataLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bytes = [0; 64];
|
let mut bytes = [0; 64];
|
||||||
bytes[..data.len()].copy_from_slice(data);
|
bytes[..data.len()].copy_from_slice(data);
|
||||||
|
|
||||||
Some(Self { bytes })
|
Ok(Self { bytes })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raw read access to data.
|
/// Raw read access to data.
|
||||||
|
@ -337,40 +315,35 @@ pub struct FdFrame {
|
||||||
|
|
||||||
impl FdFrame {
|
impl FdFrame {
|
||||||
/// Create a new CAN classic Frame
|
/// Create a new CAN classic Frame
|
||||||
pub fn new(can_header: Header, data: FdData) -> FdFrame {
|
pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
FdFrame { can_header, data }
|
let data = FdData::new(raw_data)?;
|
||||||
|
Ok(FdFrame { can_header, data })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new extended frame
|
/// Create new extended frame
|
||||||
pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Option<Self> {
|
pub fn new_extended(raw_id: u32, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
|
if let Some(id) = embedded_can::ExtendedId::new(raw_id) {
|
||||||
match FdData::new(raw_data) {
|
Self::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data)
|
||||||
Some(data) => Some(FdFrame::new(Header::new(id.into(), raw_data.len() as u8, false), data)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidCanId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new standard frame
|
/// Create new standard frame
|
||||||
pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Option<Self> {
|
pub fn new_standard(raw_id: u16, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
if let Some(id) = embedded_can::StandardId::new(raw_id) {
|
if let Some(id) = embedded_can::StandardId::new(raw_id) {
|
||||||
match FdData::new(raw_data) {
|
Self::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data)
|
||||||
Some(data) => Some(FdFrame::new(Header::new(id.into(), raw_data.len() as u8, false), data)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidCanId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new remote frame
|
/// Create new remote frame
|
||||||
pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
pub fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Result<Self, FrameCreateError> {
|
||||||
if len <= 8 {
|
if len <= 8 {
|
||||||
Some(FdFrame::new(Header::new(id.into(), len as u8, true), FdData::empty()))
|
Self::new(Header::new(id.into(), len as u8, true), &[0; 8])
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(FrameCreateError::InvalidDataLength)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,20 +365,17 @@ impl FdFrame {
|
||||||
|
|
||||||
impl embedded_can::Frame for FdFrame {
|
impl embedded_can::Frame for FdFrame {
|
||||||
fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
|
fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> {
|
||||||
match FdData::new(raw_data) {
|
match FdFrame::new(Header::new_fd(id.into(), raw_data.len() as u8, false, true), raw_data) {
|
||||||
Some(data) => Some(FdFrame::new(
|
Ok(frame) => Some(frame),
|
||||||
Header::new_fd(id.into(), raw_data.len() as u8, false, true),
|
Err(_) => None,
|
||||||
data,
|
|
||||||
)),
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
|
||||||
if len <= 8 {
|
if len <= 8 {
|
||||||
Some(FdFrame::new(
|
match FdFrame::new(Header::new_fd(id.into(), len as u8, true, true), &[0; 64]) {
|
||||||
Header::new_fd(id.into(), len as u8, true, true),
|
Ok(frame) => Some(frame),
|
||||||
FdData::empty(),
|
Err(_) => None,
|
||||||
))
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -432,8 +402,8 @@ impl embedded_can::Frame for FdFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanHeader for FdFrame {
|
impl CanHeader for FdFrame {
|
||||||
fn from_header(header: Header, data: &[u8]) -> Option<Self> {
|
fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> {
|
||||||
Some(Self::new(header, FdData::new(data)?))
|
Self::new(header, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header(&self) -> &Header {
|
fn header(&self) -> &Header {
|
||||||
|
|
|
@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
let mut i: u8 = 0;
|
let mut i: u8 = 0;
|
||||||
loop {
|
loop {
|
||||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]);
|
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap();
|
||||||
can.write(&tx_frame).await;
|
can.write(&tx_frame).await;
|
||||||
|
|
||||||
match can.read().await {
|
match can.read().await {
|
||||||
|
|
|
@ -51,7 +51,7 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
let mut i: u8 = 0;
|
let mut i: u8 = 0;
|
||||||
loop {
|
loop {
|
||||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i]);
|
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i]).unwrap();
|
||||||
let tx_ts = Instant::now();
|
let tx_ts = Instant::now();
|
||||||
can.write(&tx_frame).await;
|
can.write(&tx_frame).await;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs {
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
pub async fn send_can_message(tx: &'static mut CanTx<'static, CAN3>) {
|
pub async fn send_can_message(tx: &'static mut CanTx<'static, CAN3>) {
|
||||||
loop {
|
loop {
|
||||||
let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), &[0]);
|
let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), &[0]).unwrap();
|
||||||
tx.write(&frame).await;
|
tx.write(&frame).await;
|
||||||
embassy_time::Timer::after_secs(1).await;
|
embassy_time::Timer::after_secs(1).await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
let mut i: u8 = 0;
|
let mut i: u8 = 0;
|
||||||
loop {
|
loop {
|
||||||
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i]);
|
let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i]).unwrap();
|
||||||
|
|
||||||
info!("Transmitting frame...");
|
info!("Transmitting frame...");
|
||||||
let tx_ts = Instant::now();
|
let tx_ts = Instant::now();
|
||||||
|
|
Loading…
Reference in a new issue