diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-03-06 20:44:48 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-03-06 20:44:48 +0000 |
| commit | 5e9297313641f1a2b4a868e1fe625543da8fc40a (patch) | |
| tree | 4eeda7ee76acbe9b10d1b9b2b7bee3a026d353d3 | |
| parent | aaea056ed16b2fb064a8a4c0985d77336363226e (diff) | |
| parent | e0018c6f4f56cdef286934fb368cd4053c209461 (diff) | |
Merge pull request #2658 from MaxiluxSystems/fdcan-buffered-read-consistent
stm32: fdcan: merge read impls, add setter for TxBufferMode, rename Queue -> Priority
| -rw-r--r-- | embassy-stm32/src/can/fd/config.rs | 19 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 65 |
2 files changed, 50 insertions, 34 deletions
diff --git a/embassy-stm32/src/can/fd/config.rs b/embassy-stm32/src/can/fd/config.rs index adaffe9cc..68161ca50 100644 --- a/embassy-stm32/src/can/fd/config.rs +++ b/embassy-stm32/src/can/fd/config.rs | |||
| @@ -292,14 +292,14 @@ impl Default for GlobalFilter { | |||
| 292 | pub enum TxBufferMode { | 292 | pub enum TxBufferMode { |
| 293 | /// TX FIFO operation - In this mode CAN frames are trasmitted strictly in write order. | 293 | /// TX FIFO operation - In this mode CAN frames are trasmitted strictly in write order. |
| 294 | Fifo, | 294 | Fifo, |
| 295 | /// TX queue operation - In this mode CAN frames are transmitted according to CAN priority. | 295 | /// TX priority queue operation - In this mode CAN frames are transmitted according to CAN priority. |
| 296 | Queue, | 296 | Priority, |
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | impl From<TxBufferMode> for crate::pac::can::vals::Tfqm { | 299 | impl From<TxBufferMode> for crate::pac::can::vals::Tfqm { |
| 300 | fn from(value: TxBufferMode) -> Self { | 300 | fn from(value: TxBufferMode) -> Self { |
| 301 | match value { | 301 | match value { |
| 302 | TxBufferMode::Queue => Self::QUEUE, | 302 | TxBufferMode::Priority => Self::QUEUE, |
| 303 | TxBufferMode::Fifo => Self::FIFO, | 303 | TxBufferMode::Fifo => Self::FIFO, |
| 304 | } | 304 | } |
| 305 | } | 305 | } |
| @@ -308,7 +308,7 @@ impl From<TxBufferMode> for crate::pac::can::vals::Tfqm { | |||
| 308 | impl From<crate::pac::can::vals::Tfqm> for TxBufferMode { | 308 | impl From<crate::pac::can::vals::Tfqm> for TxBufferMode { |
| 309 | fn from(value: crate::pac::can::vals::Tfqm) -> Self { | 309 | fn from(value: crate::pac::can::vals::Tfqm) -> Self { |
| 310 | match value { | 310 | match value { |
| 311 | crate::pac::can::vals::Tfqm::QUEUE => Self::Queue, | 311 | crate::pac::can::vals::Tfqm::QUEUE => Self::Priority, |
| 312 | crate::pac::can::vals::Tfqm::FIFO => Self::Fifo, | 312 | crate::pac::can::vals::Tfqm::FIFO => Self::Fifo, |
| 313 | } | 313 | } |
| 314 | } | 314 | } |
| @@ -354,7 +354,7 @@ pub struct FdCanConfig { | |||
| 354 | pub timestamp_source: TimestampSource, | 354 | pub timestamp_source: TimestampSource, |
| 355 | /// Configures the Global Filter | 355 | /// Configures the Global Filter |
| 356 | pub global_filter: GlobalFilter, | 356 | pub global_filter: GlobalFilter, |
| 357 | /// TX buffer mode (FIFO or queue) | 357 | /// TX buffer mode (FIFO or priority queue) |
| 358 | pub tx_buffer_mode: TxBufferMode, | 358 | pub tx_buffer_mode: TxBufferMode, |
| 359 | } | 359 | } |
| 360 | 360 | ||
| @@ -445,6 +445,13 @@ impl FdCanConfig { | |||
| 445 | self.global_filter = filter; | 445 | self.global_filter = filter; |
| 446 | self | 446 | self |
| 447 | } | 447 | } |
| 448 | |||
| 449 | /// Sets the TX buffer mode (FIFO or priority queue) | ||
| 450 | #[inline] | ||
| 451 | pub const fn set_tx_buffer_mode(mut self, txbm: TxBufferMode) -> Self { | ||
| 452 | self.tx_buffer_mode = txbm; | ||
| 453 | self | ||
| 454 | } | ||
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | impl Default for FdCanConfig { | 457 | impl Default for FdCanConfig { |
| @@ -462,7 +469,7 @@ impl Default for FdCanConfig { | |||
| 462 | clock_divider: ClockDivider::_1, | 469 | clock_divider: ClockDivider::_1, |
| 463 | timestamp_source: TimestampSource::None, | 470 | timestamp_source: TimestampSource::None, |
| 464 | global_filter: GlobalFilter::default(), | 471 | global_filter: GlobalFilter::default(), |
| 465 | tx_buffer_mode: TxBufferMode::Queue, | 472 | tx_buffer_mode: TxBufferMode::Priority, |
| 466 | } | 473 | } |
| 467 | } | 474 | } |
| 468 | } | 475 | } |
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 20d00ccb5..fe8969a5a 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -398,7 +398,8 @@ impl<'d, T: Instance> Fdcan<'d, T> { | |||
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | /// User supplied buffer for RX Buffering | 400 | /// User supplied buffer for RX Buffering |
| 401 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (ClassicFrame, Timestamp), BUF_SIZE>; | 401 | pub type RxBuf<const BUF_SIZE: usize> = |
| 402 | Channel<CriticalSectionRawMutex, Result<(ClassicFrame, Timestamp), BusError>, BUF_SIZE>; | ||
| 402 | 403 | ||
| 403 | /// User supplied buffer for TX buffering | 404 | /// User supplied buffer for TX buffering |
| 404 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; | 405 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; |
| @@ -440,7 +441,8 @@ impl BufferedCanSender { | |||
| 440 | } | 441 | } |
| 441 | 442 | ||
| 442 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 443 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 443 | pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (ClassicFrame, Timestamp)>; | 444 | pub type BufferedCanReceiver = |
| 445 | embassy_sync::channel::DynamicReceiver<'static, Result<(ClassicFrame, Timestamp), BusError>>; | ||
| 444 | 446 | ||
| 445 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 447 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> |
| 446 | BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | 448 | BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> |
| @@ -485,7 +487,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 485 | 487 | ||
| 486 | /// Async read frame from RX buffer. | 488 | /// Async read frame from RX buffer. |
| 487 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { | 489 | pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { |
| 488 | Ok(self.rx_buf.receive().await) | 490 | self.rx_buf.receive().await |
| 489 | } | 491 | } |
| 490 | 492 | ||
| 491 | /// Returns a sender that can be used for sending CAN frames. | 493 | /// Returns a sender that can be used for sending CAN frames. |
| @@ -514,7 +516,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr | |||
| 514 | } | 516 | } |
| 515 | 517 | ||
| 516 | /// User supplied buffer for RX Buffering | 518 | /// User supplied buffer for RX Buffering |
| 517 | pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (FdFrame, Timestamp), BUF_SIZE>; | 519 | pub type RxFdBuf<const BUF_SIZE: usize> = |
| 520 | Channel<CriticalSectionRawMutex, Result<(FdFrame, Timestamp), BusError>, BUF_SIZE>; | ||
| 518 | 521 | ||
| 519 | /// User supplied buffer for TX buffering | 522 | /// User supplied buffer for TX buffering |
| 520 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | 523 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; |
| @@ -556,7 +559,8 @@ impl BufferedFdCanSender { | |||
| 556 | } | 559 | } |
| 557 | 560 | ||
| 558 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 561 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 559 | pub type BufferedFdCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (FdFrame, Timestamp)>; | 562 | pub type BufferedFdCanReceiver = |
| 563 | embassy_sync::channel::DynamicReceiver<'static, Result<(FdFrame, Timestamp), BusError>>; | ||
| 560 | 564 | ||
| 561 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 565 | impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> |
| 562 | BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> | 566 | BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> |
| @@ -601,7 +605,7 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 601 | 605 | ||
| 602 | /// Async read frame from RX buffer. | 606 | /// Async read frame from RX buffer. |
| 603 | pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { | 607 | pub async fn read(&mut self) -> Result<(FdFrame, Timestamp), BusError> { |
| 604 | Ok(self.rx_buf.receive().await) | 608 | self.rx_buf.receive().await |
| 605 | } | 609 | } |
| 606 | 610 | ||
| 607 | /// Returns a sender that can be used for sending CAN frames. | 611 | /// Returns a sender that can be used for sending CAN frames. |
| @@ -685,14 +689,14 @@ pub(crate) mod sealed { | |||
| 685 | use crate::can::frame::{ClassicFrame, FdFrame}; | 689 | use crate::can::frame::{ClassicFrame, FdFrame}; |
| 686 | 690 | ||
| 687 | pub struct ClassicBufferedRxInner { | 691 | pub struct ClassicBufferedRxInner { |
| 688 | pub rx_sender: DynamicSender<'static, (ClassicFrame, Timestamp)>, | 692 | pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, |
| 689 | } | 693 | } |
| 690 | pub struct ClassicBufferedTxInner { | 694 | pub struct ClassicBufferedTxInner { |
| 691 | pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, | 695 | pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, |
| 692 | } | 696 | } |
| 693 | 697 | ||
| 694 | pub struct FdBufferedRxInner { | 698 | pub struct FdBufferedRxInner { |
| 695 | pub rx_sender: DynamicSender<'static, (FdFrame, Timestamp)>, | 699 | pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, |
| 696 | } | 700 | } |
| 697 | pub struct FdBufferedTxInner { | 701 | pub struct FdBufferedTxInner { |
| 698 | pub tx_receiver: DynamicReceiver<'static, FdFrame>, | 702 | pub tx_receiver: DynamicReceiver<'static, FdFrame>, |
| @@ -721,46 +725,51 @@ pub(crate) mod sealed { | |||
| 721 | waker.wake(); | 725 | waker.wake(); |
| 722 | } | 726 | } |
| 723 | RxMode::ClassicBuffered(buf) => { | 727 | RxMode::ClassicBuffered(buf) => { |
| 724 | if let Some(r) = T::registers().read(fifonr) { | 728 | if let Some(result) = self.read::<T, _>() { |
| 725 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); | 729 | let _ = buf.rx_sender.try_send(result); |
| 726 | let _ = buf.rx_sender.try_send((r.0, ts)); | ||
| 727 | } | 730 | } |
| 728 | } | 731 | } |
| 729 | RxMode::FdBuffered(buf) => { | 732 | RxMode::FdBuffered(buf) => { |
| 730 | if let Some(r) = T::registers().read(fifonr) { | 733 | if let Some(result) = self.read::<T, _>() { |
| 731 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, r.1); | 734 | let _ = buf.rx_sender.try_send(result); |
| 732 | let _ = buf.rx_sender.try_send((r.0, ts)); | ||
| 733 | } | 735 | } |
| 734 | } | 736 | } |
| 735 | } | 737 | } |
| 736 | } | 738 | } |
| 737 | 739 | ||
| 738 | async fn read<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { | 740 | fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> { |
| 741 | if let Some((msg, ts)) = T::registers().read(0) { | ||
| 742 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 743 | Some(Ok((msg, ts))) | ||
| 744 | } else if let Some((msg, ts)) = T::registers().read(1) { | ||
| 745 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 746 | Some(Ok((msg, ts))) | ||
| 747 | } else if let Some(err) = T::registers().curr_error() { | ||
| 748 | // TODO: this is probably wrong | ||
| 749 | Some(Err(err)) | ||
| 750 | } else { | ||
| 751 | None | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | async fn read_async<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> { | ||
| 739 | poll_fn(|cx| { | 756 | poll_fn(|cx| { |
| 740 | T::state().err_waker.register(cx.waker()); | 757 | T::state().err_waker.register(cx.waker()); |
| 741 | self.register(cx.waker()); | 758 | self.register(cx.waker()); |
| 742 | 759 | match self.read::<T, _>() { | |
| 743 | if let Some((msg, ts)) = T::registers().read(0) { | 760 | Some(result) => Poll::Ready(result), |
| 744 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | 761 | None => Poll::Pending, |
| 745 | return Poll::Ready(Ok((msg, ts))); | ||
| 746 | } else if let Some((msg, ts)) = T::registers().read(1) { | ||
| 747 | let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); | ||
| 748 | return Poll::Ready(Ok((msg, ts))); | ||
| 749 | } else if let Some(err) = T::registers().curr_error() { | ||
| 750 | // TODO: this is probably wrong | ||
| 751 | return Poll::Ready(Err(err)); | ||
| 752 | } | 762 | } |
| 753 | Poll::Pending | ||
| 754 | }) | 763 | }) |
| 755 | .await | 764 | .await |
| 756 | } | 765 | } |
| 757 | 766 | ||
| 758 | pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { | 767 | pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> { |
| 759 | self.read::<T, _>().await | 768 | self.read_async::<T, _>().await |
| 760 | } | 769 | } |
| 761 | 770 | ||
| 762 | pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { | 771 | pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> { |
| 763 | self.read::<T, _>().await | 772 | self.read_async::<T, _>().await |
| 764 | } | 773 | } |
| 765 | } | 774 | } |
| 766 | 775 | ||
