aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Schuhen <[email protected]>2024-03-24 07:20:33 +1000
committerCorey Schuhen <[email protected]>2024-03-28 09:32:13 +1000
commit3bdaad39e8955fe52e55c65a834dfc42dc54d676 (patch)
treee69983676ae806ecb092a013a6efdee618615092
parent32065d7719e8dd2f5da7787d4b7edf3109c632ba (diff)
BXCAN: Register access into new Registers struct.
-rw-r--r--embassy-stm32/src/can/bx/mod.rs727
-rw-r--r--embassy-stm32/src/can/bxcan.rs76
-rw-r--r--embassy-stm32/src/can/common.rs12
-rw-r--r--embassy-stm32/src/can/fdcan.rs4
4 files changed, 452 insertions, 367 deletions
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs
index 5ea0471c9..9b6ebf5a4 100644
--- a/embassy-stm32/src/can/bx/mod.rs
+++ b/embassy-stm32/src/can/bx/mod.rs
@@ -43,7 +43,35 @@ pub type Data = crate::can::frame::ClassicData;
43/// CAN Frame 43/// CAN Frame
44pub type Frame = crate::can::frame::ClassicFrame; 44pub type Frame = crate::can::frame::ClassicFrame;
45 45
46use crate::can::_version::Envelope;
46use crate::can::bx::filter::MasterFilters; 47use crate::can::bx::filter::MasterFilters;
48use crate::can::enums::BusError;
49use crate::pac::can::vals::Lec;
50
51#[derive(Debug, Copy, Clone, Eq, PartialEq)]
52pub(crate) enum RxFifo {
53 Fifo0,
54 Fifo1,
55}
56
57trait IntoBusError {
58 fn into_bus_err(self) -> Option<BusError>;
59}
60
61impl IntoBusError for Lec {
62 fn into_bus_err(self) -> Option<BusError> {
63 match self {
64 Lec::STUFF => Some(BusError::Stuff),
65 Lec::FORM => Some(BusError::Form),
66 Lec::ACK => Some(BusError::Acknowledge),
67 Lec::BITRECESSIVE => Some(BusError::BitRecessive),
68 Lec::BITDOMINANT => Some(BusError::BitDominant),
69 Lec::CRC => Some(BusError::Crc),
70 Lec::CUSTOM => Some(BusError::Software),
71 _ => None,
72 }
73 }
74}
47 75
48/// A bxCAN peripheral instance. 76/// A bxCAN peripheral instance.
49/// 77///
@@ -233,6 +261,376 @@ impl PartialOrd for IdReg {
233 } 261 }
234} 262}
235 263
264pub(crate) struct Registers {
265 pub canregs: crate::pac::can::Can,
266}
267
268impl Registers {
269 fn enter_init_mode(&mut self) {
270 self.canregs.mcr().modify(|reg| {
271 reg.set_sleep(false);
272 reg.set_inrq(true);
273 });
274 loop {
275 let msr = self.canregs.msr().read();
276 if !msr.slak() && msr.inak() {
277 break;
278 }
279 }
280 }
281
282 // Leaves initialization mode, enters sleep mode.
283 fn leave_init_mode(&mut self) {
284 self.canregs.mcr().modify(|reg| {
285 reg.set_sleep(true);
286 reg.set_inrq(false);
287 });
288 loop {
289 let msr = self.canregs.msr().read();
290 if msr.slak() && !msr.inak() {
291 break;
292 }
293 }
294 }
295
296 fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
297 let prescaler = u16::from(bt.prescaler) & 0x1FF;
298 let seg1 = u8::from(bt.seg1);
299 let seg2 = u8::from(bt.seg2) & 0x7F;
300 let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F;
301 self.canregs.btr().modify(|reg| {
302 reg.set_brp(prescaler - 1);
303 reg.set_ts(0, seg1 - 1);
304 reg.set_ts(1, seg2 - 1);
305 reg.set_sjw(sync_jump_width - 1);
306 });
307 }
308
309 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
310 pub fn set_silent(&self, enabled: bool) {
311 let mode = match enabled {
312 false => stm32_metapac::can::vals::Silm::NORMAL,
313 true => stm32_metapac::can::vals::Silm::SILENT,
314 };
315 self.canregs.btr().modify(|reg| reg.set_silm(mode));
316 }
317
318 /// Enables or disables automatic retransmission of messages.
319 ///
320 /// If this is enabled, the CAN peripheral will automatically try to retransmit each frame
321 /// until it can be sent. Otherwise, it will try only once to send each frame.
322 ///
323 /// Automatic retransmission is enabled by default.
324 pub fn set_automatic_retransmit(&self, enabled: bool) {
325 self.canregs.mcr().modify(|reg| reg.set_nart(enabled));
326 }
327
328 /// Enables or disables loopback mode: Internally connects the TX and RX
329 /// signals together.
330 pub fn set_loopback(&self, enabled: bool) {
331 self.canregs.btr().modify(|reg| reg.set_lbkm(enabled));
332 }
333
334 /// Configures the automatic wake-up feature.
335 ///
336 /// This is turned off by default.
337 ///
338 /// When turned on, an incoming frame will cause the peripheral to wake up from sleep and
339 /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
340 /// frame.
341 #[allow(dead_code)]
342 pub fn set_automatic_wakeup(&mut self, enabled: bool) {
343 self.canregs.mcr().modify(|reg| reg.set_awum(enabled));
344 }
345
346 /// Leaves initialization mode and enables the peripheral (non-blocking version).
347 ///
348 /// Usually, it is recommended to call [`CanConfig::enable`] instead. This method is only needed
349 /// if you want non-blocking initialization.
350 ///
351 /// If this returns [`WouldBlock`][nb::Error::WouldBlock], the peripheral will enable itself
352 /// in the background. The peripheral is enabled and ready to use when this method returns
353 /// successfully.
354 pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> {
355 let msr = self.canregs.msr().read();
356 if msr.slak() {
357 self.canregs.mcr().modify(|reg| {
358 reg.set_abom(true);
359 reg.set_sleep(false);
360 });
361 Err(nb::Error::WouldBlock)
362 } else {
363 Ok(())
364 }
365 }
366
367 /// Puts the peripheral in a sleep mode to save power.
368 ///
369 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
370 #[allow(dead_code)]
371 pub fn sleep(&mut self) {
372 self.canregs.mcr().modify(|reg| {
373 reg.set_sleep(true);
374 reg.set_inrq(false);
375 });
376 loop {
377 let msr = self.canregs.msr().read();
378 if msr.slak() && !msr.inak() {
379 break;
380 }
381 }
382 }
383
384 /// Disables the CAN interface.
385 ///
386 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
387 /// enter sleep mode.
388 pub fn reset(&self) {
389 self.canregs.mcr().write(|reg| reg.set_reset(true));
390 }
391
392 /// Wakes up from sleep mode.
393 ///
394 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
395 /// frame will cause that interrupt.
396 #[allow(dead_code)]
397 pub fn wakeup(&mut self) {
398 self.canregs.mcr().modify(|reg| {
399 reg.set_sleep(false);
400 reg.set_inrq(false);
401 });
402 loop {
403 let msr = self.canregs.msr().read();
404 if !msr.slak() && !msr.inak() {
405 break;
406 }
407 }
408 }
409
410 pub fn curr_error(&self) -> Option<BusError> {
411 let err = { self.canregs.esr().read() };
412 if err.boff() {
413 return Some(BusError::BusOff);
414 } else if err.epvf() {
415 return Some(BusError::BusPassive);
416 } else if err.ewgf() {
417 return Some(BusError::BusWarning);
418 } else if let Some(err) = err.lec().into_bus_err() {
419 return Some(err);
420 }
421 None
422 }
423
424 /// Puts a CAN frame in a transmit mailbox for transmission on the bus.
425 ///
426 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
427 /// Transmit order is preserved for frames with identical priority.
428 ///
429 /// If all transmit mailboxes are full, and `frame` has a higher priority than the
430 /// lowest-priority message in the transmit mailboxes, transmission of the enqueued frame is
431 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
432 /// [`TransmitStatus::dequeued_frame`].
433 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
434 // Get the index of the next free mailbox or the one with the lowest priority.
435 let tsr = self.canregs.tsr().read();
436 let idx = tsr.code() as usize;
437
438 let frame_is_pending = !tsr.tme(0) || !tsr.tme(1) || !tsr.tme(2);
439 let pending_frame = if frame_is_pending {
440 // High priority frames are transmitted first by the mailbox system.
441 // Frames with identical identifier shall be transmitted in FIFO order.
442 // The controller schedules pending frames of same priority based on the
443 // mailbox index instead. As a workaround check all pending mailboxes
444 // and only accept higher priority frames.
445 self.check_priority(0, frame.id().into())?;
446 self.check_priority(1, frame.id().into())?;
447 self.check_priority(2, frame.id().into())?;
448
449 let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2);
450 if all_frames_are_pending {
451 // No free mailbox is available. This can only happen when three frames with
452 // ascending priority (descending IDs) were requested for transmission and all
453 // of them are blocked by bus traffic with even higher priority.
454 // To prevent a priority inversion abort and replace the lowest priority frame.
455 self.read_pending_mailbox(idx)
456 } else {
457 // There was a free mailbox.
458 None
459 }
460 } else {
461 // All mailboxes are available: Send frame without performing any checks.
462 None
463 };
464
465 self.write_mailbox(idx, frame);
466
467 let mailbox = match idx {
468 0 => Mailbox::Mailbox0,
469 1 => Mailbox::Mailbox1,
470 2 => Mailbox::Mailbox2,
471 _ => unreachable!(),
472 };
473 Ok(TransmitStatus {
474 dequeued_frame: pending_frame,
475 mailbox,
476 })
477 }
478
479 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
480 /// lower priority (higher ID) than the identifier `id`.
481 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> {
482 // Read the pending frame's id to check its priority.
483 assert!(idx < 3);
484 let tir = &self.canregs.tx(idx).tir().read();
485 //let tir = &can.tx[idx].tir.read();
486
487 // Check the priority by comparing the identifiers. But first make sure the
488 // frame has not finished the transmission (`TXRQ` == 0) in the meantime.
489 if tir.txrq() && id <= IdReg::from_register(tir.0) {
490 // There's a mailbox whose priority is higher or equal
491 // the priority of the new frame.
492 return Err(nb::Error::WouldBlock);
493 }
494
495 Ok(())
496 }
497
498 fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
499 debug_assert!(idx < 3);
500
501 let mb = self.canregs.tx(idx);
502 mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
503
504 mb.tdlr()
505 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[0..4].try_into().unwrap()));
506 mb.tdhr()
507 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[4..8].try_into().unwrap()));
508 let id: IdReg = frame.id().into();
509 mb.tir().write(|w| {
510 w.0 = id.0;
511 w.set_txrq(true);
512 });
513 }
514
515 fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
516 if self.abort_by_index(idx) {
517 debug_assert!(idx < 3);
518
519 let mb = self.canregs.tx(idx);
520
521 let id = IdReg(mb.tir().read().0);
522 let mut data = [0xff; 8];
523 data[0..4].copy_from_slice(&mb.tdlr().read().0.to_ne_bytes());
524 data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
525 let len = mb.tdtr().read().dlc();
526
527 Some(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap())
528 } else {
529 // Abort request failed because the frame was already sent (or being sent) on
530 // the bus. All mailboxes are now free. This can happen for small prescaler
531 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
532 // has preempted the execution.
533 None
534 }
535 }
536
537 /// Tries to abort a pending frame. Returns `true` when aborted.
538 fn abort_by_index(&mut self, idx: usize) -> bool {
539 self.canregs.tsr().write(|reg| reg.set_abrq(idx, true));
540
541 // Wait for the abort request to be finished.
542 loop {
543 let tsr = self.canregs.tsr().read();
544 if false == tsr.abrq(idx) {
545 break tsr.txok(idx) == false;
546 }
547 }
548 }
549
550 /// Attempts to abort the sending of a frame that is pending in a mailbox.
551 ///
552 /// If there is no frame in the provided mailbox, or its transmission succeeds before it can be
553 /// aborted, this function has no effect and returns `false`.
554 ///
555 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
556 /// returns `true`.
557 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
558 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous
559 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
560 let tsr = self.canregs.tsr().read();
561 let mailbox_empty = match mailbox {
562 Mailbox::Mailbox0 => tsr.tme(0),
563 Mailbox::Mailbox1 => tsr.tme(1),
564 Mailbox::Mailbox2 => tsr.tme(2),
565 };
566 if mailbox_empty {
567 false
568 } else {
569 self.abort_by_index(mailbox as usize)
570 }
571 }
572
573 /// Returns `true` if no frame is pending for transmission.
574 pub fn is_idle(&self) -> bool {
575 let tsr = self.canregs.tsr().read();
576 tsr.tme(0) && tsr.tme(1) && tsr.tme(2)
577 }
578
579 /// Clears the request complete flag for all mailboxes.
580 pub fn clear_interrupt_flags(&mut self) {
581 self.canregs.tsr().write(|reg| {
582 reg.set_rqcp(0, true);
583 reg.set_rqcp(1, true);
584 reg.set_rqcp(2, true);
585 });
586 }
587
588 pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
589 // Generate timestamp as early as possible
590 #[cfg(feature = "time")]
591 let ts = embassy_time::Instant::now();
592
593 use crate::pac::can::vals::Ide;
594
595 let fifo_idx = match fifo {
596 crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
597 crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
598 };
599 let rfr = self.canregs.rfr(fifo_idx);
600 let fifo = self.canregs.rx(fifo_idx);
601
602 // If there are no pending messages, there is nothing to do
603 if rfr.read().fmp() == 0 {
604 return None;
605 }
606
607 let rir = fifo.rir().read();
608 let id: embedded_can::Id = if rir.ide() == Ide::STANDARD {
609 embedded_can::StandardId::new(rir.stid()).unwrap().into()
610 } else {
611 let stid = (rir.stid() & 0x7FF) as u32;
612 let exid = rir.exid() & 0x3FFFF;
613 let id = (stid << 18) | (exid);
614 embedded_can::ExtendedId::new(id).unwrap().into()
615 };
616 let data_len = fifo.rdtr().read().dlc();
617 let mut data: [u8; 8] = [0; 8];
618 data[0..4].copy_from_slice(&fifo.rdlr().read().0.to_ne_bytes());
619 data[4..8].copy_from_slice(&fifo.rdhr().read().0.to_ne_bytes());
620
621 let frame = Frame::new(Header::new(id, data_len, false), &data).unwrap();
622 let envelope = Envelope {
623 #[cfg(feature = "time")]
624 ts,
625 frame,
626 };
627
628 rfr.modify(|v| v.set_rfom(true));
629
630 Some(envelope)
631 }
632}
633
236/// Configuration proxy returned by [`Can::modify_config`]. 634/// Configuration proxy returned by [`Can::modify_config`].
237#[must_use = "`CanConfig` leaves the peripheral in uninitialized state, call `CanConfig::enable` or explicitly drop the value"] 635#[must_use = "`CanConfig` leaves the peripheral in uninitialized state, call `CanConfig::enable` or explicitly drop the value"]
238pub struct CanConfig<'a, I: Instance> { 636pub struct CanConfig<'a, I: Instance> {
@@ -253,24 +651,20 @@ impl<I: Instance> CanConfig<'_, I> {
253 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` 651 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
254 /// parameter to this method. 652 /// parameter to this method.
255 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self { 653 pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
256 self.can.set_bit_timing(bt); 654 self.can.registers.set_bit_timing(bt);
257 self 655 self
258 } 656 }
259 657
260 /// Enables or disables loopback mode: Internally connects the TX and RX 658 /// Enables or disables loopback mode: Internally connects the TX and RX
261 /// signals together. 659 /// signals together.
262 pub fn set_loopback(self, enabled: bool) -> Self { 660 pub fn set_loopback(self, enabled: bool) -> Self {
263 self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled)); 661 self.can.registers.set_loopback(enabled);
264 self 662 self
265 } 663 }
266 664
267 /// Enables or disables silent mode: Disconnects the TX signal from the pin. 665 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
268 pub fn set_silent(self, enabled: bool) -> Self { 666 pub fn set_silent(self, enabled: bool) -> Self {
269 let mode = match enabled { 667 self.can.registers.set_silent(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 668 self
275 } 669 }
276 670
@@ -281,7 +675,7 @@ impl<I: Instance> CanConfig<'_, I> {
281 /// 675 ///
282 /// Automatic retransmission is enabled by default. 676 /// Automatic retransmission is enabled by default.
283 pub fn set_automatic_retransmit(self, enabled: bool) -> Self { 677 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
284 self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled)); 678 self.can.registers.set_automatic_retransmit(enabled);
285 self 679 self
286 } 680 }
287 681
@@ -292,10 +686,10 @@ impl<I: Instance> CanConfig<'_, I> {
292 /// 686 ///
293 /// If you want to finish configuration without enabling the peripheral, you can call 687 /// If you want to finish configuration without enabling the peripheral, you can call
294 /// [`CanConfig::leave_disabled`] or [`drop`] the [`CanConfig`] instead. 688 /// [`CanConfig::leave_disabled`] or [`drop`] the [`CanConfig`] instead.
295 pub fn enable(mut self) { 689 pub fn enable(self) {
296 self.leave_init_mode(); 690 self.can.registers.leave_init_mode();
297 691
298 match nb::block!(self.can.enable_non_blocking()) { 692 match nb::block!(self.can.registers.enable_non_blocking()) {
299 Ok(()) => {} 693 Ok(()) => {}
300 Err(void) => match void {}, 694 Err(void) => match void {},
301 } 695 }
@@ -308,29 +702,15 @@ impl<I: Instance> CanConfig<'_, I> {
308 /// 702 ///
309 /// Before the [`Can`] instance can be used, you have to enable it by calling 703 /// Before the [`Can`] instance can be used, you have to enable it by calling
310 /// [`Can::enable_non_blocking`]. 704 /// [`Can::enable_non_blocking`].
311 pub fn leave_disabled(mut self) { 705 pub fn leave_disabled(self) {
312 self.leave_init_mode(); 706 self.can.registers.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 });
321 loop {
322 let msr = self.can.canregs.msr().read();
323 if msr.slak() && !msr.inak() {
324 break;
325 }
326 }
327 } 707 }
328} 708}
329 709
330impl<I: Instance> Drop for CanConfig<'_, I> { 710impl<I: Instance> Drop for CanConfig<'_, I> {
331 #[inline] 711 #[inline]
332 fn drop(&mut self) { 712 fn drop(&mut self) {
333 self.leave_init_mode(); 713 self.can.registers.leave_init_mode();
334 } 714 }
335} 715}
336 716
@@ -354,23 +734,19 @@ impl<I: Instance> CanBuilder<I> {
354 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` 734 /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
355 /// parameter to this method. 735 /// parameter to this method.
356 pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self { 736 pub fn set_bit_timing(mut self, bt: crate::can::util::NominalBitTiming) -> Self {
357 self.can.set_bit_timing(bt); 737 self.can.registers.set_bit_timing(bt);
358 self 738 self
359 } 739 }
360 /// Enables or disables loopback mode: Internally connects the TX and RX 740 /// Enables or disables loopback mode: Internally connects the TX and RX
361 /// signals together. 741 /// signals together.
362 pub fn set_loopback(self, enabled: bool) -> Self { 742 pub fn set_loopback(self, enabled: bool) -> Self {
363 self.can.canregs.btr().modify(|reg| reg.set_lbkm(enabled)); 743 self.can.registers.set_loopback(enabled);
364 self 744 self
365 } 745 }
366 746
367 /// Enables or disables silent mode: Disconnects the TX signal from the pin. 747 /// Enables or disables silent mode: Disconnects the TX signal from the pin.
368 pub fn set_silent(self, enabled: bool) -> Self { 748 pub fn set_silent(self, enabled: bool) -> Self {
369 let mode = match enabled { 749 self.can.registers.set_silent(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 750 self
375 } 751 }
376 752
@@ -381,7 +757,7 @@ impl<I: Instance> CanBuilder<I> {
381 /// 757 ///
382 /// Automatic retransmission is enabled by default. 758 /// Automatic retransmission is enabled by default.
383 pub fn set_automatic_retransmit(self, enabled: bool) -> Self { 759 pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
384 self.can.canregs.mcr().modify(|reg| reg.set_nart(enabled)); 760 self.can.registers.set_automatic_retransmit(enabled);
385 self 761 self
386 } 762 }
387 763
@@ -395,7 +771,7 @@ impl<I: Instance> CanBuilder<I> {
395 pub fn enable(mut self) -> Can<I> { 771 pub fn enable(mut self) -> Can<I> {
396 self.leave_init_mode(); 772 self.leave_init_mode();
397 773
398 match nb::block!(self.can.enable_non_blocking()) { 774 match nb::block!(self.can.registers.enable_non_blocking()) {
399 Ok(()) => self.can, 775 Ok(()) => self.can,
400 Err(void) => match void {}, 776 Err(void) => match void {},
401 } 777 }
@@ -415,16 +791,7 @@ impl<I: Instance> CanBuilder<I> {
415 791
416 /// Leaves initialization mode, enters sleep mode. 792 /// Leaves initialization mode, enters sleep mode.
417 fn leave_init_mode(&mut self) { 793 fn leave_init_mode(&mut self) {
418 self.can.canregs.mcr().modify(|reg| { 794 self.can.registers.leave_init_mode();
419 reg.set_sleep(true);
420 reg.set_inrq(false);
421 });
422 loop {
423 let msr = self.can.canregs.msr().read();
424 if msr.slak() && !msr.inak() {
425 break;
426 }
427 }
428 } 795 }
429} 796}
430 797
@@ -432,6 +799,7 @@ impl<I: Instance> CanBuilder<I> {
432pub struct Can<I: Instance> { 799pub struct Can<I: Instance> {
433 instance: I, 800 instance: I,
434 canregs: crate::pac::can::Can, 801 canregs: crate::pac::can::Can,
802 pub(crate) registers: Registers,
435} 803}
436 804
437impl<I> Can<I> 805impl<I> Can<I>
@@ -440,50 +808,25 @@ where
440{ 808{
441 /// Creates a [`CanBuilder`] for constructing a CAN interface. 809 /// Creates a [`CanBuilder`] for constructing a CAN interface.
442 pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> { 810 pub fn builder(instance: I, canregs: crate::pac::can::Can) -> CanBuilder<I> {
443 let can_builder = CanBuilder { 811 let mut can_builder = CanBuilder {
444 can: Can { instance, canregs }, 812 can: Can {
813 instance,
814 canregs,
815 registers: Registers { canregs },
816 },
445 }; 817 };
446 818
447 canregs.mcr().modify(|reg| { 819 can_builder.can.registers.enter_init_mode();
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 820
458 can_builder 821 can_builder
459 } 822 }
460 823
461 fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) {
462 let prescaler = u16::from(bt.prescaler) & 0x1FF;
463 let seg1 = u8::from(bt.seg1);
464 let seg2 = u8::from(bt.seg2) & 0x7F;
465 let sync_jump_width = u8::from(bt.sync_jump_width) & 0x7F;
466 self.canregs.btr().modify(|reg| {
467 reg.set_brp(prescaler - 1);
468 reg.set_ts(0, seg1 - 1);
469 reg.set_ts(1, seg2 - 1);
470 reg.set_sjw(sync_jump_width - 1);
471 });
472 }
473
474 /// Returns a reference to the peripheral instance.
475 ///
476 /// This allows accessing HAL-specific data stored in the instance type.
477 pub fn instance(&mut self) -> &mut I {
478 &mut self.instance
479 }
480
481 /// Disables the CAN interface and returns back the raw peripheral it was created from. 824 /// Disables the CAN interface and returns back the raw peripheral it was created from.
482 /// 825 ///
483 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to 826 /// The peripheral is disabled by setting `RESET` in `CAN_MCR`, which causes the peripheral to
484 /// enter sleep mode. 827 /// enter sleep mode.
485 pub fn free(self) -> I { 828 pub fn free(self) -> I {
486 self.canregs.mcr().write(|reg| reg.set_reset(true)); 829 self.registers.reset();
487 self.instance 830 self.instance
488 } 831 }
489 832
@@ -491,85 +834,11 @@ where
491 /// 834 ///
492 /// Calling this method will enter initialization mode. 835 /// Calling this method will enter initialization mode.
493 pub fn modify_config(&mut self) -> CanConfig<'_, I> { 836 pub fn modify_config(&mut self) -> CanConfig<'_, I> {
494 self.canregs.mcr().modify(|reg| { 837 self.registers.enter_init_mode();
495 reg.set_sleep(false);
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 838
505 CanConfig { can: self } 839 CanConfig { can: self }
506 } 840 }
507 841
508 /// Configures the automatic wake-up feature.
509 ///
510 /// This is turned off by default.
511 ///
512 /// 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
514 /// frame.
515 pub fn set_automatic_wakeup(&mut self, enabled: bool) {
516 self.canregs.mcr().modify(|reg| reg.set_awum(enabled));
517 }
518
519 /// Leaves initialization mode and enables the peripheral (non-blocking version).
520 ///
521 /// Usually, it is recommended to call [`CanConfig::enable`] instead. This method is only needed
522 /// if you want non-blocking initialization.
523 ///
524 /// If this returns [`WouldBlock`][nb::Error::WouldBlock], the peripheral will enable itself
525 /// in the background. The peripheral is enabled and ready to use when this method returns
526 /// successfully.
527 pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> {
528 let msr = self.canregs.msr().read();
529 if msr.slak() {
530 self.canregs.mcr().modify(|reg| {
531 reg.set_abom(true);
532 reg.set_sleep(false);
533 });
534 Err(nb::Error::WouldBlock)
535 } else {
536 Ok(())
537 }
538 }
539
540 /// Puts the peripheral in a sleep mode to save power.
541 ///
542 /// While in sleep mode, an incoming CAN frame will trigger [`Interrupt::Wakeup`] if enabled.
543 pub fn sleep(&mut self) {
544 self.canregs.mcr().modify(|reg| {
545 reg.set_sleep(true);
546 reg.set_inrq(false);
547 });
548 loop {
549 let msr = self.canregs.msr().read();
550 if msr.slak() && !msr.inak() {
551 break;
552 }
553 }
554 }
555
556 /// Wakes up from sleep mode.
557 ///
558 /// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
559 /// frame will cause that interrupt.
560 pub fn wakeup(&mut self) {
561 self.canregs.mcr().modify(|reg| {
562 reg.set_sleep(false);
563 reg.set_inrq(false);
564 });
565 loop {
566 let msr = self.canregs.msr().read();
567 if !msr.slak() && !msr.inak() {
568 break;
569 }
570 }
571 }
572
573 /// Puts a CAN frame in a free transmit mailbox for transmission on the bus. 842 /// Puts a CAN frame in a free transmit mailbox for transmission on the bus.
574 /// 843 ///
575 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]). 844 /// Frames are transmitted to the bus based on their priority (see [`FramePriority`]).
@@ -602,14 +871,12 @@ where
602 unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) } 871 unsafe { Tx::<I>::conjure(self.canregs).abort(mailbox) }
603 } 872 }
604 873
605
606 pub(crate) fn split_by_ref(&mut self) -> (Tx<I>, Rx<I>) { 874 pub(crate) fn split_by_ref(&mut self) -> (Tx<I>, Rx<I>) {
607 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime. 875 // Safety: We take `&mut self` and the return value lifetimes are tied to `self`'s lifetime.
608 let tx = unsafe { Tx::conjure(self.canregs) }; 876 let tx = unsafe { Tx::conjure(self.canregs) };
609 let rx0 = unsafe { Rx::conjure() }; 877 let rx0 = unsafe { Rx::conjure() };
610 (tx, rx0) 878 (tx, rx0)
611 } 879 }
612
613} 880}
614 881
615impl<I: FilterOwner> Can<I> { 882impl<I: FilterOwner> Can<I> {
@@ -625,7 +892,7 @@ impl<I: FilterOwner> Can<I> {
625/// Marker for Tx half 892/// Marker for Tx half
626pub struct Tx<I> { 893pub struct Tx<I> {
627 _can: PhantomData<I>, 894 _can: PhantomData<I>,
628 canregs: crate::pac::can::Can, 895 pub(crate) registers: Registers,
629} 896}
630 897
631impl<I> Tx<I> 898impl<I> Tx<I>
@@ -635,7 +902,7 @@ where
635 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self { 902 unsafe fn conjure(canregs: crate::pac::can::Can) -> Self {
636 Self { 903 Self {
637 _can: PhantomData, 904 _can: PhantomData,
638 canregs, 905 registers: Registers { canregs }, //canregs,
639 } 906 }
640 } 907 }
641 908
@@ -649,120 +916,7 @@ where
649 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as 916 /// cancelled and `frame` is enqueued instead. The frame that was replaced is returned as
650 /// [`TransmitStatus::dequeued_frame`]. 917 /// [`TransmitStatus::dequeued_frame`].
651 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> { 918 pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
652 // Get the index of the next free mailbox or the one with the lowest priority. 919 self.registers.transmit(frame)
653 let tsr = self.canregs.tsr().read();
654 let idx = tsr.code() as usize;
655
656 let frame_is_pending = !tsr.tme(0) || !tsr.tme(1) || !tsr.tme(2);
657 let pending_frame = if frame_is_pending {
658 // High priority frames are transmitted first by the mailbox system.
659 // Frames with identical identifier shall be transmitted in FIFO order.
660 // The controller schedules pending frames of same priority based on the
661 // mailbox index instead. As a workaround check all pending mailboxes
662 // and only accept higher priority frames.
663 self.check_priority(0, frame.id().into())?;
664 self.check_priority(1, frame.id().into())?;
665 self.check_priority(2, frame.id().into())?;
666
667 let all_frames_are_pending = !tsr.tme(0) && !tsr.tme(1) && !tsr.tme(2);
668 if all_frames_are_pending {
669 // No free mailbox is available. This can only happen when three frames with
670 // ascending priority (descending IDs) were requested for transmission and all
671 // of them are blocked by bus traffic with even higher priority.
672 // To prevent a priority inversion abort and replace the lowest priority frame.
673 self.read_pending_mailbox(idx)
674 } else {
675 // There was a free mailbox.
676 None
677 }
678 } else {
679 // All mailboxes are available: Send frame without performing any checks.
680 None
681 };
682
683 self.write_mailbox(idx, frame);
684
685 let mailbox = match idx {
686 0 => Mailbox::Mailbox0,
687 1 => Mailbox::Mailbox1,
688 2 => Mailbox::Mailbox2,
689 _ => unreachable!(),
690 };
691 Ok(TransmitStatus {
692 dequeued_frame: pending_frame,
693 mailbox,
694 })
695 }
696
697 /// Returns `Ok` when the mailbox is free or if it contains pending frame with a
698 /// lower priority (higher ID) than the identifier `id`.
699 fn check_priority(&self, idx: usize, id: IdReg) -> nb::Result<(), Infallible> {
700 // Read the pending frame's id to check its priority.
701 assert!(idx < 3);
702 let tir = &self.canregs.tx(idx).tir().read();
703 //let tir = &can.tx[idx].tir.read();
704
705 // Check the priority by comparing the identifiers. But first make sure the
706 // frame has not finished the transmission (`TXRQ` == 0) in the meantime.
707 if tir.txrq() && id <= IdReg::from_register(tir.0) {
708 // There's a mailbox whose priority is higher or equal
709 // the priority of the new frame.
710 return Err(nb::Error::WouldBlock);
711 }
712
713 Ok(())
714 }
715
716 fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
717 debug_assert!(idx < 3);
718
719 let mb = self.canregs.tx(idx);
720 mb.tdtr().write(|w| w.set_dlc(frame.header().len() as u8));
721
722 mb.tdlr()
723 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[0..4].try_into().unwrap()));
724 mb.tdhr()
725 .write(|w| w.0 = u32::from_ne_bytes(frame.data()[4..8].try_into().unwrap()));
726 let id: IdReg = frame.id().into();
727 mb.tir().write(|w| {
728 w.0 = id.0;
729 w.set_txrq(true);
730 });
731 }
732
733 fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
734 if self.abort_by_index(idx) {
735 debug_assert!(idx < 3);
736
737 let mb = self.canregs.tx(idx);
738
739 let id = IdReg(mb.tir().read().0);
740 let mut data = [0xff; 8];
741 data[0..4].copy_from_slice(&mb.tdlr().read().0.to_ne_bytes());
742 data[4..8].copy_from_slice(&mb.tdhr().read().0.to_ne_bytes());
743 let len = mb.tdtr().read().dlc();
744
745 Some(Frame::new(Header::new(id.id(), len, id.rtr()), &data).unwrap())
746 } else {
747 // Abort request failed because the frame was already sent (or being sent) on
748 // the bus. All mailboxes are now free. This can happen for small prescaler
749 // values (e.g. 1MBit/s bit timing with a source clock of 8MHz) or when an ISR
750 // has preempted the execution.
751 None
752 }
753 }
754
755 /// Tries to abort a pending frame. Returns `true` when aborted.
756 fn abort_by_index(&mut self, idx: usize) -> bool {
757 self.canregs.tsr().write(|reg| reg.set_abrq(idx, true));
758
759 // Wait for the abort request to be finished.
760 loop {
761 let tsr = self.canregs.tsr().read();
762 if false == tsr.abrq(idx) {
763 break tsr.txok(idx) == false;
764 }
765 }
766 } 920 }
767 921
768 /// Attempts to abort the sending of a frame that is pending in a mailbox. 922 /// Attempts to abort the sending of a frame that is pending in a mailbox.
@@ -773,34 +927,17 @@ where
773 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function 927 /// If there is a frame in the provided mailbox, and it is canceled successfully, this function
774 /// returns `true`. 928 /// returns `true`.
775 pub fn abort(&mut self, mailbox: Mailbox) -> bool { 929 pub fn abort(&mut self, mailbox: Mailbox) -> bool {
776 // If the mailbox is empty, the value of TXOKx depends on what happened with the previous 930 self.registers.abort(mailbox)
777 // frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
778 let tsr = self.canregs.tsr().read();
779 let mailbox_empty = match mailbox {
780 Mailbox::Mailbox0 => tsr.tme(0),
781 Mailbox::Mailbox1 => tsr.tme(1),
782 Mailbox::Mailbox2 => tsr.tme(2),
783 };
784 if mailbox_empty {
785 false
786 } else {
787 self.abort_by_index(mailbox as usize)
788 }
789 } 931 }
790 932
791 /// Returns `true` if no frame is pending for transmission. 933 /// Returns `true` if no frame is pending for transmission.
792 pub fn is_idle(&self) -> bool { 934 pub fn is_idle(&self) -> bool {
793 let tsr = self.canregs.tsr().read(); 935 self.registers.is_idle()
794 tsr.tme(0) && tsr.tme(1) && tsr.tme(2)
795 } 936 }
796 937
797 /// Clears the request complete flag for all mailboxes. 938 /// Clears the request complete flag for all mailboxes.
798 pub fn clear_interrupt_flags(&mut self) { 939 pub fn clear_interrupt_flags(&mut self) {
799 self.canregs.tsr().write(|reg| { 940 self.registers.clear_interrupt_flags()
800 reg.set_rqcp(0, true);
801 reg.set_rqcp(1, true);
802 reg.set_rqcp(2, true);
803 });
804 } 941 }
805} 942}
806 943
@@ -814,9 +951,7 @@ where
814 I: Instance, 951 I: Instance,
815{ 952{
816 unsafe fn conjure() -> Self { 953 unsafe fn conjure() -> Self {
817 Self { 954 Self { _can: PhantomData }
818 _can: PhantomData,
819 }
820 } 955 }
821} 956}
822 957
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 9d2b8797e..d865bbe7d 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -14,7 +14,6 @@ use futures::FutureExt;
14 14
15use crate::gpio::AFType; 15use crate::gpio::AFType;
16use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
17use crate::pac::can::vals::{Ide, Lec};
18use crate::rcc::RccPeripheral; 17use crate::rcc::RccPeripheral;
19use crate::{interrupt, peripherals, Peripheral}; 18use crate::{interrupt, peripherals, Peripheral};
20 19
@@ -185,7 +184,7 @@ impl<'d, T: Instance> Can<'d, T> {
185 /// This will wait for 11 consecutive recessive bits (bus idle state). 184 /// 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. 185 /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
187 pub async fn enable(&mut self) { 186 pub async fn enable(&mut self) {
188 while self.enable_non_blocking().is_err() { 187 while self.registers.enable_non_blocking().is_err() {
189 // SCE interrupt is only generated for entering sleep mode, but not leaving. 188 // 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. 189 // Yield to allow other tasks to execute while can bus is initializing.
191 embassy_futures::yield_now().await; 190 embassy_futures::yield_now().await;
@@ -243,52 +242,17 @@ impl<'d, T: Instance> Can<'d, T> {
243 } 242 }
244 243
245 unsafe fn receive_fifo(fifo: RxFifo) { 244 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(); 245 let state = T::state();
251 let regs = T::regs(); 246 let regsisters = crate::can::bx::Registers { canregs: 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 247
259 loop { 248 loop {
260 // If there are no pending messages, there is nothing to do 249 match regsisters.receive_fifo(fifo) {
261 if rfr.read().fmp() == 0 { 250 Some(envelope) => {
262 return; 251 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
263 } 252 let _ = state.rx_queue.try_send(envelope);
264 253 }
265 let rir = fifo.rir().read(); 254 None => return,
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 }; 255 };
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 } 256 }
293 } 257 }
294 258
@@ -297,7 +261,7 @@ impl<'d, T: Instance> Can<'d, T> {
297 /// Useful for doing separate transmit/receive tasks. 261 /// Useful for doing separate transmit/receive tasks.
298 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) { 262 pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) {
299 let (tx, rx) = self.can.split_by_ref(); 263 let (tx, rx) = self.can.split_by_ref();
300 (CanTx { tx }, CanRx { rx}) 264 (CanTx { tx }, CanRx { rx })
301 } 265 }
302} 266}
303 267
@@ -459,10 +423,7 @@ impl<'d, T: Instance> CanRx<'d, T> {
459 } 423 }
460} 424}
461 425
462enum RxFifo { 426use crate::can::bx::RxFifo;
463 Fifo0,
464 Fifo1,
465}
466 427
467impl<'d, T: Instance> Drop for Can<'d, T> { 428impl<'d, T: Instance> Drop for Can<'d, T> {
468 fn drop(&mut self) { 429 fn drop(&mut self) {
@@ -601,21 +562,4 @@ impl Index for crate::can::bx::Mailbox {
601 } 562 }
602} 563}
603 564
604trait IntoBusError {
605 fn into_bus_err(self) -> Option<BusError>;
606}
607 565
608impl IntoBusError for Lec {
609 fn into_bus_err(self) -> Option<BusError> {
610 match self {
611 Lec::STUFF => Some(BusError::Stuff),
612 Lec::FORM => Some(BusError::Form),
613 Lec::ACK => Some(BusError::Acknowledge),
614 Lec::BITRECESSIVE => Some(BusError::BitRecessive),
615 Lec::BITDOMINANT => Some(BusError::BitDominant),
616 Lec::CRC => Some(BusError::Crc),
617 Lec::CUSTOM => Some(BusError::Software),
618 _ => None,
619 }
620 }
621}
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs
index 1de54e5a1..8c9990798 100644
--- a/embassy-stm32/src/can/common.rs
+++ b/embassy-stm32/src/can/common.rs
@@ -1,8 +1,15 @@
1use embassy_sync::channel::{DynamicReceiver, DynamicSender}; 1use embassy_sync::channel::{DynamicReceiver, DynamicSender};
2 2
3use crate::can::_version::frame::*;
4use crate::can::_version::Timestamp;
5use crate::can::_version::enums::*; 3use crate::can::_version::enums::*;
4use crate::can::_version::frame::*;
5
6/// Timestamp for incoming packets. Use Embassy time when enabled.
7#[cfg(feature = "time")]
8pub type Timestamp = embassy_time::Instant;
9
10/// Timestamp for incoming packets.
11#[cfg(not(feature = "time"))]
12pub type Timestamp = u16;
6 13
7pub(crate) struct ClassicBufferedRxInner { 14pub(crate) struct ClassicBufferedRxInner {
8 pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, 15 pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>,
@@ -48,4 +55,3 @@ impl BufferedCanSender {
48/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. 55/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
49pub type BufferedCanReceiver = 56pub type BufferedCanReceiver =
50 embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>; 57 embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>;
51
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index c42c42853..42c9bd9f6 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -25,7 +25,8 @@ use fd::config::*;
25use fd::filter::*; 25use fd::filter::*;
26pub use fd::{config, filter}; 26pub use fd::{config, filter};
27use frame::*; 27use frame::*;
28pub use self::common::{BufferedCanSender, BufferedCanReceiver}; 28
29pub use self::common::{BufferedCanReceiver, BufferedCanSender};
29 30
30/// Timestamp for incoming packets. Use Embassy time when enabled. 31/// Timestamp for incoming packets. Use Embassy time when enabled.
31#[cfg(feature = "time")] 32#[cfg(feature = "time")]
@@ -416,7 +417,6 @@ pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_S
416 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 417 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
417} 418}
418 419
419
420impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> 420impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
421 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> 421 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
422{ 422{