embassy_stm32/can/
common.rs

1use embassy_sync::channel::{SendDynamicReceiver, SendDynamicSender};
2
3use super::enums::*;
4use super::frame::*;
5
6pub(crate) struct ClassicBufferedRxInner {
7    pub rx_sender: SendDynamicSender<'static, Result<Envelope, BusError>>,
8}
9pub(crate) struct ClassicBufferedTxInner {
10    pub tx_receiver: SendDynamicReceiver<'static, Frame>,
11}
12
13#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
14
15pub(crate) struct FdBufferedRxInner {
16    pub rx_sender: SendDynamicSender<'static, Result<FdEnvelope, BusError>>,
17}
18
19#[cfg(any(can_fdcan_v1, can_fdcan_h7))]
20pub(crate) struct FdBufferedTxInner {
21    pub tx_receiver: SendDynamicReceiver<'static, FdFrame>,
22}
23
24/// Sender that can be used for sending CAN frames.
25pub struct BufferedSender<'ch, FRAME> {
26    pub(crate) tx_buf: embassy_sync::channel::SendDynamicSender<'ch, FRAME>,
27    pub(crate) info: TxInfoRef,
28}
29
30impl<'ch, FRAME> BufferedSender<'ch, FRAME> {
31    /// Async write frame to TX buffer.
32    pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError<FRAME>> {
33        self.tx_buf.try_send(frame)?;
34        (self.info.tx_waker)();
35        Ok(())
36    }
37
38    /// Async write frame to TX buffer.
39    pub async fn write(&mut self, frame: FRAME) {
40        self.tx_buf.send(frame).await;
41        (self.info.tx_waker)();
42    }
43
44    /// Allows a poll_fn to poll until the channel is ready to write
45    pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
46        self.tx_buf.poll_ready_to_send(cx)
47    }
48}
49
50impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> {
51    fn clone(&self) -> Self {
52        Self {
53            tx_buf: self.tx_buf,
54            info: TxInfoRef::new(&self.info),
55        }
56    }
57}
58
59/// Sender that can be used for sending Classic CAN frames.
60pub type BufferedCanSender = BufferedSender<'static, Frame>;
61
62/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
63pub struct BufferedReceiver<'ch, ENVELOPE> {
64    pub(crate) rx_buf: embassy_sync::channel::SendDynamicReceiver<'ch, Result<ENVELOPE, BusError>>,
65    pub(crate) info: RxInfoRef,
66}
67
68impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> {
69    /// Receive the next frame.
70    ///
71    /// See [`Channel::receive()`].
72    pub fn receive(&self) -> embassy_sync::channel::DynamicReceiveFuture<'_, Result<ENVELOPE, BusError>> {
73        self.rx_buf.receive()
74    }
75
76    /// Attempt to immediately receive the next frame.
77    ///
78    /// See [`Channel::try_receive()`]
79    pub fn try_receive(&self) -> Result<Result<ENVELOPE, BusError>, embassy_sync::channel::TryReceiveError> {
80        self.rx_buf.try_receive()
81    }
82
83    /// Allows a poll_fn to poll until the channel is ready to receive
84    ///
85    /// See [`Channel::poll_ready_to_receive()`]
86    pub fn poll_ready_to_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
87        self.rx_buf.poll_ready_to_receive(cx)
88    }
89
90    /// Poll the channel for the next frame
91    ///
92    /// See [`Channel::poll_receive()`]
93    pub fn poll_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<Result<ENVELOPE, BusError>> {
94        self.rx_buf.poll_receive(cx)
95    }
96}
97
98impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> {
99    fn clone(&self) -> Self {
100        Self {
101            rx_buf: self.rx_buf,
102            info: RxInfoRef::new(&self.info),
103        }
104    }
105}
106
107/// A BufferedCanReceiver for Classic CAN frames.
108pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>;
109
110/// Provides a reference to the driver internals and implements RAII for the internal reference
111/// counting. Each type that can operate on the driver should contain either InfoRef
112/// or the similar TxInfoRef or RxInfoRef. The new method and the Drop impl will automatically
113/// call the reference counting function. Like this, the reference counting function does not
114/// need to be called manually for each type.
115pub(crate) struct InfoRef {
116    info: &'static super::Info,
117}
118impl InfoRef {
119    pub(crate) fn new(info: &'static super::Info) -> Self {
120        info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated);
121        info.adjust_reference_counter(RefCountOp::NotifySenderCreated);
122        Self { info }
123    }
124}
125
126impl Drop for InfoRef {
127    fn drop(&mut self) {
128        self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed);
129        self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed);
130    }
131}
132
133impl core::ops::Deref for InfoRef {
134    type Target = &'static super::Info;
135
136    fn deref(&self) -> &Self::Target {
137        &self.info
138    }
139}
140
141/// Provides a reference to the driver internals and implements RAII for the internal reference
142/// counting for Tx only types.
143/// See InfoRef for further doc.
144pub(crate) struct TxInfoRef {
145    info: &'static super::Info,
146}
147
148impl TxInfoRef {
149    pub(crate) fn new(info: &'static super::Info) -> Self {
150        info.adjust_reference_counter(RefCountOp::NotifySenderCreated);
151        Self { info }
152    }
153}
154
155impl Drop for TxInfoRef {
156    fn drop(&mut self) {
157        self.info.adjust_reference_counter(RefCountOp::NotifySenderDestroyed);
158    }
159}
160
161impl core::ops::Deref for TxInfoRef {
162    type Target = &'static super::Info;
163
164    fn deref(&self) -> &Self::Target {
165        &self.info
166    }
167}
168
169/// Provides a reference to the driver internals and implements RAII for the internal reference
170/// counting for Rx only types.
171/// See InfoRef for further doc.
172pub(crate) struct RxInfoRef {
173    info: &'static super::Info,
174}
175
176impl RxInfoRef {
177    pub(crate) fn new(info: &'static super::Info) -> Self {
178        info.adjust_reference_counter(RefCountOp::NotifyReceiverCreated);
179        Self { info }
180    }
181}
182
183impl Drop for RxInfoRef {
184    fn drop(&mut self) {
185        self.info.adjust_reference_counter(RefCountOp::NotifyReceiverDestroyed);
186    }
187}
188
189impl core::ops::Deref for RxInfoRef {
190    type Target = &'static super::Info;
191
192    fn deref(&self) -> &Self::Target {
193        &self.info
194    }
195}