aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Schuhen <[email protected]>2024-03-24 07:27:29 +1000
committerCorey Schuhen <[email protected]>2024-03-28 09:32:13 +1000
commit26c739c2f93252e9dc476d69f591a84d44491787 (patch)
tree246b7dfa883af6b5e53cb3e0979bfd5059a21f75
parent3bdaad39e8955fe52e55c65a834dfc42dc54d676 (diff)
BXCAN: Create RxMode enum and move reader methods into it, laying foundations for different Rx buffering modes.
-rw-r--r--embassy-stm32/src/can/bx/mod.rs12
-rw-r--r--embassy-stm32/src/can/bxcan.rs266
-rw-r--r--embassy-stm32/src/can/common.rs4
-rw-r--r--embassy-stm32/src/can/enums.rs10
4 files changed, 219 insertions, 73 deletions
diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs
index 9b6ebf5a4..c508ef2fe 100644
--- a/embassy-stm32/src/can/bx/mod.rs
+++ b/embassy-stm32/src/can/bx/mod.rs
@@ -406,7 +406,7 @@ impl Registers {
406 } 406 }
407 } 407 }
408 } 408 }
409 409
410 pub fn curr_error(&self) -> Option<BusError> { 410 pub fn curr_error(&self) -> Option<BusError> {
411 let err = { self.canregs.esr().read() }; 411 let err = { self.canregs.esr().read() };
412 if err.boff() { 412 if err.boff() {
@@ -585,6 +585,16 @@ impl Registers {
585 }); 585 });
586 } 586 }
587 587
588 pub fn receive_frame_available(&self) -> bool {
589 if self.canregs.rfr(0).read().fmp() != 0 {
590 true
591 } else if self.canregs.rfr(1).read().fmp() != 0 {
592 true
593 } else {
594 false
595 }
596 }
597
588 pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> { 598 pub fn receive_fifo(&self, fifo: crate::can::_version::bx::RxFifo) -> Option<Envelope> {
589 // Generate timestamp as early as possible 599 // Generate timestamp as early as possible
590 #[cfg(feature = "time")] 600 #[cfg(feature = "time")]
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index d865bbe7d..66f6e7067 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -10,7 +10,6 @@ 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;
@@ -22,6 +21,9 @@ use enums::*;
22pub mod frame; 21pub mod frame;
23pub mod util; 22pub mod util;
24 23
24mod common;
25pub use self::common::{BufferedCanReceiver, BufferedCanSender, Timestamp};
26
25/// Contains CAN frame and additional metadata. 27/// Contains CAN frame and additional metadata.
26/// 28///
27/// Timestamp is available if `time` feature is enabled. 29/// Timestamp is available if `time` feature is enabled.
@@ -59,8 +61,7 @@ pub struct Rx0InterruptHandler<T: Instance> {
59 61
60impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> { 62impl<T: Instance> interrupt::typelevel::Handler<T::RX0Interrupt> for Rx0InterruptHandler<T> {
61 unsafe fn on_interrupt() { 63 unsafe fn on_interrupt() {
62 // info!("rx0 irq"); 64 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo0);
63 Can::<T>::receive_fifo(RxFifo::Fifo0);
64 } 65 }
65} 66}
66 67
@@ -71,8 +72,7 @@ pub struct Rx1InterruptHandler<T: Instance> {
71 72
72impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> { 73impl<T: Instance> interrupt::typelevel::Handler<T::RX1Interrupt> for Rx1InterruptHandler<T> {
73 unsafe fn on_interrupt() { 74 unsafe fn on_interrupt() {
74 // info!("rx1 irq"); 75 T::state().rx_mode.on_interrupt::<T>(RxFifo::Fifo1);
75 Can::<T>::receive_fifo(RxFifo::Fifo1);
76 } 76 }
77} 77}
78 78
@@ -99,16 +99,6 @@ pub struct Can<'d, T: Instance> {
99 can: crate::can::bx::Can<BxcanInstance<'d, T>>, 99 can: crate::can::bx::Can<BxcanInstance<'d, T>>,
100} 100}
101 101
102/// Error returned by `try_read`
103#[derive(Debug)]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105pub enum TryReadError {
106 /// Bus error
107 BusError(BusError),
108 /// Receive buffer is empty
109 Empty,
110}
111
112/// Error returned by `try_write` 102/// Error returned by `try_write`
113#[derive(Debug)] 103#[derive(Debug)]
114#[cfg_attr(feature = "defmt", derive(defmt::Format))] 104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -226,34 +216,19 @@ impl<'d, T: Instance> Can<'d, T> {
226 /// 216 ///
227 /// Returns a tuple of the time the message was received and the message frame 217 /// Returns a tuple of the time the message was received and the message frame
228 pub async fn read(&mut self) -> Result<Envelope, BusError> { 218 pub async fn read(&mut self) -> Result<Envelope, BusError> {
229 self.split().1.read().await 219 T::state().rx_mode.read::<T>().await
230 } 220 }
231 221
232 /// Attempts to read a CAN frame without blocking. 222 /// Attempts to read a CAN frame without blocking.
233 /// 223 ///
234 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 224 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
235 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 225 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
236 self.split().1.try_read() 226 T::state().rx_mode.try_read::<T>()
237 } 227 }
238 228
239 /// Waits while receive queue is empty. 229 /// Waits while receive queue is empty.
240 pub async fn wait_not_empty(&mut self) { 230 pub async fn wait_not_empty(&mut self) {
241 self.split().1.wait_not_empty().await 231 T::state().rx_mode.wait_not_empty::<T>().await
242 }
243
244 unsafe fn receive_fifo(fifo: RxFifo) {
245 let state = T::state();
246 let regsisters = crate::can::bx::Registers { canregs: T::regs() };
247
248 loop {
249 match regsisters.receive_fifo(fifo) {
250 Some(envelope) => {
251 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
252 let _ = state.rx_queue.try_send(envelope);
253 }
254 None => return,
255 };
256 }
257 } 232 }
258 233
259 /// Split the CAN driver into transmit and receive halves. 234 /// Split the CAN driver into transmit and receive halves.
@@ -375,51 +350,95 @@ impl<'d, T: Instance> CanRx<'d, T> {
375 /// 350 ///
376 /// Returns a tuple of the time the message was received and the message frame 351 /// Returns a tuple of the time the message was received and the message frame
377 pub async fn read(&mut self) -> Result<Envelope, BusError> { 352 pub async fn read(&mut self) -> Result<Envelope, BusError> {
378 poll_fn(|cx| { 353 T::state().rx_mode.read::<T>().await
379 T::state().err_waker.register(cx.waker());
380 if let Poll::Ready(envelope) = T::state().rx_queue.receive().poll_unpin(cx) {
381 return Poll::Ready(Ok(envelope));
382 } else if let Some(err) = self.curr_error() {
383 return Poll::Ready(Err(err));
384 }
385
386 Poll::Pending
387 })
388 .await
389 } 354 }
390 355
391 /// Attempts to read a CAN frame without blocking. 356 /// Attempts to read a CAN frame without blocking.
392 /// 357 ///
393 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. 358 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
394 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { 359 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
395 if let Ok(envelope) = T::state().rx_queue.try_receive() { 360 T::state().rx_mode.try_read::<T>()
396 return Ok(envelope); 361 }
397 }
398 362
399 if let Some(err) = self.curr_error() { 363 /// Waits while receive queue is empty.
400 return Err(TryReadError::BusError(err)); 364 pub async fn wait_not_empty(&mut self) {
401 } 365 T::state().rx_mode.wait_not_empty::<T>().await
366 }
367
368 /// Return a buffered instance of driver without CAN FD support. User must supply Buffers
369 pub fn buffered<const RX_BUF_SIZE: usize>(
370 self,
371 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
372 ) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
373 BufferedCanRx::new(self.rx, rxb)
374 }
375}
376
377/// User supplied buffer for RX Buffering
378pub type RxBuf<const BUF_SIZE: usize> =
379 Channel<CriticalSectionRawMutex, Result<(Frame, Timestamp), BusError>, BUF_SIZE>;
402 380
403 Err(TryReadError::Empty) 381/// CAN driver, receive half in Buffered mode.
382pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
383 _rx: crate::can::bx::Rx<BxcanInstance<'d, T>>,
384 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
385}
386
387impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
388 fn new(_rx: crate::can::bx::Rx<BxcanInstance<'d, T>>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
389 BufferedCanRx { _rx, rx_buf }.setup()
390 }
391
392 fn setup(self) -> Self {
393 // We don't want interrupts being processed while we change modes.
394 critical_section::with(|_| unsafe {
395 let rx_inner = self::common::ClassicBufferedRxInner {
396 rx_sender: self.rx_buf.sender().into(),
397 };
398 T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
399 });
400 self
401 }
402
403 /// Async read frame from RX buffer.
404 pub async fn read(&mut self) -> Result<(Frame, Timestamp), BusError> {
405 self.rx_buf.receive().await
406 }
407
408 /// Attempts to read a CAN frame without blocking.
409 ///
410 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
411 pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
412 match &T::state().rx_mode {
413 RxMode::Buffered(_) => {
414 if let Ok(result) = self.rx_buf.try_receive() {
415 match result {
416 Ok((frame, ts)) => Ok(Envelope { ts, frame }),
417 Err(e) => Err(TryReadError::BusError(e)),
418 }
419 } else {
420 let registers = crate::can::bx::Registers { canregs: T::regs() };
421 if let Some(err) = registers.curr_error() {
422 return Err(TryReadError::BusError(err));
423 } else {
424 Err(TryReadError::Empty)
425 }
426 }
427 }
428 _ => {
429 panic!("Bad Mode")
430 }
431 }
404 } 432 }
405 433
406 /// Waits while receive queue is empty. 434 /// Waits while receive queue is empty.
407 pub async fn wait_not_empty(&mut self) { 435 pub async fn wait_not_empty(&mut self) {
408 poll_fn(|cx| T::state().rx_queue.poll_ready_to_receive(cx)).await 436 poll_fn(|cx| self.rx_buf.poll_ready_to_receive(cx)).await
409 } 437 }
410 438
411 fn curr_error(&self) -> Option<BusError> { 439 /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
412 let err = { T::regs().esr().read() }; 440 pub fn reader(&self) -> BufferedCanReceiver {
413 if err.boff() { 441 self.rx_buf.receiver().into()
414 return Some(BusError::BusOff);
415 } else if err.epvf() {
416 return Some(BusError::BusPassive);
417 } else if err.ewgf() {
418 return Some(BusError::BusWarning);
419 } else if let Some(err) = err.lec().into_bus_err() {
420 return Some(err);
421 }
422 None
423 } 442 }
424} 443}
425 444
@@ -448,10 +467,111 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> {
448 } 467 }
449} 468}
450 469
470use crate::can::enums::{BusError, TryReadError};
471
472pub(crate) enum RxMode {
473 NonBuffered(AtomicWaker),
474 Buffered(crate::can::_version::common::ClassicBufferedRxInner),
475}
476
477impl RxMode {
478 pub fn on_interrupt<T: Instance>(&self, fifo: crate::can::_version::bx::RxFifo) {
479 match self {
480 Self::NonBuffered(waker) => {
481 // Disable interrupts until read
482 let fifo_idx = match fifo {
483 crate::can::_version::bx::RxFifo::Fifo0 => 0usize,
484 crate::can::_version::bx::RxFifo::Fifo1 => 1usize,
485 };
486 T::regs().ier().write(|w| {
487 w.set_fmpie(fifo_idx, false);
488 });
489 waker.wake();
490 }
491 Self::Buffered(buf) => {
492 let regsisters = crate::can::bx::Registers { canregs: T::regs() };
493
494 loop {
495 match regsisters.receive_fifo(fifo) {
496 Some(envelope) => {
497 // NOTE: consensus was reached that if rx_queue is full, packets should be dropped
498 let _ = buf.rx_sender.try_send(Ok((envelope.frame, envelope.ts)));
499 }
500 None => return,
501 };
502 }
503 }
504 }
505 }
506
507 pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> {
508 match self {
509 Self::NonBuffered(waker) => {
510 poll_fn(|cx| {
511 T::state().err_waker.register(cx.waker());
512 waker.register(cx.waker());
513 match self.try_read::<T>() {
514 Ok(result) => Poll::Ready(Ok(result)),
515 Err(TryReadError::Empty) => Poll::Pending,
516 Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
517 }
518 })
519 .await
520 }
521 _ => {
522 panic!("Bad Mode")
523 }
524 }
525 }
526 pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
527 match self {
528 Self::NonBuffered(_) => {
529 let registers = crate::can::bx::Registers { canregs: T::regs() };
530 if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo0) {
531 T::regs().ier().write(|w| {
532 w.set_fmpie(0, true);
533 });
534 Ok(msg)
535 } else if let Some(msg) = registers.receive_fifo(super::bx::RxFifo::Fifo1) {
536 T::regs().ier().write(|w| {
537 w.set_fmpie(1, true);
538 });
539 Ok(msg)
540 } else if let Some(err) = registers.curr_error() {
541 Err(TryReadError::BusError(err))
542 } else {
543 Err(TryReadError::Empty)
544 }
545 }
546 _ => {
547 panic!("Bad Mode")
548 }
549 }
550 }
551 pub async fn wait_not_empty<T: Instance>(&self) {
552 match &T::state().rx_mode {
553 Self::NonBuffered(waker) => {
554 poll_fn(|cx| {
555 waker.register(cx.waker());
556 let registers = crate::can::bx::Registers { canregs: T::regs() };
557 if registers.receive_frame_available() {
558 Poll::Ready(())
559 } else {
560 Poll::Pending
561 }
562 })
563 .await
564 }
565 _ => {
566 panic!("Bad Mode")
567 }
568 }
569 }
570}
451struct State { 571struct State {
452 pub tx_waker: AtomicWaker, 572 pub tx_waker: AtomicWaker,
453 pub err_waker: AtomicWaker, 573 pub err_waker: AtomicWaker,
454 pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>, 574 pub(crate) rx_mode: RxMode,
455} 575}
456 576
457impl State { 577impl State {
@@ -459,7 +579,7 @@ impl State {
459 Self { 579 Self {
460 tx_waker: AtomicWaker::new(), 580 tx_waker: AtomicWaker::new(),
461 err_waker: AtomicWaker::new(), 581 err_waker: AtomicWaker::new(),
462 rx_queue: Channel::new(), 582 rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
463 } 583 }
464 } 584 }
465} 585}
@@ -467,6 +587,7 @@ impl State {
467trait SealedInstance { 587trait SealedInstance {
468 fn regs() -> crate::pac::can::Can; 588 fn regs() -> crate::pac::can::Can;
469 fn state() -> &'static State; 589 fn state() -> &'static State;
590 unsafe fn mut_state() -> &'static mut State;
470} 591}
471 592
472/// CAN instance trait. 593/// CAN instance trait.
@@ -495,9 +616,12 @@ foreach_peripheral!(
495 crate::pac::$inst 616 crate::pac::$inst
496 } 617 }
497 618
619 unsafe fn mut_state() -> & 'static mut State {
620 static mut STATE: State = State::new();
621 &mut *core::ptr::addr_of_mut!(STATE)
622 }
498 fn state() -> &'static State { 623 fn state() -> &'static State {
499 static STATE: State = State::new(); 624 unsafe { peripherals::$inst::mut_state() }
500 &STATE
501 } 625 }
502 } 626 }
503 627
@@ -561,5 +685,3 @@ impl Index for crate::can::bx::Mailbox {
561 } 685 }
562 } 686 }
563} 687}
564
565
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs
index 8c9990798..b0d177a6d 100644
--- a/embassy-stm32/src/can/common.rs
+++ b/embassy-stm32/src/can/common.rs
@@ -18,9 +18,13 @@ pub(crate) struct ClassicBufferedTxInner {
18 pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, 18 pub tx_receiver: DynamicReceiver<'static, ClassicFrame>,
19} 19}
20 20
21#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
22
21pub(crate) struct FdBufferedRxInner { 23pub(crate) struct FdBufferedRxInner {
22 pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, 24 pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>,
23} 25}
26
27#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
24pub(crate) struct FdBufferedTxInner { 28pub(crate) struct FdBufferedTxInner {
25 pub tx_receiver: DynamicReceiver<'static, FdFrame>, 29 pub tx_receiver: DynamicReceiver<'static, FdFrame>,
26} 30}
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}