aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-03-28 00:10:11 +0000
committerGitHub <[email protected]>2024-03-28 00:10:11 +0000
commit393de9e19f12528a11ba98658c29d4fb43f75fa0 (patch)
treee6e144041c6d973066b8fffd979650eb443ef7a3
parent8f6c07c7750647edf9acea76cf6fe0ca1bc4da87 (diff)
parent25618cd93d5209d864fa250b2077a59532e0bedf (diff)
Merge pull request #2744 from cschuhen/feature/bxcan_use_fdcan_api
Synchronise the feature sets and API between BXCAN and FDCAN.
-rw-r--r--embassy-stm32/src/can/bx/mod.rs815
-rw-r--r--embassy-stm32/src/can/bxcan.rs519
-rw-r--r--embassy-stm32/src/can/common.rs52
-rw-r--r--embassy-stm32/src/can/enums.rs10
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs12
-rw-r--r--embassy-stm32/src/can/fdcan.rs207
-rw-r--r--embassy-stm32/src/can/frame.rs67
-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/can.rs50
-rw-r--r--tests/stm32/src/bin/can_common.rs112
-rw-r--r--tests/stm32/src/bin/fdcan.rs199
15 files changed, 1305 insertions, 894 deletions
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs
index 121da1bb2..cd82148ba 100644
--- a/embassy-stm32/src/can/bx/mod.rs
+++ b/embassy-stm32/src/can/bx/mod.rs
@@ -40,10 +40,37 @@ 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
43use crate::can::_version::Envelope;
44use crate::can::bx::filter::MasterFilters;
45use crate::can::enums::BusError;
43/// CAN Frame 46/// CAN Frame
44pub type Frame = crate::can::frame::ClassicFrame; 47pub use crate::can::frame::Frame;
48use crate::pac::can::vals::Lec;
45 49
46use crate::can::bx::filter::MasterFilters; 50#[derive(Debug, Copy, Clone, Eq, PartialEq)]
51pub(crate) enum RxFifo {
52 Fifo0,
53 Fifo1,
54}
55
56trait IntoBusError {
57 fn into_bus_err(self) -> Option<BusError>;
58}
59
60impl IntoBusError for Lec {
61 fn into_bus_err(self) -> Option<BusError> {
62 match self {
63 Lec::STUFF => Some(BusError::Stuff),
64 Lec::FORM => Some(BusError::Form),
65 Lec::ACK => Some(BusError::Acknowledge),
66 Lec::BITRECESSIVE => Some(BusError::BitRecessive),
67 Lec::BITDOMINANT => Some(BusError::BitDominant),
68 Lec::CRC => Some(BusError::Crc),
69 Lec::CUSTOM => Some(BusError::Software),
70 _ => None,
71 }
72 }
73}
47 74
48/// A bxCAN peripheral instance. 75/// A bxCAN peripheral instance.
49/// 76///
@@ -233,230 +260,37 @@ impl PartialOrd for IdReg {
233 } 260 }
234} 261}
235 262
236/// Configuration proxy returned by [`Can::modify_config`]. 263pub(crate) struct Registers {
237#[must_use = "`CanConfig` leaves the peripheral in uninitialized state, call `CanConfig::enable` or explicitly drop the value"] 264 pub canregs: crate::pac::can::Can,
238pub struct CanConfig<'a, I: Instance> {
239 can: &'a mut Can<I>,
240} 265}
241 266
242impl<I: Instance> CanConfig<'_, I> { 267impl Registers {
243 /// Configures the bit timings. 268 fn enter_init_mode(&mut self) {
244 /// 269 self.canregs.mcr().modify(|reg| {
245 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter 270 reg.set_sleep(false);
246 /// parameters as follows: 271 reg.set_inrq(true);
247 ///
248 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
249 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
250 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
251 /// - *SJW*: Should normally be left at the default value of 1.
252 ///
253 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
254 /// parameter to this method.
255 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
256 self.can.set_bit_timing(bt);
257 self
258 }
259
260 /// Enables or disables loopback mode: Internally connects the TX and RX
261 /// signals together.
262 pub fn set_loopback(self, enabled: bool) -> Self {
263 self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
264 self
265 }
266
267 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
268 pub fn set_silent(self, enabled: bool) -> Self {
269 let mode = match enabled {
270 false => stm32_metapac::can::vals::Silm::NORMAL,
271 true => stm32_metapac::can::vals::Silm::SILENT,
272 };
273 self.can.canregs.btr().modify(|reg| reg.set_silm(mode));
274 self
275 }
276
277 /// Enables or disables automatic retransmission of messages.
278 ///
279 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
280 /// until it can be sent. Otherwise, it will try only once to send each frame.
281 ///
282 /// Automatic retransmission is enabled by default.
283 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
284 self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled));
285 self
286 }
287
288 /// Leaves initialization mode and enables the peripheral.
289 ///
290 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
291 /// on the bus.
292 ///
293 /// If you want to finish configuration without enabling the peripheral, you can call
294 /// [`CanConfig::leave_disabled`] or [`drop`] the [`CanConfig`] instead.
295 pub fn enable(mut self) {
296 self.leave_init_mode();
297
298 match nb::block!(self.can.enable_non_blocking()) {
299 Ok(()) => {}
300 Err(void) => match void {},
301 }
302
303 // Don't run the destructor.
304 mem::forget(self);
305 }
306
307 /// Leaves initialization mode, but keeps the peripheral in sleep mode.
308 ///
309 /// Before the [`Can`] instance can be used, you have to enable it by calling
310 /// [`Can::enable_non_blocking`].
311 pub fn leave_disabled(mut self) {
312 self.leave_init_mode();
313 }
314
315 /// Leaves initialization mode, enters sleep mode.
316 fn leave_init_mode(&mut self) {
317 self.can.canregs.mcr().modify(|reg| {
318 reg.set_sleep(true);
319 reg.set_inrq(false);
320 }); 272 });
321 loop { 273 loop {
322 let msr = self.can.canregs.msr().read(); 274 let msr = self.canregs.msr().read();
323 if msr.slak() && !msr.inak() { 275 if !msr.slak() && msr.inak() {
324 break; 276 break;
325 } 277 }
326 } 278 }
327 } 279 }
328}
329
330impl<I: Instance> Drop for CanConfig<'_, I> {
331 #[inline]
332 fn drop(&mut self) {
333 self.leave_init_mode();
334 }
335}
336
337/// Builder returned by [`Can::builder`].
338#[must_use = "`CanBuilder` leaves the peripheral in uninitialized state, call `CanBuilder::enable` or `CanBuilder::leave_disabled`"]
339pub struct CanBuilder<I: Instance> {
340 can: Can<I>,
341}
342
343impl<I: Instance> CanBuilder<I> {
344 /// Configures the bit timings.
345 ///
346 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
347 /// parameters as follows:
348 ///
349 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
350 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
351 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
352 /// - *SJW*: Should normally be left at the default value of 1.
353 ///
354 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
355 /// parameter to this method.
356 pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self {
357 self.can.set_bit_timing(bt);
358 self
359 }
360 /// Enables or disables loopback mode: Internally connects the TX and RX
361 /// signals together.
362 pub fn set_loopback(self, enabled: bool) -> Self {
363 self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
364 self
365 }
366
367 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
368 pub fn set_silent(self, enabled: bool) -> Self {
369 let mode = match enabled {
370 false => stm32_metapac::can::vals::Silm::NORMAL,
371 true => stm32_metapac::can::vals::Silm::SILENT,
372 };
373 self.can.canregs.btr().modify(|reg| reg.set_silm(mode));
374 self
375 }
376
377 /// Enables or disables automatic retransmission of messages.
378 ///
379 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
380 /// until it can be sent. Otherwise, it will try only once to send each frame.
381 ///
382 /// Automatic retransmission is enabled by default.
383 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
384 self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled));
385 self
386 }
387
388 /// Leaves initialization mode and enables the peripheral.
389 ///
390 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
391 /// on the bus.
392 ///
393 /// If you want to finish configuration without enabling the peripheral, you can call
394 /// [`CanBuilder::leave_disabled`] instead.
395 pub fn enable(mut self) -> Can<I> {
396 self.leave_init_mode();
397
398 match nb::block!(self.can.enable_non_blocking()) {
399 Ok(()) => self.can,
400 Err(void) => match void {},
401 }
402 }
403 280
404 /// Returns the [`Can`] interface without enabling it. 281 // Leaves initialization mode, enters sleep mode.
405 ///
406 /// This leaves initialization mode, but keeps the peripheral in sleep mode instead of enabling
407 /// it.
408 ///
409 /// Before the [`Can`] instance can be used, you have to enable it by calling
410 /// [`Can::enable_non_blocking`].
411 pub fn leave_disabled(mut self) -> Can<I> {
412 self.leave_init_mode();
413 self.can
414 }
415
416 /// Leaves initialization mode, enters sleep mode.
417 fn leave_init_mode(&mut self) { 282 fn leave_init_mode(&mut self) {
418 self.can.canregs.mcr().modify(|reg| { 283 self.canregs.mcr().modify(|reg| {
419 reg.set_sleep(true); 284 reg.set_sleep(true);
420 reg.set_inrq(false); 285 reg.set_inrq(false);
421 }); 286 });
422 loop { 287 loop {
423 let msr = self.can.canregs.msr().read(); 288 let msr = self.canregs.msr().read();
424 if msr.slak() && !msr.inak() { 289 if msr.slak() && !msr.inak() {
425 break; 290 break;
426 } 291 }
427 } 292 }
428 } 293 }
429}
430
431/// Interface to a bxCAN peripheral.
432pub struct Can<I: Instance> {
433 instance: I,
434 canregs: crate::pac::can::Can,
435}
436
437impl<I> Can<I>
438where
439 I: Instance,
440{
441 /// Creates a [`CanBuilder`] for constructing a CAN interface.
442 pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
443 let can_builder = CanBuilder {
444 can: Can { instance, canregs },
445 };
446
447 canregs.mcr().modify(|reg| {
448 reg.set_sleep(false);
449 reg.set_inrq(true);
450 });
451 loop {
452 let msr = canregs.msr().read();
453 if !msr.slak() && msr.inak() {
454 break;
455 }
456 }
457
458 can_builder
459 }
460 294
461 fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) { 295 fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
462 let prescaler = u16::from(bt.prescaler) & 0x1FF; 296 let prescaler = u16::from(bt.prescaler) & 0x1FF;
@@ -471,38 +305,29 @@ where
471 }); 305 });
472 } 306 }
473 307
474 /// Returns a reference to the peripheral instance. 308 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
475 /// 309 pub fn set_silent(&self, enabled: bool) {
476 /// This allows accessing HAL-specific data stored in the instance type. 310 let mode = match enabled {
477 pub fn instance(&mut self) -> &mut I { 311 false => stm32_metapac::can::vals::Silm::NORMAL,
478 &mut self.instance 312 true => stm32_metapac::can::vals::Silm::SILENT,
313 };
314 self.canregs.btr().modify(|reg| reg.set_silm(mode));
479 } 315 }
480 316
481 /// Disables the CAN interface and returns back the raw peripheral it was created from. 317 /// Enables or disables automatic retransmission of messages.
482 /// 318 ///
483 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to 319 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
484 /// enter sleep mode. 320 /// until it can be sent. Otherwise, it will try only once to send each frame.
485 pub fn free(self) -> I {
486 self.canregs.mcr().write(|reg| reg.set_reset(true));
487 self.instance
488 }
489
490 /// Configure bit timings and silent/loop-back mode.
491 /// 321 ///
492 /// Calling this method will enter initialization mode. 322 /// Automatic retransmission is enabled by default.
493 pub fn modify_config(&mut self) -> CanConfig<'_, I> { 323 pub fn set_automatic_retransmit(&self, enabled: bool) {
494 self.canregs.mcr().modify(|reg| { 324 self.canregs.mcr().modify(|reg| reg.set_nart(enabled));
495 reg.set_sleep(false); 325 }
496 reg.set_inrq(true);
497 });
498 loop {
499 let msr = self.canregs.msr().read();
500 if !msr.slak() && msr.inak() {
501 break;
502 }
503 }
504 326
505 CanConfig { can: self } 327 /// Enables or disables loopback mode: Internally connects the TX and RX
328 /// signals together.
329 pub fn set_loopback(&self, enabled: bool) {
330 self.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
506 } 331 }
507 332
508 /// Configures the automatic wake-up feature. 333 /// Configures the automatic wake-up feature.
@@ -512,6 +337,7 @@ where
512 /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and 337 /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and
513 /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming 338 /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
514 /// frame. 339 /// frame.
340 #[allow(dead_code)]
515 pub fn set_automatic_wakeup(&mut self, enabled: bool) { 341 pub fn set_automatic_wakeup(&mut self, enabled: bool) {
516 self.canregs.mcr().modify(|reg| reg.set_awum(enabled)); 342 self.canregs.mcr().modify(|reg| reg.set_awum(enabled));
517 } 343 }
@@ -540,6 +366,7 @@ where
540 /// Puts the peripheral in a sleep mode to save power. 366 /// Puts the peripheral in a sleep mode to save power.
541 /// 367 ///
542 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled. 368 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
369 #[allow(dead_code)]
543 pub fn sleep(&mut self) { 370 pub fn sleep(&mut self) {
544 self.canregs.mcr().modify(|reg| { 371 self.canregs.mcr().modify(|reg| {
545 reg.set_sleep(true); 372 reg.set_sleep(true);
@@ -553,10 +380,19 @@ where
553 } 380 }
554 } 381 }
555 382
383 /// Disables the CAN interface.
384 ///
385 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
386 /// enter sleep mode.
387 pub fn reset(&self) {
388 self.canregs.mcr().write(|reg| reg.set_reset(true));
389 }
390
556 /// Wakes up from sleep mode. 391 /// Wakes up from sleep mode.
557 /// 392 ///
558 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN 393 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
559 /// frame will cause that interrupt. 394 /// frame will cause that interrupt.
395 #[allow(dead_code)]
560 pub fn wakeup(&mut self) { 396 pub fn wakeup(&mut self) {
561 self.canregs.mcr().modify(|reg| { 397 self.canregs.mcr().modify(|reg| {
562 reg.set_sleep(false); 398 reg.set_sleep(false);
@@ -570,113 +406,18 @@ where
570 } 406 }
571 } 407 }
572 408
573 /// Puts a CAN frame in a free transmit mailbox for transmission on the bus. 409 pub fn curr_error(&self) -> Option<BusError> {
574 /// 410 let err = { self.canregs.esr().read() };
575 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]). 411 if err.boff() {
576 /// Transmit order is preserved for frames with identical priority. 412 return Some(BusError::BusOff);
577 /// 413 } else if err.epvf() {
578 /// If all transmit mailboxes are full, and `frame` has a higher priority than the 414 return Some(BusError::BusPassive);
579 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is 415 } else if err.ewgf() {
580 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as 416 return Some(BusError::BusWarning);
581 /// [`TransmitStatus::dequeued_frame`]. 417 } else if let Some(err) = err.lec().into_bus_err() {
582 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> { 418 return Some(err);
583 // Safety: We have a `&mut self` and have unique access to the peripheral.
584 unsafe { Tx::<I>::conjure(self.canregs).transmit(frame) }
585 }
586
587 /// Returns `true` if no frame is pending for transmission.
588 pub fn is_transmitter_idle(&self) -> bool {
589 // Safety: Read-only operation.
590 unsafe { Tx::<I>::conjure(self.canregs).is_idle() }
591 }
592
593 /// Attempts to abort the sending of a frame that is pending in a mailbox.
594 ///
595 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
596 /// aborted, this function has no effect and returns `false`.
597 ///
598 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
599 /// returns `true`.
600 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
601 // Safety: We have a `&mut self` and have unique access to the peripheral.
602 unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) }
603 }
604
605 /// Returns a received frame if available.
606 ///
607 /// This will first check FIFO 0 for a message or error. If none are available, FIFO 1 is
608 /// checked.
609 ///
610 /// Returns `Err` when a frame was lost due to buffer overrun.
611 pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> {
612 // Safety: We have a `&mut self` and have unique access to the peripheral.
613 let mut rx0 = unsafe { Rx0::<I>::conjure(self.canregs) };
614 let mut rx1 = unsafe { Rx1::<I>::conjure(self.canregs) };
615
616 match rx0.receive() {
617 Err(nb::Error::WouldBlock) => rx1.receive(),
618 result => result,
619 }
620 }
621
622 /// Returns a reference to the RX FIFO 0.
623 pub fn rx0(&mut self) -> Rx0<I> {
624 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
625 unsafe { Rx0::conjure(self.canregs) }
626 }
627
628 /// Returns a reference to the RX FIFO 1.
629 pub fn rx1(&mut self) -> Rx1<I> {
630 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
631 unsafe { Rx1::conjure(self.canregs) }
632 }
633
634 pub(crate) fn split_by_ref(&mut self) -> (Tx<I>, Rx0<I>, Rx1<I>) {
635 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
636 let tx = unsafe { Tx::conjure(self.canregs) };
637 let rx0 = unsafe { Rx0::conjure(self.canregs) };
638 let rx1 = unsafe { Rx1::conjure(self.canregs) };
639 (tx, rx0, rx1)
640 }
641
642 /// Consumes this `Can` instance and splits it into transmitting and receiving halves.
643 pub fn split(self) -> (Tx<I>, Rx0<I>, Rx1<I>) {
644 // Safety: `Self` is not `Copy` and is destroyed by moving it into this method.
645 unsafe {
646 (
647 Tx::conjure(self.canregs),
648 Rx0::conjure(self.canregs),
649 Rx1::conjure(self.canregs),
650 )
651 }
652 }
653}
654
655impl<I: FilterOwner> Can<I> {
656 /// Accesses the filter banks owned by this CAN peripheral.
657 ///
658 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
659 /// peripheral instead.
660 pub fn modify_filters(&mut self) -> MasterFilters<'_, I> {
661 unsafe { MasterFilters::new(self.canregs) }
662 }
663}
664
665/// Interface to the CAN transmitter part.
666pub struct Tx<I> {
667 _can: PhantomData<I>,
668 canregs: crate::pac::can::Can,
669}
670
671impl<I> Tx<I>
672where
673 I: Instance,
674{
675 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
676 Self {
677 _can: PhantomData,
678 canregs,
679 } 419 }
420 None
680 } 421 }
681 422
682 /// Puts a CAN frame in a transmit mailbox for transmission on the bus. 423 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
@@ -842,89 +583,387 @@ where
842 reg.set_rqcp(2, true); 583 reg.set_rqcp(2, true);
843 }); 584 });
844 } 585 }
586
587 pub fn receive_frame_available(&self) -> bool {
588 if self.canregs.rfr(0).read().fmp() != 0 {
589 true
590 } else if self.canregs.rfr(1).read().fmp() != 0 {
591 true
592 } else {
593 false
594 }
595 }
596
597 pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
598 // Generate timestamp as early as possible
599 #[cfg(feature = "time")]
600 let ts = embassy_time::Instant::now();
601
602 use crate::pac::can::vals::Ide;
603
604 let fifo_idx = match fifo {
605 crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
606 crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
607 };
608 let rfr = self.canregs.rfr(fifo_idx);
609 let fifo = self.canregs.rx(fifo_idx);
610
611 // If there are no pending messages, there is nothing to do
612 if rfr.read().fmp() == 0 {
613 return None;
614 }
615
616 let rir = fifo.rir().read();
617 let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
618 embedded_can::StandardId::new(rir.stid()).unwrap().into()
619 } else {
620 let stid = (rir.stid() & 0x7FF) as u32;
621 let exid = rir.exid() & 0x3FFFF;
622 let id = (stid << 18) | (exid);
623 embedded_can::ExtendedId::new(id).unwrap().into()
624 };
625 let rdtr = fifo.rdtr().read();
626 let data_len = rdtr.dlc();
627 let rtr = rir.rtr() == stm32_metapac::can::vals::Rtr::REMOTE;
628
629 #[cfg(not(feature = "time"))]
630 let ts = rdtr.time();
631
632 let mut data: [u8; 8] = [0; 8];
633 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
634 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
635
636 let frame = Frame::new(Header::new(id, data_len, rtr), &data).unwrap();
637 let envelope = Envelope { ts, frame };
638
639 rfr.modify(|v| v.set_rfom(true));
640
641 Some(envelope)
642 }
845} 643}
846 644
847/// Interface to receiver FIFO 0. 645/// Configuration proxy returned by [`Can::modify_config`].
848pub struct Rx0<I> { 646#[must_use = "`CanConfig` leaves the peripheral in uninitialized state, call `CanConfig::enable` or explicitly drop the value"]
849 _can: PhantomData<I>, 647pub struct CanConfig<'a, I: Instance> {
648 can: &'a mut Can<I>,
649}
650
651impl<I: Instance> CanConfig<'_, I> {
652 /// Configures the bit timings.
653 ///
654 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
655 /// parameters as follows:
656 ///
657 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
658 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
659 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
660 /// - *SJW*: Should normally be left at the default value of 1.
661 ///
662 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
663 /// parameter to this method.
664 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
665 self.can.registers.set_bit_timing(bt);
666 self
667 }
668
669 /// Enables or disables loopback mode: Internally connects the TX and RX
670 /// signals together.
671 pub fn set_loopback(self, enabled: bool) -> Self {
672 self.can.registers.set_loopback(enabled);
673 self
674 }
675
676 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
677 pub fn set_silent(self, enabled: bool) -> Self {
678 self.can.registers.set_silent(enabled);
679 self
680 }
681
682 /// Enables or disables automatic retransmission of messages.
683 ///
684 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
685 /// until it can be sent. Otherwise, it will try only once to send each frame.
686 ///
687 /// Automatic retransmission is enabled by default.
688 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
689 self.can.registers.set_automatic_retransmit(enabled);
690 self
691 }
692
693 /// Leaves initialization mode and enables the peripheral.
694 ///
695 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
696 /// on the bus.
697 ///
698 /// If you want to finish configuration without enabling the peripheral, you can call
699 /// [`CanConfig::leave_disabled`] or [`drop`] the [`CanConfig`] instead.
700 pub fn enable(self) {
701 self.can.registers.leave_init_mode();
702
703 match nb::block!(self.can.registers.enable_non_blocking()) {
704 Ok(()) => {}
705 Err(void) => match void {},
706 }
707
708 // Don't run the destructor.
709 mem::forget(self);
710 }
711
712 /// Leaves initialization mode, but keeps the peripheral in sleep mode.
713 ///
714 /// Before the [`Can`] instance can be used, you have to enable it by calling
715 /// [`Can::enable_non_blocking`].
716 pub fn leave_disabled(self) {
717 self.can.registers.leave_init_mode();
718 }
719}
720
721impl<I: Instance> Drop for CanConfig<'_, I> {
722 #[inline]
723 fn drop(&mut self) {
724 self.can.registers.leave_init_mode();
725 }
726}
727
728/// Builder returned by [`Can::builder`].
729#[must_use = "`CanBuilder` leaves the peripheral in uninitialized state, call `CanBuilder::enable` or `CanBuilder::leave_disabled`"]
730pub struct CanBuilder<I: Instance> {
731 can: Can<I>,
732}
733
734impl<I: Instance> CanBuilder<I> {
735 /// Configures the bit timings.
736 ///
737 /// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
738 /// parameters as follows:
739 ///
740 /// - *Clock Rate*: The input clock speed to the CAN peripheral (*not* the CPU clock speed).
741 /// This is the clock rate of the peripheral bus the CAN peripheral is attached to (eg. APB1).
742 /// - *Sample Point*: Should normally be left at the default value of 87.5%.
743 /// - *SJW*: Should normally be left at the default value of 1.
744 ///
745 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
746 /// parameter to this method.
747 pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self {
748 self.can.registers.set_bit_timing(bt);
749 self
750 }
751 /// Enables or disables loopback mode: Internally connects the TX and RX
752 /// signals together.
753 pub fn set_loopback(self, enabled: bool) -> Self {
754 self.can.registers.set_loopback(enabled);
755 self
756 }
757
758 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
759 pub fn set_silent(self, enabled: bool) -> Self {
760 self.can.registers.set_silent(enabled);
761 self
762 }
763
764 /// Enables or disables automatic retransmission of messages.
765 ///
766 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
767 /// until it can be sent. Otherwise, it will try only once to send each frame.
768 ///
769 /// Automatic retransmission is enabled by default.
770 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
771 self.can.registers.set_automatic_retransmit(enabled);
772 self
773 }
774
775 /// Leaves initialization mode and enables the peripheral.
776 ///
777 /// To sync with the CAN bus, this will block until 11 consecutive recessive bits are detected
778 /// on the bus.
779 ///
780 /// If you want to finish configuration without enabling the peripheral, you can call
781 /// [`CanBuilder::leave_disabled`] instead.
782 pub fn enable(mut self) -> Can<I> {
783 self.leave_init_mode();
784
785 match nb::block!(self.can.registers.enable_non_blocking()) {
786 Ok(()) => self.can,
787 Err(void) => match void {},
788 }
789 }
790
791 /// Returns the [`Can`] interface without enabling it.
792 ///
793 /// This leaves initialization mode, but keeps the peripheral in sleep mode instead of enabling
794 /// it.
795 ///
796 /// Before the [`Can`] instance can be used, you have to enable it by calling
797 /// [`Can::enable_non_blocking`].
798 pub fn leave_disabled(mut self) -> Can<I> {
799 self.leave_init_mode();
800 self.can
801 }
802
803 /// Leaves initialization mode, enters sleep mode.
804 fn leave_init_mode(&mut self) {
805 self.can.registers.leave_init_mode();
806 }
807}
808
809/// Interface to a bxCAN peripheral.
810pub struct Can<I: Instance> {
811 instance: I,
850 canregs: crate::pac::can::Can, 812 canregs: crate::pac::can::Can,
813 pub(crate) registers: Registers,
851} 814}
852 815
853impl<I> Rx0<I> 816impl<I> Can<I>
854where 817where
855 I: Instance, 818 I: Instance,
856{ 819{
857 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { 820 /// Creates a [`CanBuilder`] for constructing a CAN interface.
858 Self { 821 pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
859 _can: PhantomData, 822 let mut can_builder = CanBuilder {
860 canregs, 823 can: Can {
861 } 824 instance,
825 canregs,
826 registers: Registers { canregs },
827 },
828 };
829
830 can_builder.can.registers.enter_init_mode();
831
832 can_builder
833 }
834
835 /// Disables the CAN interface and returns back the raw peripheral it was created from.
836 ///
837 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
838 /// enter sleep mode.
839 pub fn free(self) -> I {
840 self.registers.reset();
841 self.instance
842 }
843
844 /// Configure bit timings and silent/loop-back mode.
845 ///
846 /// Calling this method will enter initialization mode.
847 pub fn modify_config(&mut self) -> CanConfig<'_, I> {
848 self.registers.enter_init_mode();
849
850 CanConfig { can: self }
851 }
852
853 /// Puts a CAN frame in a free transmit mailbox for transmission on the bus.
854 ///
855 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
856 /// Transmit order is preserved for frames with identical priority.
857 ///
858 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
859 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
860 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
861 /// [`TransmitStatus::dequeued_frame`].
862 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
863 // Safety: We have a `&mut self` and have unique access to the peripheral.
864 unsafe { Tx::<I>::conjure(self.canregs).transmit(frame) }
862 } 865 }
863 866
864 /// Returns a received frame if available. 867 /// Returns `true` if no frame is pending for transmission.
868 pub fn is_transmitter_idle(&self) -> bool {
869 // Safety: Read-only operation.
870 unsafe { Tx::<I>::conjure(self.canregs).is_idle() }
871 }
872
873 /// Attempts to abort the sending of a frame that is pending in a mailbox.
865 /// 874 ///
866 /// Returns `Err` when a frame was lost due to buffer overrun. 875 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
867 pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> { 876 /// aborted, this function has no effect and returns `false`.
868 receive_fifo(self.canregs, 0) 877 ///
878 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
879 /// returns `true`.
880 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
881 // Safety: We have a `&mut self` and have unique access to the peripheral.
882 unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) }
883 }
884
885 pub(crate) fn split_by_ref(&mut self) -> (Tx<I>, Rx<I>) {
886 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
887 let tx = unsafe { Tx::conjure(self.canregs) };
888 let rx0 = unsafe { Rx::conjure() };
889 (tx, rx0)
890 }
891}
892
893impl<I: FilterOwner> Can<I> {
894 /// Accesses the filter banks owned by this CAN peripheral.
895 ///
896 /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
897 /// peripheral instead.
898 pub fn modify_filters(&mut self) -> MasterFilters<'_, I> {
899 unsafe { MasterFilters::new(self.canregs) }
869 } 900 }
870} 901}
871 902
872/// Interface to receiver FIFO 1. 903/// Marker for Tx half
873pub struct Rx1<I> { 904pub struct Tx<I> {
874 _can: PhantomData<I>, 905 _can: PhantomData<I>,
875 canregs: crate::pac::can::Can, 906 pub(crate) registers: Registers,
876} 907}
877 908
878impl<I> Rx1<I> 909impl<I> Tx<I>
879where 910where
880 I: Instance, 911 I: Instance,
881{ 912{
882 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { 913 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
883 Self { 914 Self {
884 _can: PhantomData, 915 _can: PhantomData,
885 canregs, 916 registers: Registers { canregs }, //canregs,
886 } 917 }
887 } 918 }
888 919
889 /// Returns a received frame if available. 920 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
890 /// 921 ///
891 /// Returns `Err` when a frame was lost due to buffer overrun. 922 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
892 pub fn receive(&mut self) -> nb::Result<Frame, OverrunError> { 923 /// Transmit order is preserved for frames with identical priority.
893 receive_fifo(self.canregs, 1) 924 ///
925 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
926 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
927 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
928 /// [`TransmitStatus::dequeued_frame`].
929 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
930 self.registers.transmit(frame)
894 } 931 }
895}
896 932
897fn receive_fifo(canregs: crate::pac::can::Can, fifo_nr: usize) -> nb::Result<Frame, OverrunError> { 933 /// Attempts to abort the sending of a frame that is pending in a mailbox.
898 assert!(fifo_nr < 2); 934 ///
899 let rfr = canregs.rfr(fifo_nr); 935 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
900 let rx = canregs.rx(fifo_nr); 936 /// aborted, this function has no effect and returns `false`.
901 937 ///
902 //let rfr = &can.rfr[fifo_nr]; 938 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
903 //let rx = &can.rx[fifo_nr]; 939 /// returns `true`.
904 940 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
905 // Check if a frame is available in the mailbox. 941 self.registers.abort(mailbox)
906 let rfr_read = rfr.read();
907 if rfr_read.fmp() == 0 {
908 return Err(nb::Error::WouldBlock);
909 } 942 }
910 943
911 // Check for RX FIFO overrun. 944 /// Returns `true` if no frame is pending for transmission.
912 if rfr_read.fovr() { 945 pub fn is_idle(&self) -> bool {
913 rfr.write(|w| w.set_fovr(true)); 946 self.registers.is_idle()
914 return Err(nb::Error::Other(OverrunError { _priv: () }));
915 } 947 }
916 948
917 // Read the frame. 949 /// Clears the request complete flag for all mailboxes.
918 let id = IdReg(rx.rir().read().0); 950 pub fn clear_interrupt_flags(&mut self) {
919 let mut data = [0xff; 8]; 951 self.registers.clear_interrupt_flags()
920 data[0..4].copy_from_slice(&rx.rdlr().read().0.to_ne_bytes()); 952 }
921 data[4..8].copy_from_slice(&rx.rdhr().read().0.to_ne_bytes()); 953}
922 let len = rx.rdtr().read().dlc();
923 954
924 // Release the mailbox. 955/// Marker for Rx half
925 rfr.write(|w| w.set_rfom(true)); 956pub struct Rx<I> {
957 _can: PhantomData<I>,
958}
926 959
927 Ok(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap()) 960impl<I> Rx<I>
961where
962 I: Instance,
963{
964 unsafe fn conjure() -> Self {
965 Self { _can: PhantomData }
966 }
928} 967}
929 968
930/// Identifies one of the two receive FIFOs. 969/// Identifies one of the two receive FIFOs.
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 017c5110d..fd6a79092 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -10,31 +10,19 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::channel::Channel; 11use embassy_sync::channel::Channel;
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use futures::FutureExt;
14 13
15use crate::gpio::AFType; 14use crate::gpio::AFType;
16use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
17use crate::pac::can::vals::{Ide, Lec};
18use crate::rcc::RccPeripheral; 16use crate::rcc::RccPeripheral;
19use crate::{interrupt, peripherals, Peripheral}; 17use crate::{interrupt, peripherals, Peripheral};
20 18
21pub mod enums; 19pub mod enums;
22use enums::*;
23pub mod frame; 20pub mod frame;
24pub mod util; 21pub mod util;
22pub use frame::Envelope;
25 23
26/// Contains CAN frame and additional metadata. 24mod common;
27/// 25pub use self::common::{BufferedCanReceiver, BufferedCanSender};
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> {
@@ -48,8 +36,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::TXInterrupt> for TxInterruptH
48 v.set_rqcp(1, true); 36 v.set_rqcp(1, true);
49 v.set_rqcp(2, true); 37 v.set_rqcp(2, true);
50 }); 38 });
51 39 T::state().tx_mode.on_interrupt::<T>();
52 T::state().tx_waker.wake();
53 } 40 }
54} 41}
55 42
@@ -60,8 +47,7 @@ pub struct Rx0InterruptHandler<T: Instance> {
60 47
61impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> { 48impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
62 unsafe fn on_interrupt() { 49 unsafe fn on_interrupt() {
63 // info!("rx0 irq"); 50 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo0);
64 Can::<T>::receive_fifo(RxFifo::Fifo0);
65 } 51 }
66} 52}
67 53
@@ -72,8 +58,7 @@ pub struct Rx1InterruptHandler<T: Instance> {
72 58
73impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> { 59impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
74 unsafe fn on_interrupt() { 60 unsafe fn on_interrupt() {
75 // info!("rx1 irq"); 61 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo1);
76 Can::<T>::receive_fifo(RxFifo::Fifo1);
77 } 62 }
78} 63}
79 64
@@ -100,16 +85,6 @@ pub struct Can<'d, T: Instance> {
100 can: crate::can::bx::Can<BxcanInstance<'d, T>>, 85 can: crate::can::bx::Can<BxcanInstance<'d, T>>,
101} 86}
102 87
103/// Error returned by `try_read`
104#[derive(Debug)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub enum TryReadError {
107 /// Bus error
108 BusError(BusError),
109 /// Receive buffer is empty
110 Empty,
111}
112
113/// Error returned by `try_write` 88/// Error returned by `try_write`
114#[derive(Debug)] 89#[derive(Debug)]
115#[cfg_attr(feature = "defmt", derive(defmt::Format))] 90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -185,7 +160,7 @@ impl<'d, T: Instance> Can<'d, T> {
185 /// This will wait for 11 consecutive recessive bits (bus idle state). 160 /// This will wait for 11 consecutive recessive bits (bus idle state).
186 /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting. 161 /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
187 pub async fn enable(&mut self) { 162 pub async fn enable(&mut self) {
188 while self.enable_non_blocking().is_err() { 163 while self.registers.enable_non_blocking().is_err() {
189 // SCE interrupt is only generated for entering sleep mode, but not leaving. 164 // SCE interrupt is only generated for entering sleep mode, but not leaving.
190 // Yield to allow other tasks to execute while can bus is initializing. 165 // Yield to allow other tasks to execute while can bus is initializing.
191 embassy_futures::yield_now().await; 166 embassy_futures::yield_now().await;
@@ -227,77 +202,40 @@ impl<'d, T: Instance> Can<'d, T> {
227 /// 202 ///
228 /// Returns a tuple of the time the message was received and the message frame 203 /// Returns a tuple of the time the message was received and the message frame
229 pub async fn read(&mut self) -> Result<Envelope, BusError> { 204 pub async fn read(&mut self) -> Result<Envelope, BusError> {
230 self.split().1.read().await 205 T::state().rx_mode.read::<T>().await
231 } 206 }
232 207
233 /// Attempts to read a CAN frame without blocking. 208 /// Attempts to read a CAN frame without blocking.
234 /// 209 ///
235 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 210 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
236 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 211 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
237 self.split().1.try_read() 212 T::state().rx_mode.try_read::<T>()
238 } 213 }
239 214
240 /// Waits while receive queue is empty. 215 /// Waits while receive queue is empty.
241 pub async fn wait_not_empty(&mut self) { 216 pub async fn wait_not_empty(&mut self) {
242 self.split().1.wait_not_empty().await 217 T::state().rx_mode.wait_not_empty::<T>().await
243 }
244
245 unsafe fn receive_fifo(fifo: RxFifo) {
246 // Generate timestamp as early as possible
247 #[cfg(feature = "time")]
248 let ts = embassy_time::Instant::now();
249
250 let state = T::state();
251 let regs = T::regs();
252 let fifo_idx = match fifo {
253 RxFifo::Fifo0 => 0usize,
254 RxFifo::Fifo1 => 1usize,
255 };
256 let rfr = regs.rfr(fifo_idx);
257 let fifo = regs.rx(fifo_idx);
258
259 loop {
260 // If there are no pending messages, there is nothing to do
261 if rfr.read().fmp() == 0 {
262 return;
263 }
264
265 let rir = fifo.rir().read();
266 let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
267 embedded_can::StandardId::new(rir.stid()).unwrap().into()
268 } else {
269 let stid = (rir.stid() & 0x7FF) as u32;
270 let exid = rir.exid() & 0x3FFFF;
271 let id = (stid << 18) | (exid);
272 embedded_can::ExtendedId::new(id).unwrap().into()
273 };
274 let data_len = fifo.rdtr().read().dlc();
275 let mut data: [u8; 8] = [0; 8];
276 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
277 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
278
279 let frame = Frame::new(Header::new(id, data_len, false), &data).unwrap();
280 let envelope = Envelope {
281 #[cfg(feature = "time")]
282 ts,
283 frame,
284 };
285
286 rfr.modify(|v| v.set_rfom(true));
287
288 /*
289 NOTE: consensus was reached that if rx_queue is full, packets should be dropped
290 */
291 let _ = state.rx_queue.try_send(envelope);
292 }
293 } 218 }
294 219
295 /// Split the CAN driver into transmit and receive halves. 220 /// Split the CAN driver into transmit and receive halves.
296 /// 221 ///
297 /// Useful for doing separate transmit/receive tasks. 222 /// Useful for doing separate transmit/receive tasks.
298 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) { 223 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) {
299 let (tx, rx0, rx1) = self.can.split_by_ref(); 224 let (tx, rx) = self.can.split_by_ref();
300 (CanTx { tx }, CanRx { rx0, rx1 }) 225 (CanTx { tx }, CanRx { rx })
226 }
227
228 /// Return a buffered instance of driver. User must supply Buffers
229 pub fn buffered<'c, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
230 &'c mut self,
231 txb: &'static mut TxBuf<TX_BUF_SIZE>,
232 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
233 ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
234 let (tx, rx) = self.split();
235 BufferedCan {
236 tx: tx.buffered(txb),
237 rx: rx.buffered(rxb),
238 }
301 } 239 }
302} 240}
303 241
@@ -308,6 +246,46 @@ impl<'d, T: Instance> AsMut<crate::can::bx::Can<BxcanInstance<'d, T>>> for Can<'
308 } 246 }
309} 247}
310 248
249/// Buffered CAN driver.
250pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
251 tx: BufferedCanTx<'d, T, TX_BUF_SIZE>,
252 rx: BufferedCanRx<'d, T, RX_BUF_SIZE>,
253}
254
255impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
256 /// Async write frame to TX buffer.
257 pub async fn write(&mut self, frame: &Frame) {
258 self.tx.write(frame).await
259 }
260
261 /// Returns a sender that can be used for sending CAN frames.
262 pub fn writer(&self) -> BufferedCanSender {
263 self.tx.writer()
264 }
265
266 /// Async read frame from RX buffer.
267 pub async fn read(&mut self) -> Result<Envelope, BusError> {
268 self.rx.read().await
269 }
270
271 /// Attempts to read a CAN frame without blocking.
272 ///
273 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
274 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
275 self.rx.try_read()
276 }
277
278 /// Waits while receive queue is empty.
279 pub async fn wait_not_empty(&mut self) {
280 self.rx.wait_not_empty().await
281 }
282
283 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
284 pub fn reader(&self) -> BufferedCanReceiver {
285 self.rx.reader()
286 }
287}
288
311/// CAN driver, transmit half. 289/// CAN driver, transmit half.
312pub struct CanTx<'d, T: Instance> { 290pub struct CanTx<'d, T: Instance> {
313 tx: crate::can::bx::Tx<BxcanInstance<'d, T>>, 291 tx: crate::can::bx::Tx<BxcanInstance<'d, T>>,
@@ -319,7 +297,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
319 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure. 297 /// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
320 pub async fn write(&mut self, frame: &Frame) -> crate::can::bx::TransmitStatus { 298 pub async fn write(&mut self, frame: &Frame) -> crate::can::bx::TransmitStatus {
321 poll_fn(|cx| { 299 poll_fn(|cx| {
322 T::state().tx_waker.register(cx.waker()); 300 T::state().tx_mode.register(cx.waker());
323 if let Ok(status) = self.tx.transmit(frame) { 301 if let Ok(status) = self.tx.transmit(frame) {
324 return Poll::Ready(status); 302 return Poll::Ready(status);
325 } 303 }
@@ -338,7 +316,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
338 316
339 async fn flush_inner(mb: crate::can::bx::Mailbox) { 317 async fn flush_inner(mb: crate::can::bx::Mailbox) {
340 poll_fn(|cx| { 318 poll_fn(|cx| {
341 T::state().tx_waker.register(cx.waker()); 319 T::state().tx_mode.register(cx.waker());
342 if T::regs().tsr().read().tme(mb.index()) { 320 if T::regs().tsr().read().tme(mb.index()) {
343 return Poll::Ready(()); 321 return Poll::Ready(());
344 } 322 }
@@ -355,7 +333,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
355 333
356 async fn flush_any_inner() { 334 async fn flush_any_inner() {
357 poll_fn(|cx| { 335 poll_fn(|cx| {
358 T::state().tx_waker.register(cx.waker()); 336 T::state().tx_mode.register(cx.waker());
359 337
360 let tsr = T::regs().tsr().read(); 338 let tsr = T::regs().tsr().read();
361 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index()) 339 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index())
@@ -377,7 +355,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
377 355
378 async fn flush_all_inner() { 356 async fn flush_all_inner() {
379 poll_fn(|cx| { 357 poll_fn(|cx| {
380 T::state().tx_waker.register(cx.waker()); 358 T::state().tx_mode.register(cx.waker());
381 359
382 let tsr = T::regs().tsr().read(); 360 let tsr = T::regs().tsr().read();
383 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index()) 361 if tsr.tme(crate::can::bx::Mailbox::Mailbox0.index())
@@ -396,13 +374,68 @@ impl<'d, T: Instance> CanTx<'d, T> {
396 pub async fn flush_all(&self) { 374 pub async fn flush_all(&self) {
397 Self::flush_all_inner().await 375 Self::flush_all_inner().await
398 } 376 }
377
378 /// Return a buffered instance of driver. User must supply Buffers
379 pub fn buffered<const TX_BUF_SIZE: usize>(
380 self,
381 txb: &'static mut TxBuf<TX_BUF_SIZE>,
382 ) -> BufferedCanTx<'d, T, TX_BUF_SIZE> {
383 BufferedCanTx::new(self.tx, txb)
384 }
385}
386
387/// User supplied buffer for TX buffering
388pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
389
390/// Buffered CAN driver, transmit half.
391pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> {
392 _tx: crate::can::bx::Tx<BxcanInstance<'d, T>>,
393 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
394}
395
396impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> {
397 fn new(_tx: crate::can::bx::Tx<BxcanInstance<'d, T>>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
398 Self { _tx, tx_buf }.setup()
399 }
400
401 fn setup(self) -> Self {
402 // We don't want interrupts being processed while we change modes.
403 critical_section::with(|_| unsafe {
404 let tx_inner = self::common::ClassicBufferedTxInner {
405 tx_receiver: self.tx_buf.receiver().into(),
406 };
407 T::mut_state().tx_mode = TxMode::Buffered(tx_inner);
408 });
409 self
410 }
411
412 /// Async write frame to TX buffer.
413 pub async fn write(&mut self, frame: &Frame) {
414 self.tx_buf.send(*frame).await;
415 T::TXInterrupt::pend(); // Wake for Tx
416 }
417
418 /// Returns a sender that can be used for sending CAN frames.
419 pub fn writer(&self) -> BufferedCanSender {
420 BufferedCanSender {
421 tx_buf: self.tx_buf.sender().into(),
422 waker: T::TXInterrupt::pend,
423 }
424 }
425}
426
427impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX_BUF_SIZE> {
428 fn drop(&mut self) {
429 critical_section::with(|_| unsafe {
430 T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
431 });
432 }
399} 433}
400 434
401/// CAN driver, receive half. 435/// CAN driver, receive half.
402#[allow(dead_code)] 436#[allow(dead_code)]
403pub struct CanRx<'d, T: Instance> { 437pub struct CanRx<'d, T: Instance> {
404 rx0: crate::can::bx::Rx0<BxcanInstance<'d, T>>, 438 rx: crate::can::bx::Rx<BxcanInstance<'d, T>>,
405 rx1: crate::can::bx::Rx1<BxcanInstance<'d, T>>,
406} 439}
407 440
408impl<'d, T: Instance> CanRx<'d, T> { 441impl<'d, T: Instance> CanRx<'d, T> {
@@ -412,59 +445,107 @@ impl<'d, T: Instance> CanRx<'d, T> {
412 /// 445 ///
413 /// Returns a tuple of the time the message was received and the message frame 446 /// Returns a tuple of the time the message was received and the message frame
414 pub async fn read(&mut self) -> Result<Envelope, BusError> { 447 pub async fn read(&mut self) -> Result<Envelope, BusError> {
415 poll_fn(|cx| { 448 T::state().rx_mode.read::<T>().await
416 T::state().err_waker.register(cx.waker());
417 if let Poll::Ready(envelope) = T::state().rx_queue.receive().poll_unpin(cx) {
418 return Poll::Ready(Ok(envelope));
419 } else if let Some(err) = self.curr_error() {
420 return Poll::Ready(Err(err));
421 }
422
423 Poll::Pending
424 })
425 .await
426 } 449 }
427 450
428 /// Attempts to read a CAN frame without blocking. 451 /// Attempts to read a CAN frame without blocking.
429 /// 452 ///
430 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 453 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
431 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 454 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
432 if let Ok(envelope) = T::state().rx_queue.try_receive() { 455 T::state().rx_mode.try_read::<T>()
433 return Ok(envelope); 456 }
434 }
435 457
436 if let Some(err) = self.curr_error() { 458 /// Waits while receive queue is empty.
437 return Err(TryReadError::BusError(err)); 459 pub async fn wait_not_empty(&mut self) {
438 } 460 T::state().rx_mode.wait_not_empty::<T>().await
461 }
439 462
440 Err(TryReadError::Empty) 463 /// Return a buffered instance of driver. User must supply Buffers
464 pub fn buffered<const RX_BUF_SIZE: usize>(
465 self,
466 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
467 ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
468 BufferedCanRx::new(self.rx, rxb)
469 }
470}
471
472/// User supplied buffer for RX Buffering
473pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
474
475/// CAN driver, receive half in Buffered mode.
476pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
477 _rx: crate::can::bx::Rx<BxcanInstance<'d, T>>,
478 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
479}
480
481impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
482 fn new(_rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
483 BufferedCanRx { _rx, rx_buf }.setup()
484 }
485
486 fn setup(self) -> Self {
487 // We don't want interrupts being processed while we change modes.
488 critical_section::with(|_| unsafe {
489 let rx_inner = self::common::ClassicBufferedRxInner {
490 rx_sender: self.rx_buf.sender().into(),
491 };
492 T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
493 });
494 self
495 }
496
497 /// Async read frame from RX buffer.
498 pub async fn read(&mut self) -> Result<Envelope, BusError> {
499 self.rx_buf.receive().await
500 }
501
502 /// Attempts to read a CAN frame without blocking.
503 ///
504 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
505 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
506 match &T::state().rx_mode {
507 RxMode::Buffered(_) => {
508 if let Ok(result) = self.rx_buf.try_receive() {
509 match result {
510 Ok(envelope) => Ok(envelope),
511 Err(e) => Err(TryReadError::BusError(e)),
512 }
513 } else {
514 let registers = crate::can::bx::Registers { canregs: T::regs() };
515 if let Some(err) = registers.curr_error() {
516 return Err(TryReadError::BusError(err));
517 } else {
518 Err(TryReadError::Empty)
519 }
520 }
521 }
522 _ => {
523 panic!("Bad Mode")
524 }
525 }
441 } 526 }
442 527
443 /// Waits while receive queue is empty. 528 /// Waits while receive queue is empty.
444 pub async fn wait_not_empty(&mut self) { 529 pub async fn wait_not_empty(&mut self) {
445 poll_fn(|cx| T::state().rx_queue.poll_ready_to_receive(cx)).await 530 poll_fn(|cx| self.rx_buf.poll_ready_to_receive(cx)).await
446 } 531 }
447 532
448 fn curr_error(&self) -> Option<BusError> { 533 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
449 let err = { T::regs().esr().read() }; 534 pub fn reader(&self) -> BufferedCanReceiver {
450 if err.boff() { 535 self.rx_buf.receiver().into()
451 return Some(BusError::BusOff);
452 } else if err.epvf() {
453 return Some(BusError::BusPassive);
454 } else if err.ewgf() {
455 return Some(BusError::BusWarning);
456 } else if let Some(err) = err.lec().into_bus_err() {
457 return Some(err);
458 }
459 None
460 } 536 }
461} 537}
462 538
463enum RxFifo { 539impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX_BUF_SIZE> {
464 Fifo0, 540 fn drop(&mut self) {
465 Fifo1, 541 critical_section::with(|_| unsafe {
542 T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
543 });
544 }
466} 545}
467 546
547use crate::can::bx::RxFifo;
548
468impl<'d, T: Instance> Drop for Can<'d, T> { 549impl<'d, T: Instance> Drop for Can<'d, T> {
469 fn drop(&mut self) { 550 fn drop(&mut self) {
470 // Cannot call `free()` because it moves the instance. 551 // Cannot call `free()` because it moves the instance.
@@ -488,18 +569,163 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
488 } 569 }
489} 570}
490 571
572use crate::can::enums::{BusError, TryReadError};
573
574pub(crate) enum RxMode {
575 NonBuffered(AtomicWaker),
576 Buffered(crate::can::_version::common::ClassicBufferedRxInner),
577}
578
579impl RxMode {
580 pub fn on_interrupt<T: Instance>(&self, fifo: crate::can::_version::bx::RxFifo) {
581 match self {
582 Self::NonBuffered(waker) => {
583 // Disable interrupts until read
584 let fifo_idx = match fifo {
585 crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
586 crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
587 };
588 T::regs().ier().write(|w| {
589 w.set_fmpie(fifo_idx, false);
590 });
591 waker.wake();
592 }
593 Self::Buffered(buf) => {
594 let regsisters = crate::can::bx::Registers { canregs: T::regs() };
595
596 loop {
597 match regsisters.receive_fifo(fifo) {
598 Some(envelope) => {
599 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
600 let _ = buf.rx_sender.try_send(Ok(envelope));
601 }
602 None => return,
603 };
604 }
605 }
606 }
607 }
608
609 pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> {
610 match self {
611 Self::NonBuffered(waker) => {
612 poll_fn(|cx| {
613 T::state().err_waker.register(cx.waker());
614 waker.register(cx.waker());
615 match self.try_read::<T>() {
616 Ok(result) => Poll::Ready(Ok(result)),
617 Err(TryReadError::Empty) => Poll::Pending,
618 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
619 }
620 })
621 .await
622 }
623 _ => {
624 panic!("Bad Mode")
625 }
626 }
627 }
628 pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
629 match self {
630 Self::NonBuffered(_) => {
631 let registers = crate::can::bx::Registers { canregs: T::regs() };
632 if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo0) {
633 T::regs().ier().write(|w| {
634 w.set_fmpie(0, true);
635 });
636 Ok(msg)
637 } else if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo1) {
638 T::regs().ier().write(|w| {
639 w.set_fmpie(1, true);
640 });
641 Ok(msg)
642 } else if let Some(err) = registers.curr_error() {
643 Err(TryReadError::BusError(err))
644 } else {
645 Err(TryReadError::Empty)
646 }
647 }
648 _ => {
649 panic!("Bad Mode")
650 }
651 }
652 }
653 pub async fn wait_not_empty<T: Instance>(&self) {
654 match &T::state().rx_mode {
655 Self::NonBuffered(waker) => {
656 poll_fn(|cx| {
657 waker.register(cx.waker());
658 let registers = crate::can::bx::Registers { canregs: T::regs() };
659 if registers.receive_frame_available() {
660 Poll::Ready(())
661 } else {
662 Poll::Pending
663 }
664 })
665 .await
666 }
667 _ => {
668 panic!("Bad Mode")
669 }
670 }
671 }
672}
673
674enum TxMode {
675 NonBuffered(AtomicWaker),
676 Buffered(self::common::ClassicBufferedTxInner),
677}
678
679impl TxMode {
680 pub fn buffer_free<T: Instance>(&self) -> bool {
681 let tsr = T::regs().tsr().read();
682 tsr.tme(crate::can::bx::Mailbox::Mailbox0.index())
683 || tsr.tme(crate::can::bx::Mailbox::Mailbox1.index())
684 || tsr.tme(crate::can::bx::Mailbox::Mailbox2.index())
685 }
686 pub fn on_interrupt<T: Instance>(&self) {
687 match &T::state().tx_mode {
688 TxMode::NonBuffered(waker) => waker.wake(),
689 TxMode::Buffered(buf) => {
690 while self.buffer_free::<T>() {
691 match buf.tx_receiver.try_receive() {
692 Ok(frame) => {
693 let mut registers = crate::can::bx::Registers { canregs: T::regs() };
694 _ = registers.transmit(&frame);
695 }
696 Err(_) => {
697 break;
698 }
699 }
700 }
701 }
702 }
703 }
704
705 fn register(&self, arg: &core::task::Waker) {
706 match self {
707 TxMode::NonBuffered(waker) => {
708 waker.register(arg);
709 }
710 _ => {
711 panic!("Bad mode");
712 }
713 }
714 }
715}
716
491struct State { 717struct State {
492 pub tx_waker: AtomicWaker, 718 pub(crate) rx_mode: RxMode,
719 pub(crate) tx_mode: TxMode,
493 pub err_waker: AtomicWaker, 720 pub err_waker: AtomicWaker,
494 pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>,
495} 721}
496 722
497impl State { 723impl State {
498 pub const fn new() -> Self { 724 pub const fn new() -> Self {
499 Self { 725 Self {
500 tx_waker: AtomicWaker::new(), 726 rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
727 tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
501 err_waker: AtomicWaker::new(), 728 err_waker: AtomicWaker::new(),
502 rx_queue: Channel::new(),
503 } 729 }
504 } 730 }
505} 731}
@@ -507,6 +733,7 @@ impl State {
507trait SealedInstance { 733trait SealedInstance {
508 fn regs() -> crate::pac::can::Can; 734 fn regs() -> crate::pac::can::Can;
509 fn state() -> &'static State; 735 fn state() -> &'static State;
736 unsafe fn mut_state() -> &'static mut State;
510} 737}
511 738
512/// CAN instance trait. 739/// CAN instance trait.
@@ -535,9 +762,12 @@ foreach_peripheral!(
535 crate::pac::$inst 762 crate::pac::$inst
536 } 763 }
537 764
765 unsafe fn mut_state() -> & 'static mut State {
766 static mut STATE: State = State::new();
767 &mut *core::ptr::addr_of_mut!(STATE)
768 }
538 fn state() -> &'static State { 769 fn state() -> &'static State {
539 static STATE: State = State::new(); 770 unsafe { peripherals::$inst::mut_state() }
540 &STATE
541 } 771 }
542 } 772 }
543 773
@@ -601,22 +831,3 @@ impl Index for crate::can::bx::Mailbox {
601 } 831 }
602 } 832 }
603} 833}
604
605trait IntoBusError {
606 fn into_bus_err(self) -> Option<BusError>;
607}
608
609impl IntoBusError for Lec {
610 fn into_bus_err(self) -> Option<BusError> {
611 match self {
612 Lec::STUFF => Some(BusError::Stuff),
613 Lec::FORM => Some(BusError::Form),
614 Lec::ACK => Some(BusError::Acknowledge),
615 Lec::BITRECESSIVE => Some(BusError::BitRecessive),
616 Lec::BITDOMINANT => Some(BusError::BitDominant),
617 Lec::CRC => Some(BusError::Crc),
618 Lec::CUSTOM => Some(BusError::Software),
619 _ => None,
620 }
621 }
622}
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs
new file mode 100644
index 000000000..570761b19
--- /dev/null
+++ b/embassy-stm32/src/can/common.rs
@@ -0,0 +1,52 @@
1use embassy_sync::channel::{DynamicReceiver, DynamicSender};
2
3use crate::can::_version::enums::*;
4use crate::can::_version::frame::*;
5
6pub(crate) struct ClassicBufferedRxInner {
7 pub rx_sender: DynamicSender<'static, Result<Envelope, BusError>>,
8}
9pub(crate) struct ClassicBufferedTxInner {
10 pub tx_receiver: DynamicReceiver<'static, Frame>,
11}
12
13#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
14
15pub(crate) struct FdBufferedRxInner {
16 pub rx_sender: DynamicSender<'static, Result<FdEnvelope, BusError>>,
17}
18
19#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
20pub(crate) struct FdBufferedTxInner {
21 pub tx_receiver: DynamicReceiver<'static, FdFrame>,
22}
23
24/// Sender that can be used for sending CAN frames.
25#[derive(Copy, Clone)]
26pub struct BufferedCanSender {
27 pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, Frame>,
28 pub(crate) waker: fn(),
29}
30
31impl BufferedCanSender {
32 /// Async write frame to TX buffer.
33 pub fn try_write(&mut self, frame: Frame) -> Result<(), embassy_sync::channel::TrySendError<Frame>> {
34 self.tx_buf.try_send(frame)?;
35 (self.waker)();
36 Ok(())
37 }
38
39 /// Async write frame to TX buffer.
40 pub async fn write(&mut self, frame: Frame) {
41 self.tx_buf.send(frame).await;
42 (self.waker)();
43 }
44
45 /// Allows a poll_fn to poll until the channel is ready to write
46 pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
47 self.tx_buf.poll_ready_to_send(cx)
48 }
49}
50
51/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
52pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, Result<Envelope, BusError>>;
diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs
index 651de9194..4d89c84d1 100644
--- a/embassy-stm32/src/can/enums.rs
+++ b/embassy-stm32/src/can/enums.rs
@@ -40,3 +40,13 @@ pub enum FrameCreateError {
40 /// Invalid ID. 40 /// Invalid ID.
41 InvalidCanId, 41 InvalidCanId,
42} 42}
43
44/// Error returned by `try_read`
45#[derive(Debug)]
46#[cfg_attr(feature = "defmt", derive(defmt::Format))]
47pub enum TryReadError {
48 /// Bus error
49 BusError(BusError),
50 /// Receive buffer is empty
51 Empty,
52}
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 4ea036ab4..2ccf4b093 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -14,6 +14,7 @@ use crate::interrupt::typelevel::Interrupt;
14use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
15use crate::{interrupt, peripherals, Peripheral}; 15use crate::{interrupt, peripherals, Peripheral};
16 16
17mod common;
17pub mod enums; 18pub mod enums;
18pub(crate) mod fd; 19pub(crate) mod fd;
19pub mod frame; 20pub mod frame;
@@ -25,6 +26,8 @@ use fd::filter::*;
25pub use fd::{config, filter}; 26pub use fd::{config, filter};
26use frame::*; 27use frame::*;
27 28
29pub use self::common::{BufferedCanReceiver, BufferedCanSender};
30
28/// Timestamp for incoming packets. Use Embassy time when enabled. 31/// Timestamp for incoming packets. Use Embassy time when enabled.
29#[cfg(feature = "time")] 32#[cfg(feature = "time")]
30pub type Timestamp = embassy_time::Instant; 33pub type Timestamp = embassy_time::Instant;
@@ -107,7 +110,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1Interrup
107#[derive(Debug, Copy, Clone, Eq, PartialEq)] 110#[derive(Debug, Copy, Clone, Eq, PartialEq)]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))] 111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
109/// Different operating modes 112/// Different operating modes
110pub enum FdcanOperatingMode { 113pub enum OperatingMode {
111 //PoweredDownMode, 114 //PoweredDownMode,
112 //ConfigMode, 115 //ConfigMode,
113 /// 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
@@ -145,7 +148,7 @@ pub enum FdcanOperatingMode {
145 148
146/// FDCAN Configuration instance instance 149/// FDCAN Configuration instance instance
147/// Create instance of this first 150/// Create instance of this first
148pub struct FdcanConfigurator<'d, T: Instance> { 151pub struct CanConfigurator<'d, T: Instance> {
149 config: crate::can::fd::config::FdCanConfig, 152 config: crate::can::fd::config::FdCanConfig,
150 /// Reference to internals. 153 /// Reference to internals.
151 instance: FdcanInstance<'d, T>, 154 instance: FdcanInstance<'d, T>,
@@ -166,7 +169,7 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransm
166 } 169 }
167} 170}
168 171
169impl<'d, T: Instance> FdcanConfigurator<'d, T> { 172impl<'d, T: Instance> CanConfigurator<'d, T> {
170 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. 173 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
171 /// You must call [Fdcan::enable_non_blocking] to use the peripheral. 174 /// You must call [Fdcan::enable_non_blocking] to use the peripheral.
172 pub fn new( 175 pub fn new(
@@ -176,7 +179,7 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
176 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>> 179 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
177 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>> 180 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
178 + 'd, 181 + 'd,
179 ) -> FdcanConfigurator<'d, T> { 182 ) -> CanConfigurator<'d, T> {
180 into_ref!(peri, rx, tx); 183 into_ref!(peri, rx, tx);
181 184
182 rx.set_as_af(rx.af_num(), AFType::Input); 185 rx.set_as_af(rx.af_num(), AFType::Input);
@@ -270,13 +273,13 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
270 } 273 }
271 274
272 /// Start in mode. 275 /// Start in mode.
273 pub fn start(self, mode: FdcanOperatingMode) -> Fdcan<'d, T> { 276 pub fn start(self, mode: OperatingMode) -> Can<'d, T> {
274 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);
275 critical_section::with(|_| unsafe { 278 critical_section::with(|_| unsafe {
276 T::mut_state().ns_per_timer_tick = ns_per_timer_tick; 279 T::mut_state().ns_per_timer_tick = ns_per_timer_tick;
277 }); 280 });
278 T::registers().into_mode(self.config, mode); 281 T::registers().into_mode(self.config, mode);
279 let ret = Fdcan { 282 let ret = Can {
280 config: self.config, 283 config: self.config,
281 instance: self.instance, 284 instance: self.instance,
282 _mode: mode, 285 _mode: mode,
@@ -285,30 +288,30 @@ impl<'d, T: Instance> FdcanConfigurator<'d, T> {
285 } 288 }
286 289
287 /// Start, entering mode. Does same as start(mode) 290 /// Start, entering mode. Does same as start(mode)
288 pub fn into_normal_mode(self) -> Fdcan<'d, T> { 291 pub fn into_normal_mode(self) -> Can<'d, T> {
289 self.start(FdcanOperatingMode::NormalOperationMode) 292 self.start(OperatingMode::NormalOperationMode)
290 } 293 }
291 294
292 /// Start, entering mode. Does same as start(mode) 295 /// Start, entering mode. Does same as start(mode)
293 pub fn into_internal_loopback_mode(self) -> Fdcan<'d, T> { 296 pub fn into_internal_loopback_mode(self) -> Can<'d, T> {
294 self.start(FdcanOperatingMode::InternalLoopbackMode) 297 self.start(OperatingMode::InternalLoopbackMode)
295 } 298 }
296 299
297 /// Start, entering mode. Does same as start(mode) 300 /// Start, entering mode. Does same as start(mode)
298 pub fn into_external_loopback_mode(self) -> Fdcan<'d, T> { 301 pub fn into_external_loopback_mode(self) -> Can<'d, T> {
299 self.start(FdcanOperatingMode::ExternalLoopbackMode) 302 self.start(OperatingMode::ExternalLoopbackMode)
300 } 303 }
301} 304}
302 305
303/// FDCAN Instance 306/// FDCAN Instance
304pub struct Fdcan<'d, T: Instance> { 307pub struct Can<'d, T: Instance> {
305 config: crate::can::fd::config::FdCanConfig, 308 config: crate::can::fd::config::FdCanConfig,
306 /// Reference to internals. 309 /// Reference to internals.
307 instance: FdcanInstance<'d, T>, 310 instance: FdcanInstance<'d, T>,
308 _mode: FdcanOperatingMode, 311 _mode: OperatingMode,
309} 312}
310 313
311impl<'d, T: Instance> Fdcan<'d, T> { 314impl<'d, T: Instance> Can<'d, T> {
312 /// Flush one of the TX mailboxes. 315 /// Flush one of the TX mailboxes.
313 pub async fn flush(&self, idx: usize) { 316 pub async fn flush(&self, idx: usize) {
314 poll_fn(|cx| { 317 poll_fn(|cx| {
@@ -331,12 +334,12 @@ impl<'d, T: Instance> Fdcan<'d, T> {
331 /// 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
332 /// 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
333 /// transmitted, then tries again. 336 /// transmitted, then tries again.
334 pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> { 337 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
335 T::state().tx_mode.write::<T>(frame).await 338 T::state().tx_mode.write::<T>(frame).await
336 } 339 }
337 340
338 /// Returns the next received message frame 341 /// Returns the next received message frame
339 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 342 pub async fn read(&mut self) -> Result<Envelope, BusError> {
340 T::state().rx_mode.read_classic::<T>().await 343 T::state().rx_mode.read_classic::<T>().await
341 } 344 }
342 345
@@ -349,19 +352,19 @@ impl<'d, T: Instance> Fdcan<'d, T> {
349 } 352 }
350 353
351 /// Returns the next received message frame 354 /// Returns the next received message frame
352 pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> { 355 pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
353 T::state().rx_mode.read_fd::<T>().await 356 T::state().rx_mode.read_fd::<T>().await
354 } 357 }
355 358
356 /// Split instance into separate Tx(write) and Rx(read) portions 359 /// Split instance into separate Tx(write) and Rx(read) portions
357 pub fn split(self) -> (FdcanTx<'d, T>, FdcanRx<'d, T>) { 360 pub fn split(self) -> (CanTx<'d, T>, CanRx<'d, T>) {
358 ( 361 (
359 FdcanTx { 362 CanTx {
360 config: self.config, 363 config: self.config,
361 _instance: self.instance, 364 _instance: self.instance,
362 _mode: self._mode, 365 _mode: self._mode,
363 }, 366 },
364 FdcanRx { 367 CanRx {
365 _instance1: PhantomData::<T>, 368 _instance1: PhantomData::<T>,
366 _instance2: T::regs(), 369 _instance2: T::regs(),
367 _mode: self._mode, 370 _mode: self._mode,
@@ -370,8 +373,8 @@ impl<'d, T: Instance> Fdcan<'d, T> {
370 } 373 }
371 374
372 /// Join split rx and tx portions back together 375 /// Join split rx and tx portions back together
373 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 {
374 Fdcan { 377 Can {
375 config: tx.config, 378 config: tx.config,
376 //_instance2: T::regs(), 379 //_instance2: T::regs(),
377 instance: tx._instance, 380 instance: tx._instance,
@@ -399,59 +402,27 @@ impl<'d, T: Instance> Fdcan<'d, T> {
399} 402}
400 403
401/// User supplied buffer for RX Buffering 404/// User supplied buffer for RX Buffering
402pub type RxBuf<const BUF_SIZE: usize> = 405pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
403 Channel<CriticalSectionRawMutex, Result<(ClassicFrame, Timestamp), BusError>, BUF_SIZE>;
404 406
405/// User supplied buffer for TX buffering 407/// User supplied buffer for TX buffering
406pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; 408pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
407 409
408/// Buffered FDCAN Instance 410/// Buffered FDCAN Instance
409pub 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> {
410 _instance1: PhantomData<T>, 412 _instance1: PhantomData<T>,
411 _instance2: &'d crate::pac::can::Fdcan, 413 _instance2: &'d crate::pac::can::Fdcan,
412 _mode: FdcanOperatingMode, 414 _mode: OperatingMode,
413 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 415 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
414 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 416 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
415} 417}
416 418
417/// Sender that can be used for sending CAN frames.
418#[derive(Copy, Clone)]
419pub struct BufferedCanSender {
420 tx_buf: embassy_sync::channel::DynamicSender<'static, ClassicFrame>,
421 waker: fn(),
422}
423
424impl BufferedCanSender {
425 /// Async write frame to TX buffer.
426 pub fn try_write(&mut self, frame: ClassicFrame) -> Result<(), embassy_sync::channel::TrySendError<ClassicFrame>> {
427 self.tx_buf.try_send(frame)?;
428 (self.waker)();
429 Ok(())
430 }
431
432 /// Async write frame to TX buffer.
433 pub async fn write(&mut self, frame: ClassicFrame) {
434 self.tx_buf.send(frame).await;
435 (self.waker)();
436 }
437
438 /// Allows a poll_fn to poll until the channel is ready to write
439 pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
440 self.tx_buf.poll_ready_to_send(cx)
441 }
442}
443
444/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
445pub type BufferedCanReceiver =
446 embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>;
447
448impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> 419impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
449 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> 420 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
450{ 421{
451 fn new( 422 fn new(
452 _instance1: PhantomData<T>, 423 _instance1: PhantomData<T>,
453 _instance2: &'d crate::pac::can::Fdcan, 424 _instance2: &'d crate::pac::can::Fdcan,
454 _mode: FdcanOperatingMode, 425 _mode: OperatingMode,
455 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 426 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
456 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 427 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
457 ) -> Self { 428 ) -> Self {
@@ -468,10 +439,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
468 fn setup(self) -> Self { 439 fn setup(self) -> Self {
469 // We don't want interrupts being processed while we change modes. 440 // We don't want interrupts being processed while we change modes.
470 critical_section::with(|_| unsafe { 441 critical_section::with(|_| unsafe {
471 let rx_inner = ClassicBufferedRxInner { 442 let rx_inner = self::common::ClassicBufferedRxInner {
472 rx_sender: self.rx_buf.sender().into(), 443 rx_sender: self.rx_buf.sender().into(),
473 }; 444 };
474 let tx_inner = ClassicBufferedTxInner { 445 let tx_inner = self::common::ClassicBufferedTxInner {
475 tx_receiver: self.tx_buf.receiver().into(), 446 tx_receiver: self.tx_buf.receiver().into(),
476 }; 447 };
477 T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); 448 T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner);
@@ -481,13 +452,13 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
481 } 452 }
482 453
483 /// Async write frame to TX buffer. 454 /// Async write frame to TX buffer.
484 pub async fn write(&mut self, frame: ClassicFrame) { 455 pub async fn write(&mut self, frame: Frame) {
485 self.tx_buf.send(frame).await; 456 self.tx_buf.send(frame).await;
486 T::IT0Interrupt::pend(); // Wake for Tx 457 T::IT0Interrupt::pend(); // Wake for Tx
487 } 458 }
488 459
489 /// Async read frame from RX buffer. 460 /// Async read frame from RX buffer.
490 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 461 pub async fn read(&mut self) -> Result<Envelope, BusError> {
491 self.rx_buf.receive().await 462 self.rx_buf.receive().await
492 } 463 }
493 464
@@ -517,8 +488,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
517} 488}
518 489
519/// User supplied buffer for RX Buffering 490/// User supplied buffer for RX Buffering
520pub type RxFdBuf<const BUF_SIZE: usize> = 491pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>;
521 Channel<CriticalSectionRawMutex, Result<(FdFrame, Timestamp), BusError>, BUF_SIZE>;
522 492
523/// User supplied buffer for TX buffering 493/// User supplied buffer for TX buffering
524pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; 494pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
@@ -527,7 +497,7 @@ pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFra
527pub 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> {
528 _instance1: PhantomData<T>, 498 _instance1: PhantomData<T>,
529 _instance2: &'d crate::pac::can::Fdcan, 499 _instance2: &'d crate::pac::can::Fdcan,
530 _mode: FdcanOperatingMode, 500 _mode: OperatingMode,
531 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 501 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
532 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 502 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
533} 503}
@@ -535,7 +505,7 @@ pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF
535/// Sender that can be used for sending CAN frames. 505/// Sender that can be used for sending CAN frames.
536#[derive(Copy, Clone)] 506#[derive(Copy, Clone)]
537pub struct BufferedFdCanSender { 507pub struct BufferedFdCanSender {
538 tx_buf: embassy_sync::channel::DynamicSender<'static, FdFrame>, 508 tx_buf: DynamicSender<'static, FdFrame>,
539 waker: fn(), 509 waker: fn(),
540} 510}
541 511
@@ -560,8 +530,7 @@ impl BufferedFdCanSender {
560} 530}
561 531
562/// 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.
563pub type BufferedFdCanReceiver = 533pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>;
564 embassy_sync::channel::DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>;
565 534
566impl<'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>
567 BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> 536 BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
@@ -569,7 +538,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
569 fn new( 538 fn new(
570 _instance1: PhantomData<T>, 539 _instance1: PhantomData<T>,
571 _instance2: &'d crate::pac::can::Fdcan, 540 _instance2: &'d crate::pac::can::Fdcan,
572 _mode: FdcanOperatingMode, 541 _mode: OperatingMode,
573 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 542 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
574 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 543 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
575 ) -> Self { 544 ) -> Self {
@@ -586,10 +555,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
586 fn setup(self) -> Self { 555 fn setup(self) -> Self {
587 // We don't want interrupts being processed while we change modes. 556 // We don't want interrupts being processed while we change modes.
588 critical_section::with(|_| unsafe { 557 critical_section::with(|_| unsafe {
589 let rx_inner = FdBufferedRxInner { 558 let rx_inner = self::common::FdBufferedRxInner {
590 rx_sender: self.rx_buf.sender().into(), 559 rx_sender: self.rx_buf.sender().into(),
591 }; 560 };
592 let tx_inner = FdBufferedTxInner { 561 let tx_inner = self::common::FdBufferedTxInner {
593 tx_receiver: self.tx_buf.receiver().into(), 562 tx_receiver: self.tx_buf.receiver().into(),
594 }; 563 };
595 T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); 564 T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner);
@@ -605,7 +574,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
605 } 574 }
606 575
607 /// Async read frame from RX buffer. 576 /// Async read frame from RX buffer.
608 pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { 577 pub async fn read(&mut self) -> Result<FdEnvelope, BusError> {
609 self.rx_buf.receive().await 578 self.rx_buf.receive().await
610 } 579 }
611 580
@@ -635,25 +604,25 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr
635} 604}
636 605
637/// FDCAN Rx only Instance 606/// FDCAN Rx only Instance
638pub struct FdcanRx<'d, T: Instance> { 607pub struct CanRx<'d, T: Instance> {
639 _instance1: PhantomData<T>, 608 _instance1: PhantomData<T>,
640 _instance2: &'d crate::pac::can::Fdcan, 609 _instance2: &'d crate::pac::can::Fdcan,
641 _mode: FdcanOperatingMode, 610 _mode: OperatingMode,
642} 611}
643 612
644/// FDCAN Tx only Instance 613/// FDCAN Tx only Instance
645pub struct FdcanTx<'d, T: Instance> { 614pub struct CanTx<'d, T: Instance> {
646 config: crate::can::fd::config::FdCanConfig, 615 config: crate::can::fd::config::FdCanConfig,
647 _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>); 616 _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>);
648 _mode: FdcanOperatingMode, 617 _mode: OperatingMode,
649} 618}
650 619
651impl<'c, 'd, T: Instance> FdcanTx<'d, T> { 620impl<'c, 'd, T: Instance> CanTx<'d, T> {
652 /// 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
653 /// 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
654 /// 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
655 /// transmitted, then tries again. 624 /// transmitted, then tries again.
656 pub async fn write(&mut self, frame: &ClassicFrame) -> Option<ClassicFrame> { 625 pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
657 T::state().tx_mode.write::<T>(frame).await 626 T::state().tx_mode.write::<T>(frame).await
658 } 627 }
659 628
@@ -666,36 +635,22 @@ impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
666 } 635 }
667} 636}
668 637
669impl<'c, 'd, T: Instance> FdcanRx<'d, T> { 638impl<'c, 'd, T: Instance> CanRx<'d, T> {
670 /// Returns the next received message frame 639 /// Returns the next received message frame
671 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 640 pub async fn read(&mut self) -> Result<Envelope, BusError> {
672 T::state().rx_mode.read_classic::<T>().await 641 T::state().rx_mode.read_classic::<T>().await
673 } 642 }
674 643
675 /// Returns the next received message frame 644 /// Returns the next received message frame
676 pub async fn read_fd(&mut self) -> Result<(FdFrame, Timestamp), BusError> { 645 pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
677 T::state().rx_mode.read_fd::<T>().await 646 T::state().rx_mode.read_fd::<T>().await
678 } 647 }
679} 648}
680 649
681struct ClassicBufferedRxInner {
682 rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
683}
684struct ClassicBufferedTxInner {
685 tx_receiver: DynamicReceiver<'static, ClassicFrame>,
686}
687
688struct FdBufferedRxInner {
689 rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
690}
691struct FdBufferedTxInner {
692 tx_receiver: DynamicReceiver<'static, FdFrame>,
693}
694
695enum RxMode { 650enum RxMode {
696 NonBuffered(AtomicWaker), 651 NonBuffered(AtomicWaker),
697 ClassicBuffered(ClassicBufferedRxInner), 652 ClassicBuffered(self::common::ClassicBufferedRxInner),
698 FdBuffered(FdBufferedRxInner), 653 FdBuffered(self::common::FdBufferedRxInner),
699} 654}
700 655
701impl RxMode { 656impl RxMode {
@@ -715,18 +670,50 @@ impl RxMode {
715 waker.wake(); 670 waker.wake();
716 } 671 }
717 RxMode::ClassicBuffered(buf) => { 672 RxMode::ClassicBuffered(buf) => {
718 if let Some(result) = self.read::<T, _>() { 673 if let Some(result) = self.try_read::<T>() {
719 let _ = buf.rx_sender.try_send(result); 674 let _ = buf.rx_sender.try_send(result);
720 } 675 }
721 } 676 }
722 RxMode::FdBuffered(buf) => { 677 RxMode::FdBuffered(buf) => {
723 if let Some(result) = self.read::<T, _>() { 678 if let Some(result) = self.try_read_fd::<T>() {
724 let _ = buf.rx_sender.try_send(result); 679 let _ = buf.rx_sender.try_send(result);
725 } 680 }
726 } 681 }
727 } 682 }
728 } 683 }
729 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
730 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>> {
731 if let Some((msg, ts)) = T::registers().read(0) { 718 if let Some((msg, ts)) = T::registers().read(0) {
732 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);
@@ -754,19 +741,25 @@ impl RxMode {
754 .await 741 .await
755 } 742 }
756 743
757 async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { 744 async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> {
758 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 }
759 } 749 }
760 750
761 async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { 751 async fn read_fd<T: Instance>(&self) -> Result<FdEnvelope, BusError> {
762 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 }
763 } 756 }
764} 757}
765 758
766enum TxMode { 759enum TxMode {
767 NonBuffered(AtomicWaker), 760 NonBuffered(AtomicWaker),
768 ClassicBuffered(ClassicBufferedTxInner), 761 ClassicBuffered(self::common::ClassicBufferedTxInner),
769 FdBuffered(FdBufferedTxInner), 762 FdBuffered(self::common::FdBufferedTxInner),
770} 763}
771 764
772impl TxMode { 765impl TxMode {
@@ -804,7 +797,7 @@ impl TxMode {
804 /// 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
805 /// 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
806 /// transmitted, then tries again. 799 /// transmitted, then tries again.
807 async fn write<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> { 800 async fn write<T: Instance>(&self, frame: &Frame) -> Option<Frame> {
808 self.write_generic::<T, _>(frame).await 801 self.write_generic::<T, _>(frame).await
809 } 802 }
810 803
diff --git a/embassy-stm32/src/can/frame.rs b/embassy-stm32/src/can/frame.rs
index 14fc32c51..d2d1f7aa6 100644
--- a/embassy-stm32/src/can/frame.rs
+++ b/embassy-stm32/src/can/frame.rs
@@ -3,6 +3,14 @@ use bit_field::BitField;
3 3
4use crate::can::enums::FrameCreateError; 4use crate::can::enums::FrameCreateError;
5 5
6/// Calculate proper timestamp when available.
7#[cfg(feature = "time")]
8pub type Timestamp = embassy_time::Instant;
9
10/// Raw register timestamp
11#[cfg(not(feature = "time"))]
12pub type Timestamp = u16;
13
6/// CAN Header, without meta data 14/// CAN Header, without meta data
7#[derive(Debug, Copy, Clone)] 15#[derive(Debug, Copy, Clone)]
8pub struct Header { 16pub struct Header {
@@ -136,19 +144,20 @@ impl ClassicData {
136 } 144 }
137} 145}
138 146
139/// Frame with up to 8 bytes of data payload as per Classic CAN 147/// Frame with up to 8 bytes of data payload as per Classic(non-FD) CAN
148/// For CAN-FD support use FdFrame
140#[derive(Debug, Copy, Clone)] 149#[derive(Debug, Copy, Clone)]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))] 150#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142pub struct ClassicFrame { 151pub struct Frame {
143 can_header: Header, 152 can_header: Header,
144 data: ClassicData, 153 data: ClassicData,
145} 154}
146 155
147impl ClassicFrame { 156impl Frame {
148 /// Create a new CAN classic Frame 157 /// Create a new CAN classic Frame
149 pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> { 158 pub fn new(can_header: Header, raw_data: &[u8]) -> Result<Self, FrameCreateError> {
150 let data = ClassicData::new(raw_data)?; 159 let data = ClassicData::new(raw_data)?;
151 Ok(ClassicFrame { can_header, data: data }) 160 Ok(Frame { can_header, data: data })
152 } 161 }
153 162
154 /// Creates a new data frame. 163 /// Creates a new data frame.
@@ -206,9 +215,9 @@ impl ClassicFrame {
206 } 215 }
207} 216}
208 217
209impl embedded_can::Frame for ClassicFrame { 218impl embedded_can::Frame for Frame {
210 fn new(id: impl Into<embedded_can::Id>, raw_data: &[u8]) -> Option<Self> { 219 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); 220 let frameopt = Frame::new(Header::new(id.into(), raw_data.len() as u8, false), raw_data);
212 match frameopt { 221 match frameopt {
213 Ok(frame) => Some(frame), 222 Ok(frame) => Some(frame),
214 Err(_) => None, 223 Err(_) => None,
@@ -216,7 +225,7 @@ impl embedded_can::Frame for ClassicFrame {
216 } 225 }
217 fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> { 226 fn new_remote(id: impl Into<embedded_can::Id>, len: usize) -> Option<Self> {
218 if len <= 8 { 227 if len <= 8 {
219 let frameopt = ClassicFrame::new(Header::new(id.into(), len as u8, true), &[0; 8]); 228 let frameopt = Frame::new(Header::new(id.into(), len as u8, true), &[0; 8]);
220 match frameopt { 229 match frameopt {
221 Ok(frame) => Some(frame), 230 Ok(frame) => Some(frame),
222 Err(_) => None, 231 Err(_) => None,
@@ -245,7 +254,7 @@ impl embedded_can::Frame for ClassicFrame {
245 } 254 }
246} 255}
247 256
248impl CanHeader for ClassicFrame { 257impl CanHeader for Frame {
249 fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> { 258 fn from_header(header: Header, data: &[u8]) -> Result<Self, FrameCreateError> {
250 Self::new(header, data) 259 Self::new(header, data)
251 } 260 }
@@ -255,10 +264,31 @@ impl CanHeader for ClassicFrame {
255 } 264 }
256} 265}
257 266
267/// Contains CAN frame and additional metadata.
268///
269/// Timestamp is available if `time` feature is enabled.
270/// For CAN-FD support use FdEnvelope
271#[derive(Debug, Clone)]
272#[cfg_attr(feature = "defmt", derive(defmt::Format))]
273pub struct Envelope {
274 /// Reception time.
275 pub ts: Timestamp,
276 /// The actual CAN frame.
277 pub frame: Frame,
278}
279
280impl Envelope {
281 /// Convert into a tuple
282 pub fn parts(self) -> (Frame, Timestamp) {
283 (self.frame, self.ts)
284 }
285}
286
258/// Payload of a (FD)CAN data frame. 287/// Payload of a (FD)CAN data frame.
259/// 288///
260/// Contains 0 to 64 Bytes of data. 289/// Contains 0 to 64 Bytes of data.
261#[derive(Debug, Copy, Clone)] 290#[derive(Debug, Copy, Clone)]
291#[cfg_attr(feature = "defmt", derive(defmt::Format))]
262pub struct FdData { 292pub struct FdData {
263 pub(crate) bytes: [u8; 64], 293 pub(crate) bytes: [u8; 64],
264} 294}
@@ -308,6 +338,7 @@ impl FdData {
308 338
309/// Frame with up to 8 bytes of data payload as per Fd CAN 339/// Frame with up to 8 bytes of data payload as per Fd CAN
310#[derive(Debug, Copy, Clone)] 340#[derive(Debug, Copy, Clone)]
341#[cfg_attr(feature = "defmt", derive(defmt::Format))]
311pub struct FdFrame { 342pub struct FdFrame {
312 can_header: Header, 343 can_header: Header,
313 data: FdData, 344 data: FdData,
@@ -410,3 +441,23 @@ impl CanHeader for FdFrame {
410 self.header() 441 self.header()
411 } 442 }
412} 443}
444
445/// Contains CAN FD frame and additional metadata.
446///
447/// Timestamp is available if `time` feature is enabled.
448#[derive(Debug, Clone)]
449#[cfg_attr(feature = "defmt", derive(defmt::Format))]
450pub struct FdEnvelope {
451 /// Reception time.
452 pub ts: Timestamp,
453
454 /// The actual CAN frame.
455 pub frame: FdFrame,
456}
457
458impl FdEnvelope {
459 /// Convert into a tuple
460 pub fn parts(self) -> (FdFrame, Timestamp) {
461 (self.frame, self.ts)
462 }
463}
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/can.rs b/tests/stm32/src/bin/can.rs
index c08c69a3b..74d84c42f 100644
--- a/tests/stm32/src/bin/can.rs
+++ b/tests/stm32/src/bin/can.rs
@@ -6,17 +6,19 @@
6#[path = "../common.rs"] 6#[path = "../common.rs"]
7mod common; 7mod common;
8use common::*; 8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
11use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
12use embassy_stm32::can::bx::filter::Mask32; 11use embassy_stm32::can::bx::filter::Mask32;
13use embassy_stm32::can::bx::{Fifo, Frame, StandardId}; 12use embassy_stm32::can::bx::Fifo;
14use embassy_stm32::can::{Can, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; 13use embassy_stm32::can::{Can, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler};
15use embassy_stm32::gpio::{Input, Pull}; 14use embassy_stm32::gpio::{Input, Pull};
16use embassy_stm32::peripherals::CAN1; 15use embassy_stm32::peripherals::CAN1;
17use embassy_time::{Duration, Instant}; 16use embassy_time::Duration;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
19mod can_common;
20use can_common::*;
21
20bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
21 CAN1_RX0 => Rx0InterruptHandler<CAN1>; 23 CAN1_RX0 => Rx0InterruptHandler<CAN1>;
22 CAN1_RX1 => Rx1InterruptHandler<CAN1>; 24 CAN1_RX1 => Rx1InterruptHandler<CAN1>;
@@ -29,6 +31,11 @@ async fn main(_spawner: Spawner) {
29 let p = embassy_stm32::init(config()); 31 let p = embassy_stm32::init(config());
30 info!("Hello World!"); 32 info!("Hello World!");
31 33
34 let options = TestOptions {
35 max_latency: Duration::from_micros(1200),
36 max_buffered: 2,
37 };
38
32 let can = peri!(p, CAN); 39 let can = peri!(p, CAN);
33 let tx = peri!(p, CAN_TX); 40 let tx = peri!(p, CAN_TX);
34 let mut rx = peri!(p, CAN_RX); 41 let mut rx = peri!(p, CAN_RX);
@@ -58,40 +65,13 @@ async fn main(_spawner: Spawner) {
58 65
59 info!("Can configured"); 66 info!("Can configured");
60 67
61 let mut i: u8 = 0; 68 run_can_tests(&mut can, &options).await;
62 loop {
63 let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), &[i]).unwrap();
64
65 info!("Transmitting frame...");
66 let tx_ts = Instant::now();
67 can.write(&tx_frame).await;
68
69 let envelope = can.read().await.unwrap();
70 info!("Frame received!");
71 69
72 info!("loopback time {}", envelope.ts); 70 // Test again with a split
73 info!("loopback frame {=u8}", envelope.frame.data()[0]); 71 let (mut tx, mut rx) = can.split();
74 72 run_split_can_tests(&mut tx, &mut rx, &options).await;
75 let latency = envelope.ts.saturating_duration_since(tx_ts);
76 info!("loopback latency {} us", latency.as_micros());
77
78 // Theoretical minimum latency is 55us, actual is usually ~80us
79 const MIN_LATENCY: Duration = Duration::from_micros(50);
80 const MAX_LATENCY: Duration = Duration::from_micros(150);
81 assert!(
82 MIN_LATENCY <= latency && latency <= MAX_LATENCY,
83 "{} <= {} <= {}",
84 MIN_LATENCY,
85 latency,
86 MAX_LATENCY
87 );
88
89 i += 1;
90 if i > 10 {
91 break;
92 }
93 }
94 73
95 info!("Test OK"); 74 info!("Test OK");
75
96 cortex_m::asm::bkpt(); 76 cortex_m::asm::bkpt();
97} 77}
diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs
new file mode 100644
index 000000000..4b39269cc
--- /dev/null
+++ b/tests/stm32/src/bin/can_common.rs
@@ -0,0 +1,112 @@
1use defmt::{assert, *};
2use embassy_stm32::can;
3use embassy_time::{Duration, Instant};
4
5#[derive(Clone, Copy, Debug)]
6pub struct TestOptions {
7 pub max_latency: Duration,
8 pub max_buffered: u8,
9}
10
11pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) {
12 let mut i: u8 = 0;
13 loop {
14 //let tx_frame = can::frame::Frame::new_standard(0x123, &[i, 0x12 as u8, 0x34 as u8, 0x56 as u8, 0x78 as u8, 0x9A as u8, 0xBC as u8 ]).unwrap();
15 let tx_frame = can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap();
16
17 //info!("Transmitting frame...");
18 let tx_ts = Instant::now();
19 can.write(&tx_frame).await;
20
21 let (frame, timestamp) = can.read().await.unwrap().parts();
22 //info!("Frame received!");
23
24 // Check data.
25 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
26
27 //info!("loopback time {}", timestamp);
28 //info!("loopback frame {=u8}", frame.data()[0]);
29 let latency = timestamp.saturating_duration_since(tx_ts);
30 info!("loopback latency {} us", latency.as_micros());
31
32 // Theoretical minimum latency is 55us, actual is usually ~80us
33 const MIN_LATENCY: Duration = Duration::from_micros(50);
34 // Was failing at 150 but we are not getting a real time stamp. I'm not
35 // sure if there are other delays
36 assert!(
37 MIN_LATENCY <= latency && latency <= options.max_latency,
38 "{} <= {} <= {}",
39 MIN_LATENCY,
40 latency,
41 options.max_latency
42 );
43
44 i += 1;
45 if i > 5 {
46 break;
47 }
48 }
49
50 // Below here, check that we can receive from both FIFO0 and FIFO1
51 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
52 // in each FIFO so make sure we write enough to fill them both up before reading.
53 for i in 0..options.max_buffered {
54 // Try filling up the RX FIFO0 buffers
55 //let tx_frame = if 0 != (i & 0x01) {
56 let tx_frame = if i < options.max_buffered / 2 {
57 info!("Transmitting standard frame {}", i);
58 can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap()
59 } else {
60 info!("Transmitting extended frame {}", i);
61 can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap()
62 };
63 can.write(&tx_frame).await;
64 }
65
66 // Try and receive all 6 packets
67 for _i in 0..options.max_buffered {
68 let (frame, _ts) = can.read().await.unwrap().parts();
69 match frame.id() {
70 embedded_can::Id::Extended(_id) => {
71 info!("Extended received! {}", frame.data()[0]);
72 //info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
73 }
74 embedded_can::Id::Standard(_id) => {
75 info!("Standard received! {}", frame.data()[0]);
76 //info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
77 }
78 }
79 }
80}
81
82pub async fn run_split_can_tests<'d, T: can::Instance>(
83 tx: &mut can::CanTx<'d, T>,
84 rx: &mut can::CanRx<'d, T>,
85 options: &TestOptions,
86) {
87 for i in 0..options.max_buffered {
88 // Try filling up the RX FIFO0 buffers
89 //let tx_frame = if 0 != (i & 0x01) {
90 let tx_frame = if i < options.max_buffered / 2 {
91 info!("Transmitting standard frame {}", i);
92 can::frame::Frame::new_standard(0x123, &[i; 1]).unwrap()
93 } else {
94 info!("Transmitting extended frame {}", i);
95 can::frame::Frame::new_extended(0x1232344, &[i; 1]).unwrap()
96 };
97 tx.write(&tx_frame).await;
98 }
99
100 // Try and receive all 6 packets
101 for _i in 0..options.max_buffered {
102 let (frame, _ts) = rx.read().await.unwrap().parts();
103 match frame.id() {
104 embedded_can::Id::Extended(_id) => {
105 info!("Extended received! {}", frame.data()[0]);
106 }
107 embedded_can::Id::Standard(_id) => {
108 info!("Standard received! {}", frame.data()[0]);
109 }
110 }
111 }
112}
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
index c7373e294..27bdd038a 100644
--- a/tests/stm32/src/bin/fdcan.rs
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -6,13 +6,15 @@
6#[path = "../common.rs"] 6#[path = "../common.rs"]
7mod common; 7mod common;
8use common::*; 8use common::*;
9use defmt::assert;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
11use embassy_stm32::peripherals::*; 10use embassy_stm32::peripherals::*;
12use embassy_stm32::{bind_interrupts, can, Config}; 11use embassy_stm32::{bind_interrupts, can, Config};
13use embassy_time::{Duration, Instant}; 12use embassy_time::Duration;
14use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
15 14
15mod can_common;
16use can_common::*;
17
16bind_interrupts!(struct Irqs2 { 18bind_interrupts!(struct Irqs2 {
17 FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>; 19 FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>;
18 FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>; 20 FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>;
@@ -22,14 +24,8 @@ bind_interrupts!(struct Irqs1 {
22 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>; 24 FDCAN1_IT1 => can::IT1InterruptHandler<FDCAN1>;
23}); 25});
24 26
25struct TestOptions {
26 config: Config,
27 max_latency: Duration,
28 second_fifo_working: bool,
29}
30
31#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))] 27#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi", feature = "stm32h563zi"))]
32fn options() -> TestOptions { 28fn options() -> (Config, TestOptions) {
33 use embassy_stm32::rcc; 29 use embassy_stm32::rcc;
34 info!("H75 config"); 30 info!("H75 config");
35 let mut c = config(); 31 let mut c = config();
@@ -38,15 +34,17 @@ fn options() -> TestOptions {
38 mode: rcc::HseMode::Oscillator, 34 mode: rcc::HseMode::Oscillator,
39 }); 35 });
40 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 36 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
41 TestOptions { 37 (
42 config: c, 38 c,
43 max_latency: Duration::from_micros(1200), 39 TestOptions {
44 second_fifo_working: false, 40 max_latency: Duration::from_micros(1200),
45 } 41 max_buffered: 3,
42 },
43 )
46} 44}
47 45
48#[cfg(any(feature = "stm32h7a3zi"))] 46#[cfg(any(feature = "stm32h7a3zi"))]
49fn options() -> TestOptions { 47fn options() -> (Config, TestOptions) {
50 use embassy_stm32::rcc; 48 use embassy_stm32::rcc;
51 info!("H7a config"); 49 info!("H7a config");
52 let mut c = config(); 50 let mut c = config();
@@ -55,32 +53,36 @@ fn options() -> TestOptions {
55 mode: rcc::HseMode::Oscillator, 53 mode: rcc::HseMode::Oscillator,
56 }); 54 });
57 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE; 55 c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
58 TestOptions { 56 (
59 config: c, 57 c,
60 max_latency: Duration::from_micros(1200), 58 TestOptions {
61 second_fifo_working: false, 59 max_latency: Duration::from_micros(1200),
62 } 60 max_buffered: 3,
61 },
62 )
63} 63}
64 64
65#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))] 65#[cfg(any(feature = "stm32g491re", feature = "stm32g431cb"))]
66fn options() -> TestOptions { 66fn options() -> (Config, TestOptions) {
67 info!("G4 config"); 67 info!("G4 config");
68 TestOptions { 68 (
69 config: config(), 69 config(),
70 max_latency: Duration::from_micros(500), 70 TestOptions {
71 second_fifo_working: true, 71 max_latency: Duration::from_micros(500),
72 } 72 max_buffered: 6,
73 },
74 )
73} 75}
74 76
75#[embassy_executor::main] 77#[embassy_executor::main]
76async fn main(_spawner: Spawner) { 78async fn main(_spawner: Spawner) {
77 //let peripherals = embassy_stm32::init(config()); 79 //let peripherals = embassy_stm32::init(config());
78 80
79 let options = options(); 81 let (config, options) = options();
80 let peripherals = embassy_stm32::init(options.config); 82 let peripherals = embassy_stm32::init(config);
81 83
82 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs1); 84 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); 85 let mut can2 = can::CanConfigurator::new(peripherals.FDCAN2, peripherals.PB12, peripherals.PB13, Irqs2);
84 86
85 // 250k bps 87 // 250k bps
86 can.set_bitrate(250_000); 88 can.set_bitrate(250_000);
@@ -98,141 +100,16 @@ async fn main(_spawner: Spawner) {
98 let mut can = can.into_internal_loopback_mode(); 100 let mut can = can.into_internal_loopback_mode();
99 let mut can2 = can2.into_internal_loopback_mode(); 101 let mut can2 = can2.into_internal_loopback_mode();
100 102
101 info!("CAN Configured"); 103 run_can_tests(&mut can, &options).await;
104 run_can_tests(&mut can2, &options).await;
102 105
103 let mut i: u8 = 0; 106 info!("CAN Configured");
104 loop {
105 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
106
107 info!("Transmitting frame...");
108 let tx_ts = Instant::now();
109 can.write(&tx_frame).await;
110
111 let (frame, timestamp) = can.read().await.unwrap();
112 info!("Frame received!");
113
114 // Check data.
115 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
116
117 info!("loopback time {}", timestamp);
118 info!("loopback frame {=u8}", frame.data()[0]);
119 let latency = timestamp.saturating_duration_since(tx_ts);
120 info!("loopback latency {} us", latency.as_micros());
121
122 // Theoretical minimum latency is 55us, actual is usually ~80us
123 const MIN_LATENCY: Duration = Duration::from_micros(50);
124 // Was failing at 150 but we are not getting a real time stamp. I'm not
125 // sure if there are other delays
126 assert!(
127 MIN_LATENCY <= latency && latency <= options.max_latency,
128 "{} <= {} <= {}",
129 MIN_LATENCY,
130 latency,
131 options.max_latency
132 );
133
134 i += 1;
135 if i > 10 {
136 break;
137 }
138 }
139
140 let mut i: u8 = 0;
141 loop {
142 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
143
144 info!("Transmitting frame...");
145 let tx_ts = Instant::now();
146 can2.write(&tx_frame).await;
147
148 let (frame, timestamp) = can2.read().await.unwrap();
149 info!("Frame received!");
150
151 //print_regs().await;
152 // Check data.
153 assert!(i == frame.data()[0], "{} == {}", i, frame.data()[0]);
154
155 info!("loopback time {}", timestamp);
156 info!("loopback frame {=u8}", frame.data()[0]);
157 let latency = timestamp.saturating_duration_since(tx_ts);
158 info!("loopback latency {} us", latency.as_micros());
159
160 // Theoretical minimum latency is 55us, actual is usually ~80us
161 const MIN_LATENCY: Duration = Duration::from_micros(50);
162 // Was failing at 150 but we are not getting a real time stamp. I'm not
163 // sure if there are other delays
164 assert!(
165 MIN_LATENCY <= latency && latency <= options.max_latency,
166 "{} <= {} <= {}",
167 MIN_LATENCY,
168 latency,
169 options.max_latency
170 );
171
172 i += 1;
173 if i > 10 {
174 break;
175 }
176 }
177
178 let max_buffered = if options.second_fifo_working { 6 } else { 3 };
179
180 // Below here, check that we can receive from both FIFO0 and FIFO0
181 // Above we configured FIFO1 for extended ID packets. There are only 3 slots
182 // in each FIFO so make sure we write enough to fill them both up before reading.
183 for i in 0..3 {
184 // Try filling up the RX FIFO0 buffers with standard packets
185 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap();
186 info!("Transmitting frame {}", i);
187 can.write(&tx_frame).await;
188 }
189 for i in 3..max_buffered {
190 // Try filling up the RX FIFO0 buffers with extended packets
191 let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
192 info!("Transmitting frame {}", i);
193 can.write(&tx_frame).await;
194 }
195
196 // Try and receive all 6 packets
197 for i in 0..max_buffered {
198 let (frame, _ts) = can.read().await.unwrap();
199 match frame.id() {
200 embedded_can::Id::Extended(id) => {
201 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
202 }
203 embedded_can::Id::Standard(id) => {
204 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
205 }
206 }
207 }
208 107
209 // Test again with a split 108 // Test again with a split
210 let (mut tx, mut rx) = can.split(); 109 let (mut tx, mut rx) = can.split();
211 for i in 0..3 { 110 let (mut tx2, mut rx2) = can2.split();
212 // Try filling up the RX FIFO0 buffers with standard packets 111 run_split_can_tests(&mut tx, &mut rx, &options).await;
213 let tx_frame = can::frame::ClassicFrame::new_standard(0x123, &[i; 1]).unwrap(); 112 run_split_can_tests(&mut tx2, &mut rx2, &options).await;
214 info!("Transmitting frame {}", i);
215 tx.write(&tx_frame).await;
216 }
217 for i in 3..max_buffered {
218 // Try filling up the RX FIFO0 buffers with extended packets
219 let tx_frame = can::frame::ClassicFrame::new_extended(0x1232344, &[i; 1]).unwrap();
220 info!("Transmitting frame {}", i);
221 tx.write(&tx_frame).await;
222 }
223
224 // Try and receive all 6 packets
225 for i in 0..max_buffered {
226 let (frame, _ts) = rx.read().await.unwrap();
227 match frame.id() {
228 embedded_can::Id::Extended(id) => {
229 info!("Extended received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
230 }
231 embedded_can::Id::Standard(id) => {
232 info!("Standard received! {:x} {} {}", id.as_raw(), frame.data()[0], i);
233 }
234 }
235 }
236 113
237 info!("Test OK"); 114 info!("Test OK");
238 cortex_m::asm::bkpt(); 115 cortex_m::asm::bkpt();