diff options
| author | Corey Schuhen <[email protected]> | 2024-03-02 09:00:54 +1000 |
|---|---|---|
| committer | Corey Schuhen <[email protected]> | 2024-03-02 09:09:27 +1000 |
| commit | df8f508ffa2bec79f6e3fba4ac3cfe0e5545b5b2 (patch) | |
| tree | 8d9724cde58d612778900982be9b69fddd567674 | |
| parent | d5c9c611fa317e066d6cf7c5af0513b40bd69d8c (diff) | |
Writing to TX buffer also needs to fire an interrupt to kick off transmission if it is idle.
Formatting
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 62 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 6 |
2 files changed, 63 insertions, 5 deletions
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 6a4a25cb7..77db774fc 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -436,7 +436,31 @@ pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_S | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | /// Sender that can be used for sending CAN frames. | 438 | /// Sender that can be used for sending CAN frames. |
| 439 | pub type BufferedCanSender = embassy_sync::channel::DynamicSender<'static, ClassicFrame>; | 439 | #[derive(Copy, Clone)] |
| 440 | pub struct BufferedCanSender { | ||
| 441 | tx_buf: embassy_sync::channel::DynamicSender<'static, ClassicFrame>, | ||
| 442 | waker: fn(), | ||
| 443 | } | ||
| 444 | |||
| 445 | impl BufferedCanSender { | ||
| 446 | /// Async write frame to TX buffer. | ||
| 447 | pub fn try_write(&mut self, frame: ClassicFrame) -> Result<(), embassy_sync::channel::TrySendError<ClassicFrame>> { | ||
| 448 | self.tx_buf.try_send(frame)?; | ||
| 449 | (self.waker)(); | ||
| 450 | Ok(()) | ||
| 451 | } | ||
| 452 | |||
| 453 | /// Async write frame to TX buffer. | ||
| 454 | pub async fn write(&mut self, frame: ClassicFrame) { | ||
| 455 | self.tx_buf.send(frame).await; | ||
| 456 | (self.waker)(); | ||
| 457 | } | ||
| 458 | |||
| 459 | /// Allows a poll_fn to poll until the channel is ready to write | ||
| 460 | pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> { | ||
| 461 | self.tx_buf.poll_ready_to_send(cx) | ||
| 462 | } | ||
| 463 | } | ||
| 440 | 464 | ||
| 441 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 465 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 442 | pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (ClassicFrame, Timestamp)>; | 466 | pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (ClassicFrame, Timestamp)>; |
| @@ -489,7 +513,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 489 | 513 | ||
| 490 | /// Returns a sender that can be used for sending CAN frames. | 514 | /// Returns a sender that can be used for sending CAN frames. |
| 491 | pub fn writer(&self) -> BufferedCanSender { | 515 | pub fn writer(&self) -> BufferedCanSender { |
| 492 | self.tx_buf.sender().into() | 516 | BufferedCanSender { |
| 517 | tx_buf: self.tx_buf.sender().into(), | ||
| 518 | waker: T::IT0Interrupt::pend, | ||
| 519 | } | ||
| 493 | } | 520 | } |
| 494 | 521 | ||
| 495 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 522 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| @@ -525,7 +552,31 @@ pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF | |||
| 525 | } | 552 | } |
| 526 | 553 | ||
| 527 | /// Sender that can be used for sending CAN frames. | 554 | /// Sender that can be used for sending CAN frames. |
| 528 | pub type BufferedFdCanSender = embassy_sync::channel::DynamicSender<'static, FdFrame>; | 555 | #[derive(Copy, Clone)] |
| 556 | pub struct BufferedFdCanSender { | ||
| 557 | tx_buf: embassy_sync::channel::DynamicSender<'static, FdFrame>, | ||
| 558 | waker: fn(), | ||
| 559 | } | ||
| 560 | |||
| 561 | impl BufferedFdCanSender { | ||
| 562 | /// Async write frame to TX buffer. | ||
| 563 | pub fn try_write(&mut self, frame: FdFrame) -> Result<(), embassy_sync::channel::TrySendError<FdFrame>> { | ||
| 564 | self.tx_buf.try_send(frame)?; | ||
| 565 | (self.waker)(); | ||
| 566 | Ok(()) | ||
| 567 | } | ||
| 568 | |||
| 569 | /// Async write frame to TX buffer. | ||
| 570 | pub async fn write(&mut self, frame: FdFrame) { | ||
| 571 | self.tx_buf.send(frame).await; | ||
| 572 | (self.waker)(); | ||
| 573 | } | ||
| 574 | |||
| 575 | /// Allows a poll_fn to poll until the channel is ready to write | ||
| 576 | pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> { | ||
| 577 | self.tx_buf.poll_ready_to_send(cx) | ||
| 578 | } | ||
| 579 | } | ||
| 529 | 580 | ||
| 530 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 581 | /// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
| 531 | pub type BufferedFdCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (FdFrame, Timestamp)>; | 582 | pub type BufferedFdCanReceiver = embassy_sync::channel::DynamicReceiver<'static, (FdFrame, Timestamp)>; |
| @@ -578,7 +629,10 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | |||
| 578 | 629 | ||
| 579 | /// Returns a sender that can be used for sending CAN frames. | 630 | /// Returns a sender that can be used for sending CAN frames. |
| 580 | pub fn writer(&self) -> BufferedFdCanSender { | 631 | pub fn writer(&self) -> BufferedFdCanSender { |
| 581 | self.tx_buf.sender().into() | 632 | BufferedFdCanSender { |
| 633 | tx_buf: self.tx_buf.sender().into(), | ||
| 634 | waker: T::IT0Interrupt::pend, | ||
| 635 | } | ||
| 582 | } | 636 | } |
| 583 | 637 | ||
| 584 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. | 638 | /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver. |
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs index a41f765c1..11e96361e 100644 --- a/examples/stm32g4/src/bin/can.rs +++ b/examples/stm32g4/src/bin/can.rs | |||
| @@ -184,7 +184,11 @@ async fn main(_spawner: Spawner) { | |||
| 184 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); | 184 | let frame = can::frame::ClassicFrame::new_extended(0x123456F, &[i; 8]).unwrap(); |
| 185 | info!("Writing frame"); | 185 | info!("Writing frame"); |
| 186 | 186 | ||
| 187 | _ = can.write(frame).await; | 187 | // You can use any of these approaches to send. The writer makes it |
| 188 | // easy to share sending from multiple tasks. | ||
| 189 | //_ = can.write(frame).await; | ||
| 190 | //can.writer().try_write(frame).unwrap(); | ||
| 191 | can.writer().write(frame).await; | ||
| 188 | 192 | ||
| 189 | match can.read().await { | 193 | match can.read().await { |
| 190 | Ok((rx_frame, ts)) => { | 194 | Ok((rx_frame, ts)) => { |
