diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-03-11 11:21:30 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-03-11 11:21:30 +0000 |
| commit | 0cf951128d8b187821001674cb88e5cbe080a142 (patch) | |
| tree | c719273ae14bf03fedf58f04f274a78234f41128 | |
| parent | 05c664097ddb333c4bfba685ae48f1862e0d5485 (diff) | |
| parent | 424d20727eb3d2b2bda6b6a8f42306a57e93c9f2 (diff) | |
Merge pull request #3956 from cschuhen/stm_can_count_instances_fix_3610
STM32 CAN: Count senders and receivers so that we don't close down early.
| -rw-r--r-- | embassy-stm32/src/can/bxcan/mod.rs | 64 | ||||
| -rw-r--r-- | embassy-stm32/src/can/common.rs | 86 | ||||
| -rw-r--r-- | embassy-stm32/src/can/enums.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 104 |
4 files changed, 199 insertions, 69 deletions
diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 8165364f5..c0b3c730b 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs | |||
| @@ -17,7 +17,7 @@ use self::registers::{Registers, RxFifo}; | |||
| 17 | pub use super::common::{BufferedCanReceiver, BufferedCanSender}; | 17 | pub use super::common::{BufferedCanReceiver, BufferedCanSender}; |
| 18 | use super::frame::{Envelope, Frame}; | 18 | use super::frame::{Envelope, Frame}; |
| 19 | use super::util; | 19 | use super::util; |
| 20 | use crate::can::enums::{BusError, TryReadError}; | 20 | use crate::can::enums::{BusError, InternalOperation, TryReadError}; |
| 21 | use crate::gpio::{AfType, OutputType, Pull, Speed}; | 21 | use crate::gpio::{AfType, OutputType, Pull, Speed}; |
| 22 | use crate::interrupt::typelevel::Interrupt; | 22 | use crate::interrupt::typelevel::Interrupt; |
| 23 | use crate::rcc::{self, RccPeripheral}; | 23 | use crate::rcc::{self, RccPeripheral}; |
| @@ -685,22 +685,18 @@ impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> { | |||
| 685 | 685 | ||
| 686 | /// Returns a sender that can be used for sending CAN frames. | 686 | /// Returns a sender that can be used for sending CAN frames. |
| 687 | pub fn writer(&self) -> BufferedCanSender { | 687 | pub fn writer(&self) -> BufferedCanSender { |
| 688 | (self.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 688 | BufferedCanSender { | 689 | BufferedCanSender { |
| 689 | tx_buf: self.tx_buf.sender().into(), | 690 | tx_buf: self.tx_buf.sender().into(), |
| 690 | waker: self.info.tx_waker, | 691 | waker: self.info.tx_waker, |
| 692 | internal_operation: self.info.internal_operation, | ||
| 691 | } | 693 | } |
| 692 | } | 694 | } |
| 693 | } | 695 | } |
| 694 | 696 | ||
| 695 | impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> { | 697 | impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> { |
| 696 | fn drop(&mut self) { | 698 | fn drop(&mut self) { |
| 697 | critical_section::with(|_| { | 699 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); |
| 698 | let state = self.state as *const State; | ||
| 699 | unsafe { | ||
| 700 | let mut_state = state as *mut State; | ||
| 701 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 702 | } | ||
| 703 | }); | ||
| 704 | } | 700 | } |
| 705 | } | 701 | } |
| 706 | 702 | ||
| @@ -825,7 +821,11 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { | |||
| 825 | 821 | ||
| 826 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 822 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 827 | pub fn reader(&self) -> BufferedCanReceiver { | 823 | pub fn reader(&self) -> BufferedCanReceiver { |
| 828 | self.rx_buf.receiver().into() | 824 | (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); |
| 825 | BufferedCanReceiver { | ||
| 826 | rx_buf: self.rx_buf.receiver().into(), | ||
| 827 | internal_operation: self.info.internal_operation, | ||
| 828 | } | ||
| 829 | } | 829 | } |
| 830 | 830 | ||
| 831 | /// Accesses the filter banks owned by this CAN peripheral. | 831 | /// Accesses the filter banks owned by this CAN peripheral. |
| @@ -839,13 +839,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> { | |||
| 839 | 839 | ||
| 840 | impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> { | 840 | impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> { |
| 841 | fn drop(&mut self) { | 841 | fn drop(&mut self) { |
| 842 | critical_section::with(|_| { | 842 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); |
| 843 | let state = self.state as *const State; | ||
| 844 | unsafe { | ||
| 845 | let mut_state = state as *mut State; | ||
| 846 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 847 | } | ||
| 848 | }); | ||
| 849 | } | 843 | } |
| 850 | } | 844 | } |
| 851 | 845 | ||
| @@ -1048,6 +1042,8 @@ pub(crate) struct State { | |||
| 1048 | pub(crate) rx_mode: RxMode, | 1042 | pub(crate) rx_mode: RxMode, |
| 1049 | pub(crate) tx_mode: TxMode, | 1043 | pub(crate) tx_mode: TxMode, |
| 1050 | pub err_waker: AtomicWaker, | 1044 | pub err_waker: AtomicWaker, |
| 1045 | receiver_instance_count: usize, | ||
| 1046 | sender_instance_count: usize, | ||
| 1051 | } | 1047 | } |
| 1052 | 1048 | ||
| 1053 | impl State { | 1049 | impl State { |
| @@ -1056,6 +1052,8 @@ impl State { | |||
| 1056 | rx_mode: RxMode::NonBuffered(AtomicWaker::new()), | 1052 | rx_mode: RxMode::NonBuffered(AtomicWaker::new()), |
| 1057 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), | 1053 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), |
| 1058 | err_waker: AtomicWaker::new(), | 1054 | err_waker: AtomicWaker::new(), |
| 1055 | receiver_instance_count: 1, | ||
| 1056 | sender_instance_count: 1, | ||
| 1059 | } | 1057 | } |
| 1060 | } | 1058 | } |
| 1061 | } | 1059 | } |
| @@ -1067,6 +1065,7 @@ pub(crate) struct Info { | |||
| 1067 | rx1_interrupt: crate::interrupt::Interrupt, | 1065 | rx1_interrupt: crate::interrupt::Interrupt, |
| 1068 | sce_interrupt: crate::interrupt::Interrupt, | 1066 | sce_interrupt: crate::interrupt::Interrupt, |
| 1069 | tx_waker: fn(), | 1067 | tx_waker: fn(), |
| 1068 | internal_operation: fn(InternalOperation), | ||
| 1070 | 1069 | ||
| 1071 | /// The total number of filter banks available to the instance. | 1070 | /// The total number of filter banks available to the instance. |
| 1072 | /// | 1071 | /// |
| @@ -1079,6 +1078,7 @@ trait SealedInstance { | |||
| 1079 | fn regs() -> crate::pac::can::Can; | 1078 | fn regs() -> crate::pac::can::Can; |
| 1080 | fn state() -> &'static State; | 1079 | fn state() -> &'static State; |
| 1081 | unsafe fn mut_state() -> &'static mut State; | 1080 | unsafe fn mut_state() -> &'static mut State; |
| 1081 | fn internal_operation(val: InternalOperation); | ||
| 1082 | } | 1082 | } |
| 1083 | 1083 | ||
| 1084 | /// CAN instance trait. | 1084 | /// CAN instance trait. |
| @@ -1136,6 +1136,7 @@ foreach_peripheral!( | |||
| 1136 | rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ, | 1136 | rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ, |
| 1137 | sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, | 1137 | sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, |
| 1138 | tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, | 1138 | tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, |
| 1139 | internal_operation: peripherals::$inst::internal_operation, | ||
| 1139 | num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, | 1140 | num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, |
| 1140 | }; | 1141 | }; |
| 1141 | &INFO | 1142 | &INFO |
| @@ -1151,6 +1152,37 @@ foreach_peripheral!( | |||
| 1151 | fn state() -> &'static State { | 1152 | fn state() -> &'static State { |
| 1152 | unsafe { peripherals::$inst::mut_state() } | 1153 | unsafe { peripherals::$inst::mut_state() } |
| 1153 | } | 1154 | } |
| 1155 | |||
| 1156 | |||
| 1157 | fn internal_operation(val: InternalOperation) { | ||
| 1158 | critical_section::with(|_| { | ||
| 1159 | //let state = self.state as *const State; | ||
| 1160 | unsafe { | ||
| 1161 | //let mut_state = state as *mut State; | ||
| 1162 | let mut_state = peripherals::$inst::mut_state(); | ||
| 1163 | match val { | ||
| 1164 | InternalOperation::NotifySenderCreated => { | ||
| 1165 | mut_state.sender_instance_count += 1; | ||
| 1166 | } | ||
| 1167 | InternalOperation::NotifySenderDestroyed => { | ||
| 1168 | mut_state.sender_instance_count -= 1; | ||
| 1169 | if ( 0 == mut_state.sender_instance_count) { | ||
| 1170 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 1171 | } | ||
| 1172 | } | ||
| 1173 | InternalOperation::NotifyReceiverCreated => { | ||
| 1174 | mut_state.receiver_instance_count += 1; | ||
| 1175 | } | ||
| 1176 | InternalOperation::NotifyReceiverDestroyed => { | ||
| 1177 | mut_state.receiver_instance_count -= 1; | ||
| 1178 | if ( 0 == mut_state.receiver_instance_count) { | ||
| 1179 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | }); | ||
| 1185 | } | ||
| 1154 | } | 1186 | } |
| 1155 | 1187 | ||
| 1156 | impl Instance for peripherals::$inst { | 1188 | impl Instance for peripherals::$inst { |
diff --git a/embassy-stm32/src/can/common.rs b/embassy-stm32/src/can/common.rs index a54b54f6e..e12111910 100644 --- a/embassy-stm32/src/can/common.rs +++ b/embassy-stm32/src/can/common.rs | |||
| @@ -22,22 +22,22 @@ pub(crate) struct FdBufferedTxInner { | |||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | /// Sender that can be used for sending CAN frames. | 24 | /// Sender that can be used for sending CAN frames. |
| 25 | #[derive(Copy, Clone)] | 25 | pub struct BufferedSender<'ch, FRAME> { |
| 26 | pub struct BufferedCanSender { | 26 | pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'ch, FRAME>, |
| 27 | pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, Frame>, | ||
| 28 | pub(crate) waker: fn(), | 27 | pub(crate) waker: fn(), |
| 28 | pub(crate) internal_operation: fn(InternalOperation), | ||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | impl BufferedCanSender { | 31 | impl<'ch, FRAME> BufferedSender<'ch, FRAME> { |
| 32 | /// Async write frame to TX buffer. | 32 | /// Async write frame to TX buffer. |
| 33 | pub fn try_write(&mut self, frame: Frame) -> Result<(), embassy_sync::channel::TrySendError<Frame>> { | 33 | pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError<FRAME>> { |
| 34 | self.tx_buf.try_send(frame)?; | 34 | self.tx_buf.try_send(frame)?; |
| 35 | (self.waker)(); | 35 | (self.waker)(); |
| 36 | Ok(()) | 36 | Ok(()) |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /// Async write frame to TX buffer. | 39 | /// Async write frame to TX buffer. |
| 40 | pub async fn write(&mut self, frame: Frame) { | 40 | pub async fn write(&mut self, frame: FRAME) { |
| 41 | self.tx_buf.send(frame).await; | 41 | self.tx_buf.send(frame).await; |
| 42 | (self.waker)(); | 42 | (self.waker)(); |
| 43 | } | 43 | } |
| @@ -48,5 +48,77 @@ impl BufferedCanSender { | |||
| 48 | } | 48 | } |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> { | ||
| 52 | fn clone(&self) -> Self { | ||
| 53 | (self.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 54 | Self { | ||
| 55 | tx_buf: self.tx_buf, | ||
| 56 | waker: self.waker, | ||
| 57 | internal_operation: self.internal_operation, | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | impl<'ch, FRAME> Drop for BufferedSender<'ch, FRAME> { | ||
| 63 | fn drop(&mut self) { | ||
| 64 | (self.internal_operation)(InternalOperation::NotifySenderDestroyed); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Sender that can be used for sending Classic CAN frames. | ||
| 69 | pub type BufferedCanSender = BufferedSender<'static, Frame>; | ||
| 70 | |||
| 51 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 71 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 52 | pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, Result<Envelope, BusError>>; | 72 | pub struct BufferedReceiver<'ch, ENVELOPE> { |
| 73 | pub(crate) rx_buf: embassy_sync::channel::DynamicReceiver<'ch, Result<ENVELOPE, BusError>>, | ||
| 74 | pub(crate) internal_operation: fn(InternalOperation), | ||
| 75 | } | ||
| 76 | |||
| 77 | impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> { | ||
| 78 | /// Receive the next frame. | ||
| 79 | /// | ||
| 80 | /// See [`Channel::receive()`]. | ||
| 81 | pub fn receive(&self) -> embassy_sync::channel::DynamicReceiveFuture<'_, Result<ENVELOPE, BusError>> { | ||
| 82 | self.rx_buf.receive() | ||
| 83 | } | ||
| 84 | |||
| 85 | /// Attempt to immediately receive the next frame. | ||
| 86 | /// | ||
| 87 | /// See [`Channel::try_receive()`] | ||
| 88 | pub fn try_receive(&self) -> Result<Result<ENVELOPE, BusError>, embassy_sync::channel::TryReceiveError> { | ||
| 89 | self.rx_buf.try_receive() | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Allows a poll_fn to poll until the channel is ready to receive | ||
| 93 | /// | ||
| 94 | /// See [`Channel::poll_ready_to_receive()`] | ||
| 95 | pub fn poll_ready_to_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> { | ||
| 96 | self.rx_buf.poll_ready_to_receive(cx) | ||
| 97 | } | ||
| 98 | |||
| 99 | /// Poll the channel for the next frame | ||
| 100 | /// | ||
| 101 | /// See [`Channel::poll_receive()`] | ||
| 102 | pub fn poll_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<Result<ENVELOPE, BusError>> { | ||
| 103 | self.rx_buf.poll_receive(cx) | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> { | ||
| 108 | fn clone(&self) -> Self { | ||
| 109 | (self.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 110 | Self { | ||
| 111 | rx_buf: self.rx_buf, | ||
| 112 | internal_operation: self.internal_operation, | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | impl<'ch, ENVELOPE> Drop for BufferedReceiver<'ch, ENVELOPE> { | ||
| 118 | fn drop(&mut self) { | ||
| 119 | (self.internal_operation)(InternalOperation::NotifyReceiverDestroyed); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | /// A BufferedCanReceiver for Classic CAN frames. | ||
| 124 | pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>; | ||
diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs index a5cca424d..97cb47640 100644 --- a/embassy-stm32/src/can/enums.rs +++ b/embassy-stm32/src/can/enums.rs | |||
| @@ -68,3 +68,17 @@ pub enum TryReadError { | |||
| 68 | /// Receive buffer is empty | 68 | /// Receive buffer is empty |
| 69 | Empty, | 69 | Empty, |
| 70 | } | 70 | } |
| 71 | |||
| 72 | /// Internal Operation | ||
| 73 | #[derive(Debug)] | ||
| 74 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 75 | pub enum InternalOperation { | ||
| 76 | /// Notify receiver created | ||
| 77 | NotifyReceiverCreated, | ||
| 78 | /// Notify receiver destroyed | ||
| 79 | NotifyReceiverDestroyed, | ||
| 80 | /// Notify sender created | ||
| 81 | NotifySenderCreated, | ||
| 82 | /// Notify sender destroyed | ||
| 83 | NotifySenderDestroyed, | ||
| 84 | } | ||
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index c549313f3..f950b6f99 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -6,7 +6,7 @@ use core::task::Poll; | |||
| 6 | use embassy_hal_internal::interrupt::InterruptExt; | 6 | use embassy_hal_internal::interrupt::InterruptExt; |
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 9 | use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; | 9 | use embassy_sync::channel::Channel; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | 11 | ||
| 12 | use crate::can::fd::peripheral::Registers; | 12 | use crate::can::fd::peripheral::Registers; |
| @@ -478,28 +478,28 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, | |||
| 478 | 478 | ||
| 479 | /// Returns a sender that can be used for sending CAN frames. | 479 | /// Returns a sender that can be used for sending CAN frames. |
| 480 | pub fn writer(&self) -> BufferedCanSender { | 480 | pub fn writer(&self) -> BufferedCanSender { |
| 481 | (self.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 481 | BufferedCanSender { | 482 | BufferedCanSender { |
| 482 | tx_buf: self.tx_buf.sender().into(), | 483 | tx_buf: self.tx_buf.sender().into(), |
| 483 | waker: self.info.tx_waker, | 484 | waker: self.info.tx_waker, |
| 485 | internal_operation: self.info.internal_operation, | ||
| 484 | } | 486 | } |
| 485 | } | 487 | } |
| 486 | 488 | ||
| 487 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 489 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 488 | pub fn reader(&self) -> BufferedCanReceiver { | 490 | pub fn reader(&self) -> BufferedCanReceiver { |
| 489 | self.rx_buf.receiver().into() | 491 | (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); |
| 492 | BufferedCanReceiver { | ||
| 493 | rx_buf: self.rx_buf.receiver().into(), | ||
| 494 | internal_operation: self.info.internal_operation, | ||
| 495 | } | ||
| 490 | } | 496 | } |
| 491 | } | 497 | } |
| 492 | 498 | ||
| 493 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { | 499 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 494 | fn drop(&mut self) { | 500 | fn drop(&mut self) { |
| 495 | critical_section::with(|_| { | 501 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); |
| 496 | let state = self.state as *const State; | 502 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); |
| 497 | unsafe { | ||
| 498 | let mut_state = state as *mut State; | ||
| 499 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 500 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 501 | } | ||
| 502 | }); | ||
| 503 | } | 503 | } |
| 504 | } | 504 | } |
| 505 | 505 | ||
| @@ -509,35 +509,11 @@ pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Resul | |||
| 509 | /// User supplied buffer for TX buffering | 509 | /// User supplied buffer for TX buffering |
| 510 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | 510 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; |
| 511 | 511 | ||
| 512 | /// Sender that can be used for sending CAN frames. | 512 | /// Sender that can be used for sending Classic CAN frames. |
| 513 | #[derive(Copy, Clone)] | 513 | pub type BufferedFdCanSender = super::common::BufferedSender<'static, FdFrame>; |
| 514 | pub struct BufferedFdCanSender { | ||
| 515 | tx_buf: DynamicSender<'static, FdFrame>, | ||
| 516 | waker: fn(), | ||
| 517 | } | ||
| 518 | |||
| 519 | impl BufferedFdCanSender { | ||
| 520 | /// Async write frame to TX buffer. | ||
| 521 | pub fn try_write(&mut self, frame: FdFrame) -> Result<(), embassy_sync::channel::TrySendError<FdFrame>> { | ||
| 522 | self.tx_buf.try_send(frame)?; | ||
| 523 | (self.waker)(); | ||
| 524 | Ok(()) | ||
| 525 | } | ||
| 526 | |||
| 527 | /// Async write frame to TX buffer. | ||
| 528 | pub async fn write(&mut self, frame: FdFrame) { | ||
| 529 | self.tx_buf.send(frame).await; | ||
| 530 | (self.waker)(); | ||
| 531 | } | ||
| 532 | |||
| 533 | /// Allows a poll_fn to poll until the channel is ready to write | ||
| 534 | pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> { | ||
| 535 | self.tx_buf.poll_ready_to_send(cx) | ||
| 536 | } | ||
| 537 | } | ||
| 538 | 514 | ||
| 539 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 515 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 540 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>; | 516 | pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnvelope>; |
| 541 | 517 | ||
| 542 | /// Buffered FDCAN Instance | 518 | /// Buffered FDCAN Instance |
| 543 | pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { | 519 | pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| @@ -608,28 +584,28 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' | |||
| 608 | 584 | ||
| 609 | /// Returns a sender that can be used for sending CAN frames. | 585 | /// Returns a sender that can be used for sending CAN frames. |
| 610 | pub fn writer(&self) -> BufferedFdCanSender { | 586 | pub fn writer(&self) -> BufferedFdCanSender { |
| 587 | (self.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 611 | BufferedFdCanSender { | 588 | BufferedFdCanSender { |
| 612 | tx_buf: self.tx_buf.sender().into(), | 589 | tx_buf: self.tx_buf.sender().into(), |
| 613 | waker: self.info.tx_waker, | 590 | waker: self.info.tx_waker, |
| 591 | internal_operation: self.info.internal_operation, | ||
| 614 | } | 592 | } |
| 615 | } | 593 | } |
| 616 | 594 | ||
| 617 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 595 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 618 | pub fn reader(&self) -> BufferedFdCanReceiver { | 596 | pub fn reader(&self) -> BufferedFdCanReceiver { |
| 619 | self.rx_buf.receiver().into() | 597 | (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); |
| 598 | BufferedFdCanReceiver { | ||
| 599 | rx_buf: self.rx_buf.receiver().into(), | ||
| 600 | internal_operation: self.info.internal_operation, | ||
| 601 | } | ||
| 620 | } | 602 | } |
| 621 | } | 603 | } |
| 622 | 604 | ||
| 623 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { | 605 | impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> { |
| 624 | fn drop(&mut self) { | 606 | fn drop(&mut self) { |
| 625 | critical_section::with(|_| { | 607 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); |
| 626 | let state = self.state as *const State; | 608 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); |
| 627 | unsafe { | ||
| 628 | let mut_state = state as *mut State; | ||
| 629 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 630 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 631 | } | ||
| 632 | }); | ||
| 633 | } | 609 | } |
| 634 | } | 610 | } |
| 635 | 611 | ||
| @@ -922,6 +898,8 @@ struct State { | |||
| 922 | pub rx_mode: RxMode, | 898 | pub rx_mode: RxMode, |
| 923 | pub tx_mode: TxMode, | 899 | pub tx_mode: TxMode, |
| 924 | pub ns_per_timer_tick: u64, | 900 | pub ns_per_timer_tick: u64, |
| 901 | receiver_instance_count: usize, | ||
| 902 | sender_instance_count: usize, | ||
| 925 | 903 | ||
| 926 | pub err_waker: AtomicWaker, | 904 | pub err_waker: AtomicWaker, |
| 927 | } | 905 | } |
| @@ -933,6 +911,8 @@ impl State { | |||
| 933 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), | 911 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), |
| 934 | ns_per_timer_tick: 0, | 912 | ns_per_timer_tick: 0, |
| 935 | err_waker: AtomicWaker::new(), | 913 | err_waker: AtomicWaker::new(), |
| 914 | receiver_instance_count: 1, | ||
| 915 | sender_instance_count: 1, | ||
| 936 | } | 916 | } |
| 937 | } | 917 | } |
| 938 | } | 918 | } |
| @@ -942,6 +922,7 @@ struct Info { | |||
| 942 | interrupt0: crate::interrupt::Interrupt, | 922 | interrupt0: crate::interrupt::Interrupt, |
| 943 | _interrupt1: crate::interrupt::Interrupt, | 923 | _interrupt1: crate::interrupt::Interrupt, |
| 944 | tx_waker: fn(), | 924 | tx_waker: fn(), |
| 925 | internal_operation: fn(InternalOperation), | ||
| 945 | } | 926 | } |
| 946 | 927 | ||
| 947 | impl Info { | 928 | impl Info { |
| @@ -970,6 +951,7 @@ trait SealedInstance { | |||
| 970 | fn registers() -> crate::can::fd::peripheral::Registers; | 951 | fn registers() -> crate::can::fd::peripheral::Registers; |
| 971 | fn state() -> &'static State; | 952 | fn state() -> &'static State; |
| 972 | unsafe fn mut_state() -> &'static mut State; | 953 | unsafe fn mut_state() -> &'static mut State; |
| 954 | fn internal_operation(val: InternalOperation); | ||
| 973 | fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; | 955 | fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; |
| 974 | } | 956 | } |
| 975 | 957 | ||
| @@ -992,12 +974,42 @@ macro_rules! impl_fdcan { | |||
| 992 | impl SealedInstance for peripherals::$inst { | 974 | impl SealedInstance for peripherals::$inst { |
| 993 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; | 975 | const MSG_RAM_OFFSET: usize = $msg_ram_offset; |
| 994 | 976 | ||
| 977 | fn internal_operation(val: InternalOperation) { | ||
| 978 | critical_section::with(|_| { | ||
| 979 | //let state = self.state as *const State; | ||
| 980 | unsafe { | ||
| 981 | //let mut_state = state as *mut State; | ||
| 982 | let mut_state = peripherals::$inst::mut_state(); | ||
| 983 | match val { | ||
| 984 | InternalOperation::NotifySenderCreated => { | ||
| 985 | mut_state.sender_instance_count += 1; | ||
| 986 | } | ||
| 987 | InternalOperation::NotifySenderDestroyed => { | ||
| 988 | mut_state.sender_instance_count -= 1; | ||
| 989 | if ( 0 == mut_state.sender_instance_count) { | ||
| 990 | (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 991 | } | ||
| 992 | } | ||
| 993 | InternalOperation::NotifyReceiverCreated => { | ||
| 994 | mut_state.receiver_instance_count += 1; | ||
| 995 | } | ||
| 996 | InternalOperation::NotifyReceiverDestroyed => { | ||
| 997 | mut_state.receiver_instance_count -= 1; | ||
| 998 | if ( 0 == mut_state.receiver_instance_count) { | ||
| 999 | (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | }); | ||
| 1005 | } | ||
| 995 | fn info() -> &'static Info { | 1006 | fn info() -> &'static Info { |
| 996 | static INFO: Info = Info { | 1007 | static INFO: Info = Info { |
| 997 | regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset}, | 1008 | regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset}, |
| 998 | interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, | 1009 | interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ, |
| 999 | _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, | 1010 | _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ, |
| 1000 | tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, | 1011 | tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend, |
| 1012 | internal_operation: peripherals::$inst::internal_operation, | ||
| 1001 | }; | 1013 | }; |
| 1002 | &INFO | 1014 | &INFO |
| 1003 | } | 1015 | } |
