aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/can/bx/mod.rs5
-rw-r--r--embassy-stm32/src/can/bxcan.rs27
-rw-r--r--embassy-stm32/src/can/common.rs23
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs12
-rw-r--r--embassy-stm32/src/can/fdcan.rs140
-rw-r--r--embassy-stm32/src/can/frame.rs60
-rw-r--r--examples/stm32f1/Cargo.toml1
-rw-r--r--examples/stm32f1/src/bin/can.rs102
-rw-r--r--examples/stm32g4/src/bin/can.rs29
-rw-r--r--examples/stm32h5/src/bin/can.rs12
-rw-r--r--examples/stm32h7/src/bin/can.rs12
-rw-r--r--tests/stm32/src/bin/fdcan.rs24
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
41pub type Data = crate::can::frame::ClassicData; 41pub type Data = crate::can::frame::ClassicData;
42 42
43/// CAN Frame
44pub type Frame = crate::can::frame::ClassicFrame;
45
46use crate::can::_version::Envelope; 43use crate::can::_version::Envelope;
47use crate::can::bx::filter::MasterFilters; 44use crate::can::bx::filter::MasterFilters;
48use crate::can::enums::BusError; 45use crate::can::enums::BusError;
46/// CAN Frame
47pub use crate::can::frame::Frame;
49use crate::pac::can::vals::Lec; 48use 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};
19pub mod enums; 19pub mod enums;
20pub mod frame; 20pub mod frame;
21pub mod util; 21pub mod util;
22pub use frame::Envelope;
22 23
23mod common; 24mod common;
24pub use self::common::{BufferedCanReceiver, BufferedCanSender, Timestamp}; 25pub 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))]
31pub 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.
40pub struct TxInterruptHandler<T: Instance> { 28pub 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
485pub type RxBuf<const BUF_SIZE: usize> = 473pub 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.
489pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> { 476pub 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};
3use crate::can::_version::enums::*; 3use crate::can::_version::enums::*;
4use crate::can::_version::frame::*; 4use crate::can::_version::frame::*;
5 5
6/// Timestamp for incoming packets. Use Embassy time when enabled.
7#[cfg(feature = "time")]
8pub type Timestamp = embassy_time::Instant;
9
10/// Timestamp for incoming packets.
11#[cfg(not(feature = "time"))]
12pub type Timestamp = u16;
13
14pub(crate) struct ClassicBufferedRxInner { 6pub(crate) struct ClassicBufferedRxInner {
15 pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, 7 pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>,
16} 8}
17pub(crate) struct ClassicBufferedTxInner { 9pub(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
23pub(crate) struct FdBufferedRxInner { 15pub(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)]
34pub struct BufferedCanSender { 26pub 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
39impl BufferedCanSender { 31impl 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.
60pub type BufferedCanReceiver = 52pub 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
113pub enum FdcanOperatingMode { 113pub 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
151pub struct FdcanConfigurator<'d, T: Instance> { 151pub 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
172impl<'d, T: Instance> FdcanConfigurator<'d, T> { 172impl<'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
307pub struct Fdcan<'d, T: Instance> { 307pub 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
314impl<'d, T: Instance> Fdcan<'d, T> { 314impl<'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
405pub type RxBuf<const BUF_SIZE: usize> = 405pub 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
409pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; 408pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
410 409
411/// Buffered FDCAN Instance 410/// Buffered FDCAN Instance
412pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { 411pub 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
492pub type RxFdBuf<const BUF_SIZE: usize> = 491pub 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
496pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; 494pub 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
499pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { 497pub 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.
535pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>; 533pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>;
536 534
537impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> 535impl<'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
609pub struct FdcanRx<'d, T: Instance> { 607pub 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
616pub struct FdcanTx<'d, T: Instance> { 614pub 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
622impl<'c, 'd, T: Instance> FdcanTx<'d, T> { 620impl<'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
640impl<'c, 'd, T: Instance> FdcanRx<'d, T> { 638impl<'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))]
142pub struct ClassicFrame { 143pub struct Frame {
143 can_header: Header, 144 can_header: Header,
144 data: ClassicData, 145 data: ClassicData,
145} 146}
146 147
147impl ClassicFrame { 148impl 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
209impl embedded_can::Frame for ClassicFrame { 210impl 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
248impl CanHeader for ClassicFrame { 249impl 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))]
265pub 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
273impl 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))]
262pub struct FdData { 285pub 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))]
311pub struct FdFrame { 335pub 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))]
443pub 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
451impl 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"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 23futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
25nb = "1.0.0" 25nb = "1.0.0"
26static_cell = "2.0.0"
26 27
27[profile.dev] 28[profile.dev]
28opt-level = "s" 29opt-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 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::can::{ 6use 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};
10use embassy_stm32::peripherals::CAN; 10use embassy_stm32::peripherals::CAN;
11use embassy_stm32::{bind_interrupts, Config}; 11use embassy_stm32::{bind_interrupts, Config};
12use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
13 14
14bind_interrupts!(struct Irqs { 15bind_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
25fn 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]
25async fn main(_spawner: Spawner) { 47async 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);