diff options
| author | Corey Schuhen <[email protected]> | 2024-02-17 18:12:47 +1000 |
|---|---|---|
| committer | Corey Schuhen <[email protected]> | 2024-02-17 18:26:57 +1000 |
| commit | 5ad291b708528b5772d6ebcc9309fbd3f8a002c8 (patch) | |
| tree | d591f9170b2e63f054c85a7650aba70a52dc8c0a | |
| parent | 91c75c92a0e67c93550a163ae62b22a652bf2012 (diff) | |
Add a buffered mode.
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 233 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 97 |
2 files changed, 323 insertions, 7 deletions
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 42ce73ded..3ae330e14 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -5,6 +5,8 @@ use core::task::Poll; | |||
| 5 | 5 | ||
| 6 | pub mod fd; | 6 | pub mod fd; |
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 9 | use embassy_sync::channel::Channel; | ||
| 8 | use fd::config::*; | 10 | use fd::config::*; |
| 9 | use fd::filter::*; | 11 | use fd::filter::*; |
| 10 | 12 | ||
| @@ -49,6 +51,26 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0Interrup | |||
| 49 | 51 | ||
| 50 | match &T::state().tx_mode { | 52 | match &T::state().tx_mode { |
| 51 | sealed::TxMode::NonBuffered(waker) => waker.wake(), | 53 | sealed::TxMode::NonBuffered(waker) => waker.wake(), |
| 54 | sealed::TxMode::ClassicBuffered(buf) => { | ||
| 55 | if !T::registers().tx_queue_is_full() { | ||
| 56 | match buf.tx_receiver.try_receive() { | ||
| 57 | Ok(frame) => { | ||
| 58 | _ = T::registers().write_classic(&frame); | ||
| 59 | } | ||
| 60 | Err(_) => {} | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | sealed::TxMode::FdBuffered(buf) => { | ||
| 65 | if !T::registers().tx_queue_is_full() { | ||
| 66 | match buf.tx_receiver.try_receive() { | ||
| 67 | Ok(frame) => { | ||
| 68 | _ = T::registers().write_fd(&frame); | ||
| 69 | } | ||
| 70 | Err(_) => {} | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 52 | } | 74 | } |
| 53 | } | 75 | } |
| 54 | 76 | ||
| @@ -405,6 +427,179 @@ where | |||
| 405 | ) | 427 | ) |
| 406 | } | 428 | } |
| 407 | 429 | ||
| 430 | /// Return a buffered instance of driver without CAN FD support. User must supply Buffers | ||
| 431 | pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( | ||
| 432 | &self, | ||
| 433 | tx_buf: &'static mut TxBuf<TX_BUF_SIZE>, | ||
| 434 | rxb: &'static mut RxBuf<RX_BUF_SIZE>, | ||
| 435 | ) -> BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> { | ||
| 436 | BufferedCan::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) | ||
| 437 | } | ||
| 438 | |||
| 439 | /// Return a buffered instance of driver with CAN FD support. User must supply Buffers | ||
| 440 | pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( | ||
| 441 | &self, | ||
| 442 | tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>, | ||
| 443 | rxb: &'static mut RxFdBuf<RX_BUF_SIZE>, | ||
| 444 | ) -> BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> { | ||
| 445 | BufferedCanFd::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) | ||
| 446 | } | ||
| 447 | } | ||
| 448 | |||
| 449 | /// User supplied buffer for RX Buffering | ||
| 450 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (ClassicFrame, Timestamp), BUF_SIZE>; | ||
| 451 | |||
| 452 | /// User supplied buffer for TX buffering | ||
| 453 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; | ||
| 454 | |||
| 455 | /// Buffered FDCAN Instance | ||
| 456 | #[allow(dead_code)] | ||
| 457 | pub struct BufferedCan<'d, T: Instance, M: FdcanOperatingMode, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | ||
| 458 | _instance1: PhantomData<T>, | ||
| 459 | _instance2: &'d crate::pac::can::Fdcan, | ||
| 460 | _mode: PhantomData<M>, | ||
| 461 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | ||
| 462 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | ||
| 463 | } | ||
| 464 | |||
| 465 | impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | ||
| 466 | BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 467 | where | ||
| 468 | M: FdcanOperatingMode, | ||
| 469 | { | ||
| 470 | fn new( | ||
| 471 | _instance1: PhantomData<T>, | ||
| 472 | _instance2: &'d crate::pac::can::Fdcan, | ||
| 473 | _mode: PhantomData<M>, | ||
| 474 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | ||
| 475 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | ||
| 476 | ) -> Self { | ||
| 477 | BufferedCan { | ||
| 478 | _instance1, | ||
| 479 | _instance2, | ||
| 480 | _mode, | ||
| 481 | tx_buf, | ||
| 482 | rx_buf, | ||
| 483 | } | ||
| 484 | .setup() | ||
| 485 | } | ||
| 486 | |||
| 487 | fn setup(self) -> Self { | ||
| 488 | // We don't want interrupts being processed while we change modes. | ||
| 489 | critical_section::with(|_| unsafe { | ||
| 490 | let rx_inner = sealed::ClassicBufferedRxInner { | ||
| 491 | rx_sender: self.rx_buf.sender().into(), | ||
| 492 | }; | ||
| 493 | let tx_inner = sealed::ClassicBufferedTxInner { | ||
| 494 | tx_receiver: self.tx_buf.receiver().into(), | ||
| 495 | }; | ||
| 496 | T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner); | ||
| 497 | T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner); | ||
| 498 | }); | ||
| 499 | self | ||
| 500 | } | ||
| 501 | |||
| 502 | /// Async write frame to TX buffer. | ||
| 503 | pub async fn write(&mut self, frame: ClassicFrame) { | ||
| 504 | self.tx_buf.send(frame).await; | ||
| 505 | T::IT0Interrupt::pend(); // Wake for Tx | ||
| 506 | } | ||
| 507 | |||
| 508 | /// Async read frame from RX buffer. | ||
| 509 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { | ||
| 510 | Ok(self.rx_buf.receive().await) | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | ||
| 515 | for BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 516 | where | ||
| 517 | M: FdcanOperatingMode, | ||
| 518 | { | ||
| 519 | fn drop(&mut self) { | ||
| 520 | critical_section::with(|_| unsafe { | ||
| 521 | T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 522 | T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 523 | }); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | /// User supplied buffer for RX Buffering | ||
| 528 | pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (FdFrame, Timestamp), BUF_SIZE>; | ||
| 529 | |||
| 530 | /// User supplied buffer for TX buffering | ||
| 531 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | ||
| 532 | |||
| 533 | /// Buffered FDCAN Instance | ||
| 534 | #[allow(dead_code)] | ||
| 535 | pub struct BufferedCanFd<'d, T: Instance, M: FdcanOperatingMode, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | ||
| 536 | _instance1: PhantomData<T>, | ||
| 537 | _instance2: &'d crate::pac::can::Fdcan, | ||
| 538 | _mode: PhantomData<M>, | ||
| 539 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | ||
| 540 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | ||
| 541 | } | ||
| 542 | |||
| 543 | impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | ||
| 544 | BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 545 | where | ||
| 546 | M: FdcanOperatingMode, | ||
| 547 | { | ||
| 548 | fn new( | ||
| 549 | _instance1: PhantomData<T>, | ||
| 550 | _instance2: &'d crate::pac::can::Fdcan, | ||
| 551 | _mode: PhantomData<M>, | ||
| 552 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | ||
| 553 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | ||
| 554 | ) -> Self { | ||
| 555 | BufferedCanFd { | ||
| 556 | _instance1, | ||
| 557 | _instance2, | ||
| 558 | _mode, | ||
| 559 | tx_buf, | ||
| 560 | rx_buf, | ||
| 561 | } | ||
| 562 | .setup() | ||
| 563 | } | ||
| 564 | |||
| 565 | fn setup(self) -> Self { | ||
| 566 | // We don't want interrupts being processed while we change modes. | ||
| 567 | critical_section::with(|_| unsafe { | ||
| 568 | let rx_inner = sealed::FdBufferedRxInner { | ||
| 569 | rx_sender: self.rx_buf.sender().into(), | ||
| 570 | }; | ||
| 571 | let tx_inner = sealed::FdBufferedTxInner { | ||
| 572 | tx_receiver: self.tx_buf.receiver().into(), | ||
| 573 | }; | ||
| 574 | T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner); | ||
| 575 | T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner); | ||
| 576 | }); | ||
| 577 | self | ||
| 578 | } | ||
| 579 | |||
| 580 | /// Async write frame to TX buffer. | ||
| 581 | pub async fn write(&mut self, frame: FdFrame) { | ||
| 582 | self.tx_buf.send(frame).await; | ||
| 583 | T::IT0Interrupt::pend(); // Wake for Tx | ||
| 584 | } | ||
| 585 | |||
| 586 | /// Async read frame from RX buffer. | ||
| 587 | pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { | ||
| 588 | Ok(self.rx_buf.receive().await) | ||
| 589 | } | ||
| 590 | } | ||
| 591 | |||
| 592 | impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | ||
| 593 | for BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> | ||
| 594 | where | ||
| 595 | M: FdcanOperatingMode, | ||
| 596 | { | ||
| 597 | fn drop(&mut self) { | ||
| 598 | critical_section::with(|_| unsafe { | ||
| 599 | T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 600 | T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 601 | }); | ||
| 602 | } | ||
| 408 | } | 603 | } |
| 409 | 604 | ||
| 410 | /// FDCAN Rx only Instance | 605 | /// FDCAN Rx only Instance |
| @@ -456,18 +651,39 @@ pub(crate) mod sealed { | |||
| 456 | use core::future::poll_fn; | 651 | use core::future::poll_fn; |
| 457 | use core::task::Poll; | 652 | use core::task::Poll; |
| 458 | 653 | ||
| 654 | use embassy_sync::channel::{DynamicReceiver, DynamicSender}; | ||
| 459 | use embassy_sync::waitqueue::AtomicWaker; | 655 | use embassy_sync::waitqueue::AtomicWaker; |
| 460 | 656 | ||
| 461 | use crate::can::_version::{BusError, Timestamp}; | 657 | use crate::can::_version::{BusError, Timestamp}; |
| 462 | use crate::can::frame::{ClassicFrame, FdFrame}; | 658 | use crate::can::frame::{ClassicFrame, FdFrame}; |
| 659 | |||
| 660 | pub struct ClassicBufferedRxInner { | ||
| 661 | pub rx_sender: DynamicSender<'static, (ClassicFrame, Timestamp)>, | ||
| 662 | } | ||
| 663 | pub struct ClassicBufferedTxInner { | ||
| 664 | pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, | ||
| 665 | } | ||
| 666 | |||
| 667 | pub struct FdBufferedRxInner { | ||
| 668 | pub rx_sender: DynamicSender<'static, (FdFrame, Timestamp)>, | ||
| 669 | } | ||
| 670 | pub struct FdBufferedTxInner { | ||
| 671 | pub tx_receiver: DynamicReceiver<'static, FdFrame>, | ||
| 672 | } | ||
| 673 | |||
| 463 | pub enum RxMode { | 674 | pub enum RxMode { |
| 464 | NonBuffered(AtomicWaker), | 675 | NonBuffered(AtomicWaker), |
| 676 | ClassicBuffered(ClassicBufferedRxInner), | ||
| 677 | FdBuffered(FdBufferedRxInner), | ||
| 465 | } | 678 | } |
| 466 | 679 | ||
| 467 | impl RxMode { | 680 | impl RxMode { |
| 468 | pub fn register(&self, arg: &core::task::Waker) { | 681 | pub fn register(&self, arg: &core::task::Waker) { |
| 469 | match self { | 682 | match self { |
| 470 | RxMode::NonBuffered(waker) => waker.register(arg), | 683 | RxMode::NonBuffered(waker) => waker.register(arg), |
| 684 | _ => { | ||
| 685 | panic!("Bad Mode") | ||
| 686 | } | ||
| 471 | } | 687 | } |
| 472 | } | 688 | } |
| 473 | 689 | ||
| @@ -477,6 +693,18 @@ pub(crate) mod sealed { | |||
| 477 | RxMode::NonBuffered(waker) => { | 693 | RxMode::NonBuffered(waker) => { |
| 478 | waker.wake(); | 694 | waker.wake(); |
| 479 | } | 695 | } |
| 696 | RxMode::ClassicBuffered(buf) => { | ||
| 697 | if let Some(r) = T::registers().read_classic(fifonr) { | ||
| 698 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); | ||
| 699 | let _ = buf.rx_sender.try_send((r.0, ts)); | ||
| 700 | } | ||
| 701 | } | ||
| 702 | RxMode::FdBuffered(buf) => { | ||
| 703 | if let Some(r) = T::registers().read_fd(fifonr) { | ||
| 704 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); | ||
| 705 | let _ = buf.rx_sender.try_send((r.0, ts)); | ||
| 706 | } | ||
| 707 | } | ||
| 480 | } | 708 | } |
| 481 | } | 709 | } |
| 482 | 710 | ||
| @@ -523,6 +751,8 @@ pub(crate) mod sealed { | |||
| 523 | 751 | ||
| 524 | pub enum TxMode { | 752 | pub enum TxMode { |
| 525 | NonBuffered(AtomicWaker), | 753 | NonBuffered(AtomicWaker), |
| 754 | ClassicBuffered(ClassicBufferedTxInner), | ||
| 755 | FdBuffered(FdBufferedTxInner), | ||
| 526 | } | 756 | } |
| 527 | 757 | ||
| 528 | impl TxMode { | 758 | impl TxMode { |
| @@ -531,6 +761,9 @@ pub(crate) mod sealed { | |||
| 531 | TxMode::NonBuffered(waker) => { | 761 | TxMode::NonBuffered(waker) => { |
| 532 | waker.register(arg); | 762 | waker.register(arg); |
| 533 | } | 763 | } |
| 764 | _ => { | ||
| 765 | panic!("Bad mode"); | ||
| 766 | } | ||
| 534 | } | 767 | } |
| 535 | } | 768 | } |
| 536 | 769 | ||
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index 5ff4f0ef0..043ca7144 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -5,6 +5,7 @@ use embassy_executor::Spawner; | |||
| 5 | use embassy_stm32::peripherals::*; | 5 | use embassy_stm32::peripherals::*; |
| 6 | use embassy_stm32::{bind_interrupts, can, Config}; | 6 | use embassy_stm32::{bind_interrupts, can, Config}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use static_cell::StaticCell; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 10 | ||
| 10 | bind_interrupts!(struct Irqs { | 11 | bind_interrupts!(struct Irqs { |
| @@ -28,13 +29,17 @@ async fn main(_spawner: Spawner) { | |||
| 28 | // 250k bps | 29 | // 250k bps |
| 29 | can.set_bitrate(250_000); | 30 | can.set_bitrate(250_000); |
| 30 | 31 | ||
| 32 | let use_fd = false; | ||
| 33 | |||
| 31 | // 1M bps | 34 | // 1M bps |
| 32 | can.set_fd_data_bitrate(1_000_000, false); | 35 | if use_fd { |
| 36 | can.set_fd_data_bitrate(1_000_000, false); | ||
| 37 | } | ||
| 33 | 38 | ||
| 34 | info!("Configured"); | 39 | info!("Configured"); |
| 35 | 40 | ||
| 36 | //let mut can = can.into_normal_mode(); | 41 | let mut can = can.into_normal_mode(); |
| 37 | let mut can = can.into_internal_loopback_mode(); | 42 | //let mut can = can.into_internal_loopback_mode(); |
| 38 | 43 | ||
| 39 | let mut i = 0; | 44 | let mut i = 0; |
| 40 | let mut last_read_ts = embassy_time::Instant::now(); | 45 | let mut last_read_ts = embassy_time::Instant::now(); |
| @@ -68,11 +73,17 @@ async fn main(_spawner: Spawner) { | |||
| 68 | } | 73 | } |
| 69 | 74 | ||
| 70 | // Use the FD API's even if we don't get FD packets. | 75 | // Use the FD API's even if we don't get FD packets. |
| 71 | loop { | ||
| 72 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); | ||
| 73 | info!("Writing frame using FD API"); | ||
| 74 | 76 | ||
| 75 | _ = can.write_fd(&frame).await; | 77 | loop { |
| 78 | if use_fd { | ||
| 79 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); | ||
| 80 | info!("Writing frame using FD API"); | ||
| 81 | _ = can.write_fd(&frame).await; | ||
| 82 | } else { | ||
| 83 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 84 | info!("Writing frame using FD API"); | ||
| 85 | _ = can.write_fd(&frame).await; | ||
| 86 | } | ||
| 76 | 87 | ||
| 77 | match can.read_fd().await { | 88 | match can.read_fd().await { |
| 78 | Ok((rx_frame, ts)) => { | 89 | Ok((rx_frame, ts)) => { |
| @@ -96,6 +107,7 @@ async fn main(_spawner: Spawner) { | |||
| 96 | } | 107 | } |
| 97 | } | 108 | } |
| 98 | 109 | ||
| 110 | i = 0; | ||
| 99 | let (mut tx, mut rx) = can.split(); | 111 | let (mut tx, mut rx) = can.split(); |
| 100 | // With split | 112 | // With split |
| 101 | loop { | 113 | loop { |
| @@ -120,5 +132,76 @@ async fn main(_spawner: Spawner) { | |||
| 120 | Timer::after_millis(250).await; | 132 | Timer::after_millis(250).await; |
| 121 | 133 | ||
| 122 | i += 1; | 134 | i += 1; |
| 135 | |||
| 136 | if i > 2 { | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | let can = can::Fdcan::join(tx, rx); | ||
| 142 | |||
| 143 | info!("\n\n\nBuffered\n"); | ||
| 144 | if use_fd { | ||
| 145 | static TX_BUF: StaticCell<can::TxFdBuf<8>> = StaticCell::new(); | ||
| 146 | static RX_BUF: StaticCell<can::RxFdBuf<10>> = StaticCell::new(); | ||
| 147 | let mut can = can.buffered_fd( | ||
| 148 | TX_BUF.init(can::TxFdBuf::<8>::new()), | ||
| 149 | RX_BUF.init(can::RxFdBuf::<10>::new()), | ||
| 150 | ); | ||
| 151 | loop { | ||
| 152 | let frame = can::frame::FdFrame::new_extended(0x123456F, &[i; 16]).unwrap(); | ||
| 153 | info!("Writing frame"); | ||
| 154 | |||
| 155 | _ = can.write(frame).await; | ||
| 156 | |||
| 157 | match can.read().await { | ||
| 158 | Ok((rx_frame, ts)) => { | ||
| 159 | let delta = (ts - last_read_ts).as_millis(); | ||
| 160 | last_read_ts = ts; | ||
| 161 | info!( | ||
| 162 | "Rx: {} {:02x} --- {}ms", | ||
| 163 | rx_frame.header().len(), | ||
| 164 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 165 | delta, | ||
| 166 | ) | ||
| 167 | } | ||
| 168 | Err(_err) => error!("Error in frame"), | ||
| 169 | } | ||
| 170 | |||
| 171 | Timer::after_millis(250).await; | ||
| 172 | |||
| 173 | i += 1; | ||
| 174 | } | ||
| 175 | } else { | ||
| 176 | static TX_BUF: StaticCell<can::TxBuf<8>> = StaticCell::new(); | ||
| 177 | static RX_BUF: StaticCell<can::RxBuf<10>> = StaticCell::new(); | ||
| 178 | let mut can = can.buffered( | ||
| 179 | TX_BUF.init(can::TxBuf::<8>::new()), | ||
| 180 | RX_BUF.init(can::RxBuf::<10>::new()), | ||
| 181 | ); | ||
| 182 | loop { | ||
| 183 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | ||
| 184 | info!("Writing frame"); | ||
| 185 | |||
| 186 | _ = can.write(frame).await; | ||
| 187 | |||
| 188 | match can.read().await { | ||
| 189 | Ok((rx_frame, ts)) => { | ||
| 190 | let delta = (ts - last_read_ts).as_millis(); | ||
| 191 | last_read_ts = ts; | ||
| 192 | info!( | ||
| 193 | "Rx: {} {:02x} --- {}ms", | ||
| 194 | rx_frame.header().len(), | ||
| 195 | rx_frame.data()[0..rx_frame.header().len() as usize], | ||
| 196 | delta, | ||
| 197 | ) | ||
| 198 | } | ||
| 199 | Err(_err) => error!("Error in frame"), | ||
| 200 | } | ||
| 201 | |||
| 202 | Timer::after_millis(250).await; | ||
| 203 | |||
| 204 | i += 1; | ||
| 205 | } | ||
| 123 | } | 206 | } |
| 124 | } | 207 | } |
