diff options
| -rw-r--r-- | embassy-stm32/src/can/bx/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/can/bxcan.rs | 27 | ||||
| -rw-r--r-- | embassy-stm32/src/can/common.rs | 23 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fd/peripheral.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 140 | ||||
| -rw-r--r-- | embassy-stm32/src/can/frame.rs | 60 | ||||
| -rw-r--r-- | examples/stm32f1/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/can.rs | 102 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 29 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/can.rs | 12 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/can.rs | 12 | ||||
| -rw-r--r-- | tests/stm32/src/bin/fdcan.rs | 24 |
12 files changed, 295 insertions, 152 deletions
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs index c508ef2fe..253bcee13 100644 --- a/embassy-stm32/src/can/bx/mod.rs +++ b/embassy-stm32/src/can/bx/mod.rs | |||
| @@ -40,12 +40,11 @@ pub type Header = crate::can::frame::Header; | |||
| 40 | /// Data for a CAN Frame | 40 | /// Data for a CAN Frame |
| 41 | pub type Data = crate::can::frame::ClassicData; | 41 | pub type Data = crate::can::frame::ClassicData; |
| 42 | 42 | ||
| 43 | /// CAN Frame | ||
| 44 | pub type Frame = crate::can::frame::ClassicFrame; | ||
| 45 | |||
| 46 | use crate::can::_version::Envelope; | 43 | use crate::can::_version::Envelope; |
| 47 | use crate::can::bx::filter::MasterFilters; | 44 | use crate::can::bx::filter::MasterFilters; |
| 48 | use crate::can::enums::BusError; | 45 | use crate::can::enums::BusError; |
| 46 | /// CAN Frame | ||
| 47 | pub use crate::can::frame::Frame; | ||
| 49 | use crate::pac::can::vals::Lec; | 48 | use crate::pac::can::vals::Lec; |
| 50 | 49 | ||
| 51 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 50 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index be2e34963..fd6a79092 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -19,22 +19,10 @@ use crate::{interrupt, peripherals, Peripheral}; | |||
| 19 | pub mod enums; | 19 | pub mod enums; |
| 20 | pub mod frame; | 20 | pub mod frame; |
| 21 | pub mod util; | 21 | pub mod util; |
| 22 | pub use frame::Envelope; | ||
| 22 | 23 | ||
| 23 | mod common; | 24 | mod common; |
| 24 | pub use self::common::{BufferedCanReceiver, BufferedCanSender, Timestamp}; | 25 | pub use self::common::{BufferedCanReceiver, BufferedCanSender}; |
| 25 | |||
| 26 | /// Contains CAN frame and additional metadata. | ||
| 27 | /// | ||
| 28 | /// Timestamp is available if `time` feature is enabled. | ||
| 29 | #[derive(Debug, Clone)] | ||
| 30 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 31 | pub struct Envelope { | ||
| 32 | /// Reception time. | ||
| 33 | #[cfg(feature = "time")] | ||
| 34 | pub ts: embassy_time::Instant, | ||
| 35 | /// The actual CAN frame. | ||
| 36 | pub frame: Frame, | ||
| 37 | } | ||
| 38 | 26 | ||
| 39 | /// Interrupt handler. | 27 | /// Interrupt handler. |
| 40 | pub struct TxInterruptHandler<T: Instance> { | 28 | pub struct TxInterruptHandler<T: Instance> { |
| @@ -276,7 +264,7 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer | |||
| 276 | } | 264 | } |
| 277 | 265 | ||
| 278 | /// Async read frame from RX buffer. | 266 | /// Async read frame from RX buffer. |
| 279 | pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> { | 267 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 280 | self.rx.read().await | 268 | self.rx.read().await |
| 281 | } | 269 | } |
| 282 | 270 | ||
| @@ -482,8 +470,7 @@ impl<'d, T: Instance> CanRx<'d, T> { | |||
| 482 | } | 470 | } |
| 483 | 471 | ||
| 484 | /// User supplied buffer for RX Buffering | 472 | /// User supplied buffer for RX Buffering |
| 485 | pub type RxBuf<const BUF_SIZE: usize> = | 473 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; |
| 486 | Channel<CriticalSectionRawMutex, Result<(Frame, Timestamp), BusError>, BUF_SIZE>; | ||
| 487 | 474 | ||
| 488 | /// CAN driver, receive half in Buffered mode. | 475 | /// CAN driver, receive half in Buffered mode. |
| 489 | pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { | 476 | pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { |
| @@ -508,7 +495,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE | |||
| 508 | } | 495 | } |
| 509 | 496 | ||
| 510 | /// Async read frame from RX buffer. | 497 | /// Async read frame from RX buffer. |
| 511 | pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> { | 498 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 512 | self.rx_buf.receive().await | 499 | self.rx_buf.receive().await |
| 513 | } | 500 | } |
| 514 | 501 | ||
| @@ -520,7 +507,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE | |||
| 520 | RxMode::Buffered(_) => { | 507 | RxMode::Buffered(_) => { |
| 521 | if let Ok(result) = self.rx_buf.try_receive() { | 508 | if let Ok(result) = self.rx_buf.try_receive() { |
| 522 | match result { | 509 | match result { |
| 523 | Ok((frame, ts)) => Ok(Envelope { ts, frame }), | 510 | Ok(envelope) => Ok(envelope), |
| 524 | Err(e) => Err(TryReadError::BusError(e)), | 511 | Err(e) => Err(TryReadError::BusError(e)), |
| 525 | } | 512 | } |
| 526 | } else { | 513 | } else { |
| @@ -610,7 +597,7 @@ impl RxMode { | |||
| 610 | match regsisters.receive_fifo(fifo) { | 597 | match regsisters.receive_fifo(fifo) { |
| 611 | Some(envelope) => { | 598 | Some(envelope) => { |
| 612 | // NOTE: consensus was reached that if rx_queue is full, packets should be dropped | 599 | // NOTE: consensus was reached that if rx_queue is full, packets should be dropped |
| 613 | let _ = buf.rx_sender.try_send(Ok((envelope.frame, envelope.ts))); | 600 | let _ = buf.rx_sender.try_send(Ok(envelope)); |
| 614 | } | 601 | } |
| 615 | None => return, | 602 | None => return, |
| 616 | }; | 603 | }; |
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs index b0d177a6d..570761b19 100644 --- a/embassy-stm32/src/can/common.rs +++ b/embassy-stm32/src/can/common.rs | |||
| @@ -3,25 +3,17 @@ use embassy_sync::channel::{DynamicReceiver, DynamicSender}; | |||
| 3 | use crate::can::_version::enums::*; | 3 | use crate::can::_version::enums::*; |
| 4 | use crate::can::_version::frame::*; | 4 | use crate::can::_version::frame::*; |
| 5 | 5 | ||
| 6 | /// Timestamp for incoming packets. Use Embassy time when enabled. | ||
| 7 | #[cfg(feature = "time")] | ||
| 8 | pub type Timestamp = embassy_time::Instant; | ||
| 9 | |||
| 10 | /// Timestamp for incoming packets. | ||
| 11 | #[cfg(not(feature = "time"))] | ||
| 12 | pub type Timestamp = u16; | ||
| 13 | |||
| 14 | pub(crate) struct ClassicBufferedRxInner { | 6 | pub(crate) struct ClassicBufferedRxInner { |
| 15 | pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, | 7 | pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>, |
| 16 | } | 8 | } |
| 17 | pub(crate) struct ClassicBufferedTxInner { | 9 | pub(crate) struct ClassicBufferedTxInner { |
| 18 | pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, | 10 | pub tx_receiver: DynamicReceiver<'static, Frame>, |
| 19 | } | 11 | } |
| 20 | 12 | ||
| 21 | #[cfg(any(can_fdcan_v1, can_fdcan_h7))] | 13 | #[cfg(any(can_fdcan_v1, can_fdcan_h7))] |
| 22 | 14 | ||
| 23 | pub(crate) struct FdBufferedRxInner { | 15 | pub(crate) struct FdBufferedRxInner { |
| 24 | pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, | 16 | pub rx_sender: DynamicSender<'static, Result<FdEnvelope, BusError>>, |
| 25 | } | 17 | } |
| 26 | 18 | ||
| 27 | #[cfg(any(can_fdcan_v1, can_fdcan_h7))] | 19 | #[cfg(any(can_fdcan_v1, can_fdcan_h7))] |
| @@ -32,20 +24,20 @@ pub(crate) struct FdBufferedTxInner { | |||
| 32 | /// Sender that can be used for sending CAN frames. | 24 | /// Sender that can be used for sending CAN frames. |
| 33 | #[derive(Copy, Clone)] | 25 | #[derive(Copy, Clone)] |
| 34 | pub struct BufferedCanSender { | 26 | pub struct BufferedCanSender { |
| 35 | pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, ClassicFrame>, | 27 | pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, Frame>, |
| 36 | pub(crate) waker: fn(), | 28 | pub(crate) waker: fn(), |
| 37 | } | 29 | } |
| 38 | 30 | ||
| 39 | impl BufferedCanSender { | 31 | impl BufferedCanSender { |
| 40 | /// Async write frame to TX buffer. | 32 | /// Async write frame to TX buffer. |
| 41 | pub fn try_write(&mut self, frame: ClassicFrame) -> Result<(), embassy_sync::channel::TrySendError<ClassicFrame>> { | 33 | pub fn try_write(&mut self, frame: Frame) -> Result<(), embassy_sync::channel::TrySendError<Frame>> { |
| 42 | self.tx_buf.try_send(frame)?; | 34 | self.tx_buf.try_send(frame)?; |
| 43 | (self.waker)(); | 35 | (self.waker)(); |
| 44 | Ok(()) | 36 | Ok(()) |
| 45 | } | 37 | } |
| 46 | 38 | ||
| 47 | /// Async write frame to TX buffer. | 39 | /// Async write frame to TX buffer. |
| 48 | pub async fn write(&mut self, frame: ClassicFrame) { | 40 | pub async fn write(&mut self, frame: Frame) { |
| 49 | self.tx_buf.send(frame).await; | 41 | self.tx_buf.send(frame).await; |
| 50 | (self.waker)(); | 42 | (self.waker)(); |
| 51 | } | 43 | } |
| @@ -57,5 +49,4 @@ impl BufferedCanSender { | |||
| 57 | } | 49 | } |
| 58 | 50 | ||
| 59 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 51 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 60 | pub type BufferedCanReceiver = | 52 | pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, Result<Envelope, BusError>>; |
| 61 | embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>; | ||
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs index 76b76afe1..e32f19d91 100644 --- a/embassy-stm32/src/can/fd/peripheral.rs +++ b/embassy-stm32/src/can/fd/peripheral.rs | |||
| @@ -397,13 +397,13 @@ impl Registers { | |||
| 397 | 397 | ||
| 398 | /// Moves out of ConfigMode and into specified mode | 398 | /// Moves out of ConfigMode and into specified mode |
| 399 | #[inline] | 399 | #[inline] |
| 400 | pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::FdcanOperatingMode) { | 400 | pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::OperatingMode) { |
| 401 | match mode { | 401 | match mode { |
| 402 | crate::can::FdcanOperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal), | 402 | crate::can::OperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal), |
| 403 | crate::can::FdcanOperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External), | 403 | crate::can::OperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External), |
| 404 | crate::can::FdcanOperatingMode::NormalOperationMode => self.set_normal_operations(true), | 404 | crate::can::OperatingMode::NormalOperationMode => self.set_normal_operations(true), |
| 405 | crate::can::FdcanOperatingMode::RestrictedOperationMode => self.set_restricted_operations(true), | 405 | crate::can::OperatingMode::RestrictedOperationMode => self.set_restricted_operations(true), |
| 406 | crate::can::FdcanOperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true), | 406 | crate::can::OperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true), |
| 407 | } | 407 | } |
| 408 | self.leave_init_mode(config); | 408 | self.leave_init_mode(config); |
| 409 | } | 409 | } |
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index e58d8c0ec..2ccf4b093 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -110,7 +110,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1Interrup | |||
| 110 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 110 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
| 111 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 111 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 112 | /// Different operating modes | 112 | /// Different operating modes |
| 113 | pub enum FdcanOperatingMode { | 113 | pub enum OperatingMode { |
| 114 | //PoweredDownMode, | 114 | //PoweredDownMode, |
| 115 | //ConfigMode, | 115 | //ConfigMode, |
| 116 | /// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without | 116 | /// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without |
| @@ -148,7 +148,7 @@ pub enum FdcanOperatingMode { | |||
| 148 | 148 | ||
| 149 | /// FDCAN Configuration instance instance | 149 | /// FDCAN Configuration instance instance |
| 150 | /// Create instance of this first | 150 | /// Create instance of this first |
| 151 | pub struct FdcanConfigurator<'d, T: Instance> { | 151 | pub struct CanConfigurator<'d, T: Instance> { |
| 152 | config: crate::can::fd::config::FdCanConfig, | 152 | config: crate::can::fd::config::FdCanConfig, |
| 153 | /// Reference to internals. | 153 | /// Reference to internals. |
| 154 | instance: FdcanInstance<'d, T>, | 154 | instance: FdcanInstance<'d, T>, |
| @@ -169,7 +169,7 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransm | |||
| 169 | } | 169 | } |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | impl<'d, T: Instance> FdcanConfigurator<'d, T> { | 172 | impl<'d, T: Instance> CanConfigurator<'d, T> { |
| 173 | /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. | 173 | /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. |
| 174 | /// You must call [Fdcan::enable_non_blocking] to use the peripheral. | 174 | /// You must call [Fdcan::enable_non_blocking] to use the peripheral. |
| 175 | pub fn new( | 175 | pub fn new( |
| @@ -179,7 +179,7 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> { | |||
| 179 | _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>> | 179 | _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>> |
| 180 | + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>> | 180 | + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>> |
| 181 | + 'd, | 181 | + 'd, |
| 182 | ) -> FdcanConfigurator<'d, T> { | 182 | ) -> CanConfigurator<'d, T> { |
| 183 | into_ref!(peri, rx, tx); | 183 | into_ref!(peri, rx, tx); |
| 184 | 184 | ||
| 185 | rx.set_as_af(rx.af_num(), AFType::Input); | 185 | rx.set_as_af(rx.af_num(), AFType::Input); |
| @@ -273,13 +273,13 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> { | |||
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | /// Start in mode. | 275 | /// Start in mode. |
| 276 | pub fn start(self, mode: FdcanOperatingMode) -> Fdcan<'d, T> { | 276 | pub fn start(self, mode: OperatingMode) -> Can<'d, T> { |
| 277 | let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit); | 277 | let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit); |
| 278 | critical_section::with(|_| unsafe { | 278 | critical_section::with(|_| unsafe { |
| 279 | T::mut_state().ns_per_timer_tick = ns_per_timer_tick; | 279 | T::mut_state().ns_per_timer_tick = ns_per_timer_tick; |
| 280 | }); | 280 | }); |
| 281 | T::registers().into_mode(self.config, mode); | 281 | T::registers().into_mode(self.config, mode); |
| 282 | let ret = Fdcan { | 282 | let ret = Can { |
| 283 | config: self.config, | 283 | config: self.config, |
| 284 | instance: self.instance, | 284 | instance: self.instance, |
| 285 | _mode: mode, | 285 | _mode: mode, |
| @@ -288,30 +288,30 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> { | |||
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | /// Start, entering mode. Does same as start(mode) | 290 | /// Start, entering mode. Does same as start(mode) |
| 291 | pub fn into_normal_mode(self) -> Fdcan<'d, T> { | 291 | pub fn into_normal_mode(self) -> Can<'d, T> { |
| 292 | self.start(FdcanOperatingMode::NormalOperationMode) | 292 | self.start(OperatingMode::NormalOperationMode) |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | /// Start, entering mode. Does same as start(mode) | 295 | /// Start, entering mode. Does same as start(mode) |
| 296 | pub fn into_internal_loopback_mode(self) -> Fdcan<'d, T> { | 296 | pub fn into_internal_loopback_mode(self) -> Can<'d, T> { |
| 297 | self.start(FdcanOperatingMode::InternalLoopbackMode) | 297 | self.start(OperatingMode::InternalLoopbackMode) |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | /// Start, entering mode. Does same as start(mode) | 300 | /// Start, entering mode. Does same as start(mode) |
| 301 | pub fn into_external_loopback_mode(self) -> Fdcan<'d, T> { | 301 | pub fn into_external_loopback_mode(self) -> Can<'d, T> { |
| 302 | self.start(FdcanOperatingMode::ExternalLoopbackMode) | 302 | self.start(OperatingMode::ExternalLoopbackMode) |
| 303 | } | 303 | } |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | /// FDCAN Instance | 306 | /// FDCAN Instance |
| 307 | pub struct Fdcan<'d, T: Instance> { | 307 | pub struct Can<'d, T: Instance> { |
| 308 | config: crate::can::fd::config::FdCanConfig, | 308 | config: crate::can::fd::config::FdCanConfig, |
| 309 | /// Reference to internals. | 309 | /// Reference to internals. |
| 310 | instance: FdcanInstance<'d, T>, | 310 | instance: FdcanInstance<'d, T>, |
| 311 | _mode: FdcanOperatingMode, | 311 | _mode: OperatingMode, |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | impl<'d, T: Instance> Fdcan<'d, T> { | 314 | impl<'d, T: Instance> Can<'d, T> { |
| 315 | /// Flush one of the TX mailboxes. | 315 | /// Flush one of the TX mailboxes. |
| 316 | pub async fn flush(&self, idx: usize) { | 316 | pub async fn flush(&self, idx: usize) { |
| 317 | poll_fn(|cx| { | 317 | poll_fn(|cx| { |
| @@ -334,12 +334,12 @@ impl<'d, T: Instance> Fdcan<'d, T> { | |||
| 334 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 334 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 335 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 335 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 336 | /// transmitted, then tries again. | 336 | /// transmitted, then tries again. |
| 337 | pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> { | 337 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { |
| 338 | T::state().tx_mode.write::<T>(frame).await | 338 | T::state().tx_mode.write::<T>(frame).await |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | /// Returns the next received message frame | 341 | /// Returns the next received message frame |
| 342 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { | 342 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 343 | T::state().rx_mode.read_classic::<T>().await | 343 | T::state().rx_mode.read_classic::<T>().await |
| 344 | } | 344 | } |
| 345 | 345 | ||
| @@ -352,19 +352,19 @@ impl<'d, T: Instance> Fdcan<'d, T> { | |||
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | /// Returns the next received message frame | 354 | /// Returns the next received message frame |
| 355 | pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> { | 355 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { |
| 356 | T::state().rx_mode.read_fd::<T>().await | 356 | T::state().rx_mode.read_fd::<T>().await |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | /// Split instance into separate Tx(write) and Rx(read) portions | 359 | /// Split instance into separate Tx(write) and Rx(read) portions |
| 360 | pub fn split(self) -> (FdcanTx<'d, T>, FdcanRx<'d, T>) { | 360 | pub fn split(self) -> (CanTx<'d, T>, CanRx<'d, T>) { |
| 361 | ( | 361 | ( |
| 362 | FdcanTx { | 362 | CanTx { |
| 363 | config: self.config, | 363 | config: self.config, |
| 364 | _instance: self.instance, | 364 | _instance: self.instance, |
| 365 | _mode: self._mode, | 365 | _mode: self._mode, |
| 366 | }, | 366 | }, |
| 367 | FdcanRx { | 367 | CanRx { |
| 368 | _instance1: PhantomData::<T>, | 368 | _instance1: PhantomData::<T>, |
| 369 | _instance2: T::regs(), | 369 | _instance2: T::regs(), |
| 370 | _mode: self._mode, | 370 | _mode: self._mode, |
| @@ -373,8 +373,8 @@ impl<'d, T: Instance> Fdcan<'d, T> { | |||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | /// Join split rx and tx portions back together | 375 | /// Join split rx and tx portions back together |
| 376 | pub fn join(tx: FdcanTx<'d, T>, rx: FdcanRx<'d, T>) -> Self { | 376 | pub fn join(tx: CanTx<'d, T>, rx: CanRx<'d, T>) -> Self { |
| 377 | Fdcan { | 377 | Can { |
| 378 | config: tx.config, | 378 | config: tx.config, |
| 379 | //_instance2: T::regs(), | 379 | //_instance2: T::regs(), |
| 380 | instance: tx._instance, | 380 | instance: tx._instance, |
| @@ -402,17 +402,16 @@ impl<'d, T: Instance> Fdcan<'d, T> { | |||
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | /// User supplied buffer for RX Buffering | 404 | /// User supplied buffer for RX Buffering |
| 405 | pub type RxBuf<const BUF_SIZE: usize> = | 405 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; |
| 406 | Channel<CriticalSectionRawMutex, Result<(ClassicFrame, Timestamp), BusError>, BUF_SIZE>; | ||
| 407 | 406 | ||
| 408 | /// User supplied buffer for TX buffering | 407 | /// User supplied buffer for TX buffering |
| 409 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; | 408 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; |
| 410 | 409 | ||
| 411 | /// Buffered FDCAN Instance | 410 | /// Buffered FDCAN Instance |
| 412 | pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | 411 | pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 413 | _instance1: PhantomData<T>, | 412 | _instance1: PhantomData<T>, |
| 414 | _instance2: &'d crate::pac::can::Fdcan, | 413 | _instance2: &'d crate::pac::can::Fdcan, |
| 415 | _mode: FdcanOperatingMode, | 414 | _mode: OperatingMode, |
| 416 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | 415 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, |
| 417 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | 416 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, |
| 418 | } | 417 | } |
| @@ -423,7 +422,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 423 | fn new( | 422 | fn new( |
| 424 | _instance1: PhantomData<T>, | 423 | _instance1: PhantomData<T>, |
| 425 | _instance2: &'d crate::pac::can::Fdcan, | 424 | _instance2: &'d crate::pac::can::Fdcan, |
| 426 | _mode: FdcanOperatingMode, | 425 | _mode: OperatingMode, |
| 427 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | 426 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, |
| 428 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | 427 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, |
| 429 | ) -> Self { | 428 | ) -> Self { |
| @@ -453,13 +452,13 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 453 | } | 452 | } |
| 454 | 453 | ||
| 455 | /// Async write frame to TX buffer. | 454 | /// Async write frame to TX buffer. |
| 456 | pub async fn write(&mut self, frame: ClassicFrame) { | 455 | pub async fn write(&mut self, frame: Frame) { |
| 457 | self.tx_buf.send(frame).await; | 456 | self.tx_buf.send(frame).await; |
| 458 | T::IT0Interrupt::pend(); // Wake for Tx | 457 | T::IT0Interrupt::pend(); // Wake for Tx |
| 459 | } | 458 | } |
| 460 | 459 | ||
| 461 | /// Async read frame from RX buffer. | 460 | /// Async read frame from RX buffer. |
| 462 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { | 461 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 463 | self.rx_buf.receive().await | 462 | self.rx_buf.receive().await |
| 464 | } | 463 | } |
| 465 | 464 | ||
| @@ -489,8 +488,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr | |||
| 489 | } | 488 | } |
| 490 | 489 | ||
| 491 | /// User supplied buffer for RX Buffering | 490 | /// User supplied buffer for RX Buffering |
| 492 | pub type RxFdBuf<const BUF_SIZE: usize> = | 491 | pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>; |
| 493 | Channel<CriticalSectionRawMutex, Result<(FdFrame, Timestamp), BusError>, BUF_SIZE>; | ||
| 494 | 492 | ||
| 495 | /// User supplied buffer for TX buffering | 493 | /// User supplied buffer for TX buffering |
| 496 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | 494 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; |
| @@ -499,7 +497,7 @@ pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFra | |||
| 499 | pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | 497 | pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 500 | _instance1: PhantomData<T>, | 498 | _instance1: PhantomData<T>, |
| 501 | _instance2: &'d crate::pac::can::Fdcan, | 499 | _instance2: &'d crate::pac::can::Fdcan, |
| 502 | _mode: FdcanOperatingMode, | 500 | _mode: OperatingMode, |
| 503 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | 501 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, |
| 504 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | 502 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, |
| 505 | } | 503 | } |
| @@ -532,7 +530,7 @@ impl BufferedFdCanSender { | |||
| 532 | } | 530 | } |
| 533 | 531 | ||
| 534 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 532 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 535 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>; | 533 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>; |
| 536 | 534 | ||
| 537 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 535 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> |
| 538 | BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | 536 | BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> |
| @@ -540,7 +538,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 540 | fn new( | 538 | fn new( |
| 541 | _instance1: PhantomData<T>, | 539 | _instance1: PhantomData<T>, |
| 542 | _instance2: &'d crate::pac::can::Fdcan, | 540 | _instance2: &'d crate::pac::can::Fdcan, |
| 543 | _mode: FdcanOperatingMode, | 541 | _mode: OperatingMode, |
| 544 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | 542 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, |
| 545 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | 543 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, |
| 546 | ) -> Self { | 544 | ) -> Self { |
| @@ -576,7 +574,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 576 | } | 574 | } |
| 577 | 575 | ||
| 578 | /// Async read frame from RX buffer. | 576 | /// Async read frame from RX buffer. |
| 579 | pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { | 577 | pub async fn read(&mut self) -> Result<FdEnvelope, BusError> { |
| 580 | self.rx_buf.receive().await | 578 | self.rx_buf.receive().await |
| 581 | } | 579 | } |
| 582 | 580 | ||
| @@ -606,25 +604,25 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr | |||
| 606 | } | 604 | } |
| 607 | 605 | ||
| 608 | /// FDCAN Rx only Instance | 606 | /// FDCAN Rx only Instance |
| 609 | pub struct FdcanRx<'d, T: Instance> { | 607 | pub struct CanRx<'d, T: Instance> { |
| 610 | _instance1: PhantomData<T>, | 608 | _instance1: PhantomData<T>, |
| 611 | _instance2: &'d crate::pac::can::Fdcan, | 609 | _instance2: &'d crate::pac::can::Fdcan, |
| 612 | _mode: FdcanOperatingMode, | 610 | _mode: OperatingMode, |
| 613 | } | 611 | } |
| 614 | 612 | ||
| 615 | /// FDCAN Tx only Instance | 613 | /// FDCAN Tx only Instance |
| 616 | pub struct FdcanTx<'d, T: Instance> { | 614 | pub struct CanTx<'d, T: Instance> { |
| 617 | config: crate::can::fd::config::FdCanConfig, | 615 | config: crate::can::fd::config::FdCanConfig, |
| 618 | _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>); | 616 | _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>); |
| 619 | _mode: FdcanOperatingMode, | 617 | _mode: OperatingMode, |
| 620 | } | 618 | } |
| 621 | 619 | ||
| 622 | impl<'c, 'd, T: Instance> FdcanTx<'d, T> { | 620 | impl<'c, 'd, T: Instance> CanTx<'d, T> { |
| 623 | /// Queues the message to be sent but exerts backpressure. If a lower-priority | 621 | /// Queues the message to be sent but exerts backpressure. If a lower-priority |
| 624 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 622 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 625 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 623 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 626 | /// transmitted, then tries again. | 624 | /// transmitted, then tries again. |
| 627 | pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> { | 625 | pub async fn write(&mut self, frame: &Frame) -> Option<Frame> { |
| 628 | T::state().tx_mode.write::<T>(frame).await | 626 | T::state().tx_mode.write::<T>(frame).await |
| 629 | } | 627 | } |
| 630 | 628 | ||
| @@ -637,14 +635,14 @@ impl<'c, 'd, T: Instance> FdcanTx<'d, T> { | |||
| 637 | } | 635 | } |
| 638 | } | 636 | } |
| 639 | 637 | ||
| 640 | impl<'c, 'd, T: Instance> FdcanRx<'d, T> { | 638 | impl<'c, 'd, T: Instance> CanRx<'d, T> { |
| 641 | /// Returns the next received message frame | 639 | /// Returns the next received message frame |
| 642 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { | 640 | pub async fn read(&mut self) -> Result<Envelope, BusError> { |
| 643 | T::state().rx_mode.read_classic::<T>().await | 641 | T::state().rx_mode.read_classic::<T>().await |
| 644 | } | 642 | } |
| 645 | 643 | ||
| 646 | /// Returns the next received message frame | 644 | /// Returns the next received message frame |
| 647 | pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> { | 645 | pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> { |
| 648 | T::state().rx_mode.read_fd::<T>().await | 646 | T::state().rx_mode.read_fd::<T>().await |
| 649 | } | 647 | } |
| 650 | } | 648 | } |
| @@ -672,18 +670,50 @@ impl RxMode { | |||
| 672 | waker.wake(); | 670 | waker.wake(); |
| 673 | } | 671 | } |
| 674 | RxMode::ClassicBuffered(buf) => { | 672 | RxMode::ClassicBuffered(buf) => { |
| 675 | if let Some(result) = self.read::<T, _>() { | 673 | if let Some(result) = self.try_read::<T>() { |
| 676 | let _ = buf.rx_sender.try_send(result); | 674 | let _ = buf.rx_sender.try_send(result); |
| 677 | } | 675 | } |
| 678 | } | 676 | } |
| 679 | RxMode::FdBuffered(buf) => { | 677 | RxMode::FdBuffered(buf) => { |
| 680 | if let Some(result) = self.read::<T, _>() { | 678 | if let Some(result) = self.try_read_fd::<T>() { |
| 681 | let _ = buf.rx_sender.try_send(result); | 679 | let _ = buf.rx_sender.try_send(result); |
| 682 | } | 680 | } |
| 683 | } | 681 | } |
| 684 | } | 682 | } |
| 685 | } | 683 | } |
| 686 | 684 | ||
| 685 | //async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> { | ||
| 686 | fn try_read<T: Instance>(&self) -> Option<Result<Envelope, BusError>> { | ||
| 687 | if let Some((frame, ts)) = T::registers().read(0) { | ||
| 688 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 689 | Some(Ok(Envelope { ts, frame })) | ||
| 690 | } else if let Some((frame, ts)) = T::registers().read(1) { | ||
| 691 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 692 | Some(Ok(Envelope { ts, frame })) | ||
| 693 | } else if let Some(err) = T::registers().curr_error() { | ||
| 694 | // TODO: this is probably wrong | ||
| 695 | Some(Err(err)) | ||
| 696 | } else { | ||
| 697 | None | ||
| 698 | } | ||
| 699 | } | ||
| 700 | |||
| 701 | //async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> { | ||
| 702 | fn try_read_fd<T: Instance>(&self) -> Option<Result<FdEnvelope, BusError>> { | ||
| 703 | if let Some((frame, ts)) = T::registers().read(0) { | ||
| 704 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 705 | Some(Ok(FdEnvelope { ts, frame })) | ||
| 706 | } else if let Some((frame, ts)) = T::registers().read(1) { | ||
| 707 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 708 | Some(Ok(FdEnvelope { ts, frame })) | ||
| 709 | } else if let Some(err) = T::registers().curr_error() { | ||
| 710 | // TODO: this is probably wrong | ||
| 711 | Some(Err(err)) | ||
| 712 | } else { | ||
| 713 | None | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 687 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { | 717 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { |
| 688 | if let Some((msg, ts)) = T::registers().read(0) { | 718 | if let Some((msg, ts)) = T::registers().read(0) { |
| 689 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | 719 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); |
| @@ -711,12 +741,18 @@ impl RxMode { | |||
| 711 | .await | 741 | .await |
| 712 | } | 742 | } |
| 713 | 743 | ||
| 714 | async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { | 744 | async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> { |
| 715 | self.read_async::<T, _>().await | 745 | match self.read_async::<T, _>().await { |
| 746 | Ok((frame, ts)) => Ok(Envelope { ts, frame }), | ||
| 747 | Err(e) => Err(e), | ||
| 748 | } | ||
| 716 | } | 749 | } |
| 717 | 750 | ||
| 718 | async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { | 751 | async fn read_fd<T: Instance>(&self) -> Result<FdEnvelope, BusError> { |
| 719 | self.read_async::<T, _>().await | 752 | match self.read_async::<T, _>().await { |
| 753 | Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }), | ||
| 754 | Err(e) => Err(e), | ||
| 755 | } | ||
| 720 | } | 756 | } |
| 721 | } | 757 | } |
| 722 | 758 | ||
| @@ -761,7 +797,7 @@ impl TxMode { | |||
| 761 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames | 797 | /// frame is dropped from the mailbox, it is returned. If no lower-priority frames |
| 762 | /// can be replaced, this call asynchronously waits for a frame to be successfully | 798 | /// can be replaced, this call asynchronously waits for a frame to be successfully |
| 763 | /// transmitted, then tries again. | 799 | /// transmitted, then tries again. |
| 764 | async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { | 800 | async fn write<T: Instance>(&self, frame: &Frame) -> Option<Frame> { |
| 765 | self.write_generic::<T, _>(frame).await | 801 | self.write_generic::<T, _>(frame).await |
| 766 | } | 802 | } |
| 767 | 803 | ||
diff --git a/embassy-stm32/src/can/frame.rs b/embassy-stm32/src/can/frame.rs index 14fc32c51..fb032aee2 100644 --- a/embassy-stm32/src/can/frame.rs +++ b/embassy-stm32/src/can/frame.rs | |||
| @@ -136,19 +136,20 @@ impl ClassicData { | |||
| 136 | } | 136 | } |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | /// Frame with up to 8 bytes of data payload as per Classic CAN | 139 | /// Frame with up to 8 bytes of data payload as per Classic(non-FD) CAN |
| 140 | /// For CAN-FD support use FdFrame | ||
| 140 | #[derive(Debug, Copy, Clone)] | 141 | #[derive(Debug, Copy, Clone)] |
| 141 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 142 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 142 | pub struct ClassicFrame { | 143 | pub struct Frame { |
| 143 | can_header: Header, | 144 | can_header: Header, |
| 144 | data: ClassicData, | 145 | data: ClassicData, |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | impl ClassicFrame { | 148 | impl Frame { |
| 148 | /// Create a new CAN classic Frame | 149 | /// Create a new CAN classic Frame |
| 149 | pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> { | 150 | pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> { |
| 150 | let data = ClassicData::new(raw_data)?; | 151 | let data = ClassicData::new(raw_data)?; |
| 151 | Ok(ClassicFrame { can_header, data: data }) | 152 | Ok(Frame { can_header, data: data }) |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | /// Creates a new data frame. | 155 | /// Creates a new data frame. |
| @@ -206,9 +207,9 @@ impl ClassicFrame { | |||
| 206 | } | 207 | } |
| 207 | } | 208 | } |
| 208 | 209 | ||
| 209 | impl embedded_can::Frame for ClassicFrame { | 210 | impl embedded_can::Frame for Frame { |
| 210 | fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> { | 211 | fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> { |
| 211 | let frameopt = ClassicFrame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data); | 212 | let frameopt = Frame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data); |
| 212 | match frameopt { | 213 | match frameopt { |
| 213 | Ok(frame) => Some(frame), | 214 | Ok(frame) => Some(frame), |
| 214 | Err(_) => None, | 215 | Err(_) => None, |
| @@ -216,7 +217,7 @@ impl embedded_can::Frame for ClassicFrame { | |||
| 216 | } | 217 | } |
| 217 | fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> { | 218 | fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> { |
| 218 | if len <= 8 { | 219 | if len <= 8 { |
| 219 | let frameopt = ClassicFrame::new(Header::new(id.into(), len as u8, true), &[0; 8]); | 220 | let frameopt = Frame::new(Header::new(id.into(), len as u8, true), &[0; 8]); |
| 220 | match frameopt { | 221 | match frameopt { |
| 221 | Ok(frame) => Some(frame), | 222 | Ok(frame) => Some(frame), |
| 222 | Err(_) => None, | 223 | Err(_) => None, |
| @@ -245,7 +246,7 @@ impl embedded_can::Frame for ClassicFrame { | |||
| 245 | } | 246 | } |
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | impl CanHeader for ClassicFrame { | 249 | impl CanHeader for Frame { |
| 249 | fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> { | 250 | fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> { |
| 250 | Self::new(header, data) | 251 | Self::new(header, data) |
| 251 | } | 252 | } |
| @@ -255,10 +256,32 @@ impl CanHeader for ClassicFrame { | |||
| 255 | } | 256 | } |
| 256 | } | 257 | } |
| 257 | 258 | ||
| 259 | /// Contains CAN frame and additional metadata. | ||
| 260 | /// | ||
| 261 | /// Timestamp is available if `time` feature is enabled. | ||
| 262 | /// For CAN-FD support use FdEnvelope | ||
| 263 | #[derive(Debug, Clone)] | ||
| 264 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 265 | pub struct Envelope { | ||
| 266 | /// Reception time. | ||
| 267 | #[cfg(feature = "time")] | ||
| 268 | pub ts: embassy_time::Instant, | ||
| 269 | /// The actual CAN frame. | ||
| 270 | pub frame: Frame, | ||
| 271 | } | ||
| 272 | |||
| 273 | impl Envelope { | ||
| 274 | /// Convert into a tuple | ||
| 275 | pub fn parts(self) -> (Frame, embassy_time::Instant) { | ||
| 276 | (self.frame, self.ts) | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 258 | /// Payload of a (FD)CAN data frame. | 280 | /// Payload of a (FD)CAN data frame. |
| 259 | /// | 281 | /// |
| 260 | /// Contains 0 to 64 Bytes of data. | 282 | /// Contains 0 to 64 Bytes of data. |
| 261 | #[derive(Debug, Copy, Clone)] | 283 | #[derive(Debug, Copy, Clone)] |
| 284 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 262 | pub struct FdData { | 285 | pub struct FdData { |
| 263 | pub(crate) bytes: [u8; 64], | 286 | pub(crate) bytes: [u8; 64], |
| 264 | } | 287 | } |
| @@ -308,6 +331,7 @@ impl FdData { | |||
| 308 | 331 | ||
| 309 | /// Frame with up to 8 bytes of data payload as per Fd CAN | 332 | /// Frame with up to 8 bytes of data payload as per Fd CAN |
| 310 | #[derive(Debug, Copy, Clone)] | 333 | #[derive(Debug, Copy, Clone)] |
| 334 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 311 | pub struct FdFrame { | 335 | pub struct FdFrame { |
| 312 | can_header: Header, | 336 | can_header: Header, |
| 313 | data: FdData, | 337 | data: FdData, |
| @@ -410,3 +434,23 @@ impl CanHeader for FdFrame { | |||
| 410 | self.header() | 434 | self.header() |
| 411 | } | 435 | } |
| 412 | } | 436 | } |
| 437 | |||
| 438 | /// Contains CAN FD frame and additional metadata. | ||
| 439 | /// | ||
| 440 | /// Timestamp is available if `time` feature is enabled. | ||
| 441 | #[derive(Debug, Clone)] | ||
| 442 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 443 | pub struct FdEnvelope { | ||
| 444 | /// Reception time. | ||
| 445 | #[cfg(feature = "time")] | ||
| 446 | pub ts: embassy_time::Instant, | ||
| 447 | /// The actual CAN frame. | ||
| 448 | pub frame: FdFrame, | ||
| 449 | } | ||
| 450 | |||
| 451 | impl FdEnvelope { | ||
| 452 | /// Convert into a tuple | ||
| 453 | pub fn parts(self) -> (FdFrame, embassy_time::Instant) { | ||
| 454 | (self.frame, self.ts) | ||
| 455 | } | ||
| 456 | } | ||
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index df5d32f70..4f282f326 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -23,6 +23,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } | |||
| 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 23 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 24 | heapless = { version = "0.8", default-features = false } | 24 | heapless = { version = "0.8", default-features = false } |
| 25 | nb = "1.0.0" | 25 | nb = "1.0.0" |
| 26 | static_cell = "2.0.0" | ||
| 26 | 27 | ||
| 27 | [profile.dev] | 28 | [profile.dev] |
| 28 | opt-level = "s" | 29 | opt-level = "s" |
diff --git a/examples/stm32f1/src/bin/can.rs b/examples/stm32f1/src/bin/can.rs index ac337e8a0..90cb9e46b 100644 --- a/examples/stm32f1/src/bin/can.rs +++ b/examples/stm32f1/src/bin/can.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::can::{ | 6 | use embassy_stm32::can::{ |
| 7 | filter, Can, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, | 7 | filter, Can, Envelope, Fifo, Frame, Id, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, StandardId, |
| 8 | TxInterruptHandler, | 8 | TxInterruptHandler, |
| 9 | }; | 9 | }; |
| 10 | use embassy_stm32::peripherals::CAN; | 10 | use embassy_stm32::peripherals::CAN; |
| 11 | use embassy_stm32::{bind_interrupts, Config}; | 11 | use embassy_stm32::{bind_interrupts, Config}; |
| 12 | use static_cell::StaticCell; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 14 | ||
| 14 | bind_interrupts!(struct Irqs { | 15 | bind_interrupts!(struct Irqs { |
| @@ -21,6 +22,27 @@ bind_interrupts!(struct Irqs { | |||
| 21 | // This example is configured to work with real CAN transceivers on B8/B9. | 22 | // This example is configured to work with real CAN transceivers on B8/B9. |
| 22 | // See other examples for loopback. | 23 | // See other examples for loopback. |
| 23 | 24 | ||
| 25 | fn handle_frame(env: Envelope, read_mode: &str) { | ||
| 26 | match env.frame.id() { | ||
| 27 | Id::Extended(id) => { | ||
| 28 | defmt::println!( | ||
| 29 | "{} Extended Frame id={:x} {:02x}", | ||
| 30 | read_mode, | ||
| 31 | id.as_raw(), | ||
| 32 | env.frame.data() | ||
| 33 | ); | ||
| 34 | } | ||
| 35 | Id::Standard(id) => { | ||
| 36 | defmt::println!( | ||
| 37 | "{} Standard Frame id={:x} {:02x}", | ||
| 38 | read_mode, | ||
| 39 | id.as_raw(), | ||
| 40 | env.frame.data() | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 24 | #[embassy_executor::main] | 46 | #[embassy_executor::main] |
| 25 | async fn main(_spawner: Spawner) { | 47 | async fn main(_spawner: Spawner) { |
| 26 | let p = embassy_stm32::init(Config::default()); | 48 | let p = embassy_stm32::init(Config::default()); |
| @@ -28,6 +50,9 @@ async fn main(_spawner: Spawner) { | |||
| 28 | // Set alternate pin mapping to B8/B9 | 50 | // Set alternate pin mapping to B8/B9 |
| 29 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); | 51 | embassy_stm32::pac::AFIO.mapr().modify(|w| w.set_can1_remap(2)); |
| 30 | 52 | ||
| 53 | static RX_BUF: StaticCell<embassy_stm32::can::RxBuf<10>> = StaticCell::new(); | ||
| 54 | static TX_BUF: StaticCell<embassy_stm32::can::TxBuf<10>> = StaticCell::new(); | ||
| 55 | |||
| 31 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); | 56 | let mut can = Can::new(p.CAN, p.PB8, p.PB9, Irqs); |
| 32 | 57 | ||
| 33 | can.as_mut() | 58 | can.as_mut() |
| @@ -43,21 +68,72 @@ async fn main(_spawner: Spawner) { | |||
| 43 | can.set_bitrate(250_000); | 68 | can.set_bitrate(250_000); |
| 44 | 69 | ||
| 45 | can.enable().await; | 70 | can.enable().await; |
| 46 | |||
| 47 | let mut i: u8 = 0; | 71 | let mut i: u8 = 0; |
| 72 | |||
| 73 | /* | ||
| 74 | // Example for using buffered Tx and Rx without needing to | ||
| 75 | // split first as is done below. | ||
| 76 | let mut can = can.buffered( | ||
| 77 | TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new()), | ||
| 78 | RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 79 | loop { | ||
| 80 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 81 | can.write(&tx_frame).await; | ||
| 82 | |||
| 83 | match can.read().await { | ||
| 84 | Ok((frame, ts)) => { | ||
| 85 | handle_frame(Envelope { ts, frame }, "Buf"); | ||
| 86 | } | ||
| 87 | Err(err) => { | ||
| 88 | defmt::println!("Error {}", err); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | i += 1; | ||
| 92 | } | ||
| 93 | |||
| 94 | */ | ||
| 95 | let (mut tx, mut rx) = can.split(); | ||
| 96 | |||
| 97 | // This example shows using the wait_not_empty API before try read | ||
| 98 | while i < 3 { | ||
| 99 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 100 | tx.write(&tx_frame).await; | ||
| 101 | |||
| 102 | rx.wait_not_empty().await; | ||
| 103 | let env = rx.try_read().unwrap(); | ||
| 104 | handle_frame(env, "Wait"); | ||
| 105 | i += 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | // This example shows using the full async non-buffered API | ||
| 109 | while i < 6 { | ||
| 110 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | ||
| 111 | tx.write(&tx_frame).await; | ||
| 112 | |||
| 113 | match rx.read().await { | ||
| 114 | Ok(env) => { | ||
| 115 | handle_frame(env, "NoBuf"); | ||
| 116 | } | ||
| 117 | Err(err) => { | ||
| 118 | defmt::println!("Error {}", err); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | i += 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | // This example shows using buffered RX and TX. User passes in desired buffer (size) | ||
| 125 | // It's possible this way to have just RX or TX buffered. | ||
| 126 | let mut rx = rx.buffered(RX_BUF.init(embassy_stm32::can::RxBuf::<10>::new())); | ||
| 127 | let mut tx = tx.buffered(TX_BUF.init(embassy_stm32::can::TxBuf::<10>::new())); | ||
| 128 | |||
| 48 | loop { | 129 | loop { |
| 49 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); | 130 | let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i, 0, 1, 2, 3, 4, 5, 6]).unwrap(); |
| 50 | can.write(&tx_frame).await; | 131 | tx.write(&tx_frame).await; |
| 51 | 132 | ||
| 52 | match can.read().await { | 133 | match rx.read().await { |
| 53 | Ok(env) => match env.frame.id() { | 134 | Ok(envelope) => { |
| 54 | Id::Extended(id) => { | 135 | handle_frame(envelope, "Buf"); |
| 55 | defmt::println!("Extended Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | 136 | } |
| 56 | } | ||
| 57 | Id::Standard(id) => { | ||
| 58 | defmt::println!("Standard Frame id={:x} {:02x}", id.as_raw(), env.frame.data()); | ||
| 59 | } | ||
| 60 | }, | ||
| 61 | Err(err) => { | 137 | Err(err) => { |
| 62 | defmt::println!("Error {}", err); | 138 | defmt::println!("Error {}", err); |
| 63 | } | 139 | } |
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 4373a89a8..2ed632a93 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { | |||
| 36 | } | 36 | } |
| 37 | let peripherals = embassy_stm32::init(config); | 37 | let peripherals = embassy_stm32::init(config); |
| 38 | 38 | ||
| 39 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 39 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 40 | 40 | ||
| 41 | can.set_extended_filter( | 41 | can.set_extended_filter( |
| 42 | can::filter::ExtendedFilterSlot::_0, | 42 | can::filter::ExtendedFilterSlot::_0, |
| @@ -56,21 +56,22 @@ async fn main(_spawner: Spawner) { | |||
| 56 | info!("Configured"); | 56 | info!("Configured"); |
| 57 | 57 | ||
| 58 | let mut can = can.start(match use_fd { | 58 | let mut can = can.start(match use_fd { |
| 59 | true => can::FdcanOperatingMode::InternalLoopbackMode, | 59 | true => can::OperatingMode::InternalLoopbackMode, |
| 60 | false => can::FdcanOperatingMode::NormalOperationMode, | 60 | false => can::OperatingMode::NormalOperationMode, |
| 61 | }); | 61 | }); |
| 62 | 62 | ||
| 63 | let mut i = 0; | 63 | let mut i = 0; |
| 64 | let mut last_read_ts = embassy_time::Instant::now(); | 64 | let mut last_read_ts = embassy_time::Instant::now(); |
| 65 | 65 | ||
| 66 | loop { | 66 | loop { |
| 67 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 67 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 68 | info!("Writing frame"); | 68 | info!("Writing frame"); |
| 69 | 69 | ||
| 70 | _ = can.write(&frame).await; | 70 | _ = can.write(&frame).await; |
| 71 | 71 | ||
| 72 | match can.read().await { | 72 | match can.read().await { |
| 73 | Ok((rx_frame, ts)) => { | 73 | Ok(envelope) => { |
| 74 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 74 | let delta = (ts - last_read_ts).as_millis(); | 75 | let delta = (ts - last_read_ts).as_millis(); |
| 75 | last_read_ts = ts; | 76 | last_read_ts = ts; |
| 76 | info!( | 77 | info!( |
| @@ -105,7 +106,8 @@ async fn main(_spawner: Spawner) { | |||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | match can.read_fd().await { | 108 | match can.read_fd().await { |
| 108 | Ok((rx_frame, ts)) => { | 109 | Ok(envelope) => { |
| 110 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 109 | let delta = (ts - last_read_ts).as_millis(); | 111 | let delta = (ts - last_read_ts).as_millis(); |
| 110 | last_read_ts = ts; | 112 | last_read_ts = ts; |
| 111 | info!( | 113 | info!( |
| @@ -129,12 +131,13 @@ async fn main(_spawner: Spawner) { | |||
| 129 | let (mut tx, mut rx) = can.split(); | 131 | let (mut tx, mut rx) = can.split(); |
| 130 | // With split | 132 | // With split |
| 131 | loop { | 133 | loop { |
| 132 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 134 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 133 | info!("Writing frame"); | 135 | info!("Writing frame"); |
| 134 | _ = tx.write(&frame).await; | 136 | _ = tx.write(&frame).await; |
| 135 | 137 | ||
| 136 | match rx.read().await { | 138 | match rx.read().await { |
| 137 | Ok((rx_frame, ts)) => { | 139 | Ok(envelope) => { |
| 140 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 138 | let delta = (ts - last_read_ts).as_millis(); | 141 | let delta = (ts - last_read_ts).as_millis(); |
| 139 | last_read_ts = ts; | 142 | last_read_ts = ts; |
| 140 | info!( | 143 | info!( |
| @@ -156,7 +159,7 @@ async fn main(_spawner: Spawner) { | |||
| 156 | } | 159 | } |
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | let can = can::Fdcan::join(tx, rx); | 162 | let can = can::Can::join(tx, rx); |
| 160 | 163 | ||
| 161 | info!("\n\n\nBuffered\n"); | 164 | info!("\n\n\nBuffered\n"); |
| 162 | if use_fd { | 165 | if use_fd { |
| @@ -173,7 +176,8 @@ async fn main(_spawner: Spawner) { | |||
| 173 | _ = can.write(frame).await; | 176 | _ = can.write(frame).await; |
| 174 | 177 | ||
| 175 | match can.read().await { | 178 | match can.read().await { |
| 176 | Ok((rx_frame, ts)) => { | 179 | Ok(envelope) => { |
| 180 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 177 | let delta = (ts - last_read_ts).as_millis(); | 181 | let delta = (ts - last_read_ts).as_millis(); |
| 178 | last_read_ts = ts; | 182 | last_read_ts = ts; |
| 179 | info!( | 183 | info!( |
| @@ -198,7 +202,7 @@ async fn main(_spawner: Spawner) { | |||
| 198 | RX_BUF.init(can::RxBuf::<10>::new()), | 202 | RX_BUF.init(can::RxBuf::<10>::new()), |
| 199 | ); | 203 | ); |
| 200 | loop { | 204 | loop { |
| 201 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 205 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 202 | info!("Writing frame"); | 206 | info!("Writing frame"); |
| 203 | 207 | ||
| 204 | // You can use any of these approaches to send. The writer makes it | 208 | // You can use any of these approaches to send. The writer makes it |
| @@ -208,7 +212,8 @@ async fn main(_spawner: Spawner) { | |||
| 208 | can.writer().write(frame).await; | 212 | can.writer().write(frame).await; |
| 209 | 213 | ||
| 210 | match can.read().await { | 214 | match can.read().await { |
| 211 | Ok((rx_frame, ts)) => { | 215 | Ok(envelope) => { |
| 216 | let (ts, rx_frame) = (envelope.ts, envelope.frame); | ||
| 212 | let delta = (ts - last_read_ts).as_millis(); | 217 | let delta = (ts - last_read_ts).as_millis(); |
| 213 | last_read_ts = ts; | 218 | last_read_ts = ts; |
| 214 | info!( | 219 | info!( |
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs index 643df27f9..dd625c90a 100644 --- a/examples/stm32h5/src/bin/can.rs +++ b/examples/stm32h5/src/bin/can.rs | |||
| @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | 24 | ||
| 25 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 26 | 26 | ||
| 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 28 | 28 | ||
| 29 | // 250k bps | 29 | // 250k bps |
| 30 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| @@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) { | |||
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | 38 | let mut last_read_ts = embassy_time::Instant::now(); |
| 39 | 39 | ||
| 40 | loop { | 40 | loop { |
| 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 41 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 42 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 43 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 44 | 44 | ||
| 45 | match can.read().await { | 45 | match can.read().await { |
| 46 | Ok((rx_frame, ts)) => { | 46 | Ok(envelope) => { |
| 47 | let (rx_frame, ts) = envelope.parts(); | ||
| 47 | let delta = (ts - last_read_ts).as_millis(); | 48 | let delta = (ts - last_read_ts).as_millis(); |
| 48 | last_read_ts = ts; | 49 | last_read_ts = ts; |
| 49 | info!( | 50 | info!( |
| @@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) { | |||
| 69 | let (mut tx, mut rx) = can.split(); | 70 | let (mut tx, mut rx) = can.split(); |
| 70 | // With split | 71 | // With split |
| 71 | loop { | 72 | loop { |
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 73 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 73 | info!("Writing frame"); | 74 | info!("Writing frame"); |
| 74 | _ = tx.write(&frame).await; | 75 | _ = tx.write(&frame).await; |
| 75 | 76 | ||
| 76 | match rx.read().await { | 77 | match rx.read().await { |
| 77 | Ok((rx_frame, ts)) => { | 78 | Ok(envelope) => { |
| 79 | let (rx_frame, ts) = envelope.parts(); | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | 80 | let delta = (ts - last_read_ts).as_millis(); |
| 79 | last_read_ts = ts; | 81 | last_read_ts = ts; |
| 80 | info!( | 82 | info!( |
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs index 13a6a5051..22cb27481 100644 --- a/examples/stm32h7/src/bin/can.rs +++ b/examples/stm32h7/src/bin/can.rs | |||
| @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | 24 | ||
| 25 | let peripherals = embassy_stm32::init(config); | 25 | let peripherals = embassy_stm32::init(config); |
| 26 | 26 | ||
| 27 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); | 27 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); |
| 28 | 28 | ||
| 29 | // 250k bps | 29 | // 250k bps |
| 30 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| @@ -38,12 +38,13 @@ async fn main(_spawner: Spawner) { | |||
| 38 | let mut last_read_ts = embassy_time::Instant::now(); | 38 | let mut last_read_ts = embassy_time::Instant::now(); |
| 39 | 39 | ||
| 40 | loop { | 40 | loop { |
| 41 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 41 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 42 | info!("Writing frame"); | 42 | info!("Writing frame"); |
| 43 | _ = can.write(&frame).await; | 43 | _ = can.write(&frame).await; |
| 44 | 44 | ||
| 45 | match can.read().await { | 45 | match can.read().await { |
| 46 | Ok((rx_frame, ts)) => { | 46 | Ok(envelope) => { |
| 47 | let (rx_frame, ts) = envelope.parts(); | ||
| 47 | let delta = (ts - last_read_ts).as_millis(); | 48 | let delta = (ts - last_read_ts).as_millis(); |
| 48 | last_read_ts = ts; | 49 | last_read_ts = ts; |
| 49 | info!( | 50 | info!( |
| @@ -69,12 +70,13 @@ async fn main(_spawner: Spawner) { | |||
| 69 | let (mut tx, mut rx) = can.split(); | 70 | let (mut tx, mut rx) = can.split(); |
| 70 | // With split | 71 | // With split |
| 71 | loop { | 72 | loop { |
| 72 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 73 | let frame = can::frame::Frame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 73 | info!("Writing frame"); | 74 | info!("Writing frame"); |
| 74 | _ = tx.write(&frame).await; | 75 | _ = tx.write(&frame).await; |
| 75 | 76 | ||
| 76 | match rx.read().await { | 77 | match rx.read().await { |
| 77 | Ok((rx_frame, ts)) => { | 78 | Ok(envelope) => { |
| 79 | let (rx_frame, ts) = envelope.parts(); | ||
| 78 | let delta = (ts - last_read_ts).as_millis(); | 80 | let delta = (ts - last_read_ts).as_millis(); |
| 79 | last_read_ts = ts; | 81 | last_read_ts = ts; |
| 80 | info!( | 82 | info!( |
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs index c7373e294..bddfa7684 100644 --- a/tests/stm32/src/bin/fdcan.rs +++ b/tests/stm32/src/bin/fdcan.rs | |||
| @@ -79,8 +79,8 @@ async fn main(_spawner: Spawner) { | |||
| 79 | let options = options(); | 79 | let options = options(); |
| 80 | let peripherals = embassy_stm32::init(options.config); | 80 | let peripherals = embassy_stm32::init(options.config); |
| 81 | 81 | ||
| 82 | let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1); | 82 | let mut can = can::CanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1); |
| 83 | let mut can2 = can::FdcanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2); | 83 | let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2); |
| 84 | 84 | ||
| 85 | // 250k bps | 85 | // 250k bps |
| 86 | can.set_bitrate(250_000); | 86 | can.set_bitrate(250_000); |
| @@ -102,13 +102,13 @@ async fn main(_spawner: Spawner) { | |||
| 102 | 102 | ||
| 103 | let mut i: u8 = 0; | 103 | let mut i: u8 = 0; |
| 104 | loop { | 104 | loop { |
| 105 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | 105 | let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); |
| 106 | 106 | ||
| 107 | info!("Transmitting frame..."); | 107 | info!("Transmitting frame..."); |
| 108 | let tx_ts = Instant::now(); | 108 | let tx_ts = Instant::now(); |
| 109 | can.write(&tx_frame).await; | 109 | can.write(&tx_frame).await; |
| 110 | 110 | ||
| 111 | let (frame, timestamp) = can.read().await.unwrap(); | 111 | let (frame, timestamp) = can.read().await.unwrap().parts(); |
| 112 | info!("Frame received!"); | 112 | info!("Frame received!"); |
| 113 | 113 | ||
| 114 | // Check data. | 114 | // Check data. |
| @@ -139,13 +139,13 @@ async fn main(_spawner: Spawner) { | |||
| 139 | 139 | ||
| 140 | let mut i: u8 = 0; | 140 | let mut i: u8 = 0; |
| 141 | loop { | 141 | loop { |
| 142 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | 142 | let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); |
| 143 | 143 | ||
| 144 | info!("Transmitting frame..."); | 144 | info!("Transmitting frame..."); |
| 145 | let tx_ts = Instant::now(); | 145 | let tx_ts = Instant::now(); |
| 146 | can2.write(&tx_frame).await; | 146 | can2.write(&tx_frame).await; |
| 147 | 147 | ||
| 148 | let (frame, timestamp) = can2.read().await.unwrap(); | 148 | let (frame, timestamp) = can2.read().await.unwrap().parts(); |
| 149 | info!("Frame received!"); | 149 | info!("Frame received!"); |
| 150 | 150 | ||
| 151 | //print_regs().await; | 151 | //print_regs().await; |
| @@ -182,20 +182,20 @@ async fn main(_spawner: Spawner) { | |||
| 182 | // in each FIFO so make sure we write enough to fill them both up before reading. | 182 | // in each FIFO so make sure we write enough to fill them both up before reading. |
| 183 | for i in 0..3 { | 183 | for i in 0..3 { |
| 184 | // Try filling up the RX FIFO0 buffers with standard packets | 184 | // Try filling up the RX FIFO0 buffers with standard packets |
| 185 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | 185 | let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); |
| 186 | info!("Transmitting frame {}", i); | 186 | info!("Transmitting frame {}", i); |
| 187 | can.write(&tx_frame).await; | 187 | can.write(&tx_frame).await; |
| 188 | } | 188 | } |
| 189 | for i in 3..max_buffered { | 189 | for i in 3..max_buffered { |
| 190 | // Try filling up the RX FIFO0 buffers with extended packets | 190 | // Try filling up the RX FIFO0 buffers with extended packets |
| 191 | let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap(); | 191 | let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap(); |
| 192 | info!("Transmitting frame {}", i); | 192 | info!("Transmitting frame {}", i); |
| 193 | can.write(&tx_frame).await; | 193 | can.write(&tx_frame).await; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | // Try and receive all 6 packets | 196 | // Try and receive all 6 packets |
| 197 | for i in 0..max_buffered { | 197 | for i in 0..max_buffered { |
| 198 | let (frame, _ts) = can.read().await.unwrap(); | 198 | let (frame, _ts) = can.read().await.unwrap().parts(); |
| 199 | match frame.id() { | 199 | match frame.id() { |
| 200 | embedded_can::Id::Extended(id) => { | 200 | embedded_can::Id::Extended(id) => { |
| 201 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | 201 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); |
| @@ -210,20 +210,20 @@ async fn main(_spawner: Spawner) { | |||
| 210 | let (mut tx, mut rx) = can.split(); | 210 | let (mut tx, mut rx) = can.split(); |
| 211 | for i in 0..3 { | 211 | for i in 0..3 { |
| 212 | // Try filling up the RX FIFO0 buffers with standard packets | 212 | // Try filling up the RX FIFO0 buffers with standard packets |
| 213 | let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); | 213 | let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap(); |
| 214 | info!("Transmitting frame {}", i); | 214 | info!("Transmitting frame {}", i); |
| 215 | tx.write(&tx_frame).await; | 215 | tx.write(&tx_frame).await; |
| 216 | } | 216 | } |
| 217 | for i in 3..max_buffered { | 217 | for i in 3..max_buffered { |
| 218 | // Try filling up the RX FIFO0 buffers with extended packets | 218 | // Try filling up the RX FIFO0 buffers with extended packets |
| 219 | let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap(); | 219 | let tx_frame = can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap(); |
| 220 | info!("Transmitting frame {}", i); | 220 | info!("Transmitting frame {}", i); |
| 221 | tx.write(&tx_frame).await; | 221 | tx.write(&tx_frame).await; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | // Try and receive all 6 packets | 224 | // Try and receive all 6 packets |
| 225 | for i in 0..max_buffered { | 225 | for i in 0..max_buffered { |
| 226 | let (frame, _ts) = rx.read().await.unwrap(); | 226 | let (frame, _ts) = rx.read().await.unwrap().parts(); |
| 227 | match frame.id() { | 227 | match frame.id() { |
| 228 | embedded_can::Id::Extended(id) => { | 228 | embedded_can::Id::Extended(id) => { |
| 229 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); | 229 | info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i); |
