aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2023-07-28 14:22:24 +0300
committerchemicstry <[email protected]>2023-07-28 14:22:24 +0300
commit38b5d1ee2b1319a6f84c8894f05c650bb3630ece (patch)
tree11a771f504670c30578f40adc5e1a25bcd520a49
parent44c8db2911f0f9d82e6517e31944777454c4e459 (diff)
stm32/can: implement more convenience methods
-rw-r--r--embassy-stm32/src/can/bxcan.rs154
1 files changed, 116 insertions, 38 deletions
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs
index 8b8244d4f..d4ec23816 100644
--- a/embassy-stm32/src/can/bxcan.rs
+++ b/embassy-stm32/src/can/bxcan.rs
@@ -77,6 +77,7 @@ pub struct Can<'d, T: Instance> {
77} 77}
78 78
79#[derive(Debug)] 79#[derive(Debug)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub enum BusError { 81pub enum BusError {
81 Stuff, 82 Stuff,
82 Form, 83 Form,
@@ -90,6 +91,22 @@ pub enum BusError {
90 BusWarning, 91 BusWarning,
91} 92}
92 93
94#[derive(Debug)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub enum TryReadError {
97 /// Bus error
98 BusError(BusError),
99 /// Receive buffer is empty
100 Empty,
101}
102
103#[derive(Debug)]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105pub enum TryWriteError {
106 /// All transmit mailboxes are full
107 Full,
108}
109
93impl<'d, T: Instance> Can<'d, T> { 110impl<'d, T: Instance> Can<'d, T> {
94 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. 111 /// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
95 /// You must call [Can::enable_non_blocking] to use the peripheral. 112 /// You must call [Can::enable_non_blocking] to use the peripheral.
@@ -175,56 +192,46 @@ impl<'d, T: Instance> Can<'d, T> {
175 192
176 /// Queues the message to be sent but exerts backpressure 193 /// Queues the message to be sent but exerts backpressure
177 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { 194 pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
178 poll_fn(|cx| { 195 CanTx { can: &self.can }.write(frame).await
179 T::state().tx_waker.register(cx.waker()); 196 }
180 if let Ok(status) = self.can.borrow_mut().transmit(frame) {
181 return Poll::Ready(status);
182 }
183 197
184 Poll::Pending 198 /// Attempts to transmit a frame without blocking.
185 }) 199 ///
186 .await 200 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
201 pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
202 CanTx { can: &self.can }.try_write(frame)
187 } 203 }
188 204
205 /// Waits for a specific transmit mailbox to become empty
189 pub async fn flush(&self, mb: bxcan::Mailbox) { 206 pub async fn flush(&self, mb: bxcan::Mailbox) {
190 poll_fn(|cx| { 207 CanTx { can: &self.can }.flush(mb).await
191 T::state().tx_waker.register(cx.waker()); 208 }
192 if T::regs().tsr().read().tme(mb.index()) {
193 return Poll::Ready(());
194 }
195 209
196 Poll::Pending 210 /// Waits until any of the transmit mailboxes become empty
197 }) 211 pub async fn flush_any(&self) {
198 .await; 212 CanTx { can: &self.can }.flush_any().await
213 }
214
215 /// Waits until all of the transmit mailboxes become empty
216 pub async fn flush_all(&self) {
217 CanTx { can: &self.can }.flush_all().await
199 } 218 }
200 219
201 /// Returns a tuple of the time the message was received and the message frame 220 /// Returns a tuple of the time the message was received and the message frame
202 pub async fn read(&mut self) -> Result<(u16, bxcan::Frame), BusError> { 221 pub async fn read(&mut self) -> Result<(u16, bxcan::Frame), BusError> {
203 poll_fn(|cx| { 222 CanRx { can: &self.can }.read().await
204 T::state().err_waker.register(cx.waker()); 223 }
205 if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) {
206 return Poll::Ready(Ok((time, frame)));
207 } else if let Some(err) = self.curr_error() {
208 return Poll::Ready(Err(err));
209 }
210 224
211 Poll::Pending 225 /// Attempts to read a can frame without blocking.
212 }) 226 ///
213 .await 227 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
228 pub fn try_read(&mut self) -> Result<(u16, bxcan::Frame), TryReadError> {
229 CanRx { can: &self.can }.try_read()
214 } 230 }
215 231
216 fn curr_error(&self) -> Option<BusError> { 232 /// Waits while receive queue is empty.
217 let err = { T::regs().esr().read() }; 233 pub async fn wait_not_empty(&mut self) {
218 if err.boff() { 234 CanRx { can: &self.can }.wait_not_empty().await
219 return Some(BusError::BusOff);
220 } else if err.epvf() {
221 return Some(BusError::BusPassive);
222 } else if err.ewgf() {
223 return Some(BusError::BusWarning);
224 } else if let Some(err) = err.lec().into_bus_err() {
225 return Some(err);
226 }
227 None
228 } 235 }
229 236
230 unsafe fn receive_fifo(fifo: RxFifo) { 237 unsafe fn receive_fifo(fifo: RxFifo) {
@@ -386,6 +393,14 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
386 .await 393 .await
387 } 394 }
388 395
396 /// Attempts to transmit a frame without blocking.
397 ///
398 /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
399 pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
400 self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full)
401 }
402
403 /// Waits for a specific transmit mailbox to become empty
389 pub async fn flush(&self, mb: bxcan::Mailbox) { 404 pub async fn flush(&self, mb: bxcan::Mailbox) {
390 poll_fn(|cx| { 405 poll_fn(|cx| {
391 T::state().tx_waker.register(cx.waker()); 406 T::state().tx_waker.register(cx.waker());
@@ -397,6 +412,42 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
397 }) 412 })
398 .await; 413 .await;
399 } 414 }
415
416 /// Waits until any of the transmit mailboxes become empty
417 pub async fn flush_any(&self) {
418 poll_fn(|cx| {
419 T::state().tx_waker.register(cx.waker());
420
421 let tsr = T::regs().tsr().read();
422 if tsr.tme(bxcan::Mailbox::Mailbox0.index())
423 || tsr.tme(bxcan::Mailbox::Mailbox1.index())
424 || tsr.tme(bxcan::Mailbox::Mailbox2.index())
425 {
426 return Poll::Ready(());
427 }
428
429 Poll::Pending
430 })
431 .await;
432 }
433
434 /// Waits until all of the transmit mailboxes become empty
435 pub async fn flush_all(&self) {
436 poll_fn(|cx| {
437 T::state().tx_waker.register(cx.waker());
438
439 let tsr = T::regs().tsr().read();
440 if tsr.tme(bxcan::Mailbox::Mailbox0.index())
441 && tsr.tme(bxcan::Mailbox::Mailbox1.index())
442 && tsr.tme(bxcan::Mailbox::Mailbox2.index())
443 {
444 return Poll::Ready(());
445 }
446
447 Poll::Pending
448 })
449 .await;
450 }
400} 451}
401 452
402#[allow(dead_code)] 453#[allow(dead_code)]
@@ -419,6 +470,33 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
419 .await 470 .await
420 } 471 }
421 472
473 /// Attempts to read a CAN frame without blocking.
474 ///
475 /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
476 pub fn try_read(&mut self) -> Result<(u16, bxcan::Frame), TryReadError> {
477 if let Ok(envelope) = T::state().rx_queue.try_recv() {
478 return Ok(envelope);
479 }
480
481 if let Some(err) = self.curr_error() {
482 return Err(TryReadError::BusError(err));
483 }
484
485 Err(TryReadError::Empty)
486 }
487
488 /// Waits while receive queue is empty.
489 pub async fn wait_not_empty(&mut self) {
490 poll_fn(|cx| {
491 if T::state().rx_queue.poll_ready_to_receive(cx) {
492 Poll::Ready(())
493 } else {
494 Poll::Pending
495 }
496 })
497 .await
498 }
499
422 fn curr_error(&self) -> Option<BusError> { 500 fn curr_error(&self) -> Option<BusError> {
423 let err = { T::regs().esr().read() }; 501 let err = { T::regs().esr().read() };
424 if err.boff() { 502 if err.boff() {