Refactor bxcan split.

This commit is contained in:
Tommas Bakker 2023-10-25 13:56:23 +02:00 committed by Mick van Gelderen
parent 766ec77ec5
commit 06a83c0f89
No known key found for this signature in database
GPG Key ID: 6BD3FEFAFF7626D1

View File

@ -1,4 +1,3 @@
use core::cell::{RefCell, RefMut};
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
@ -84,7 +83,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
} }
pub struct Can<'d, T: Instance> { pub struct Can<'d, T: Instance> {
pub can: RefCell<bxcan::Can<BxcanInstance<'d, T>>>, pub can: bxcan::Can<BxcanInstance<'d, T>>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -175,14 +174,12 @@ impl<'d, T: Instance> Can<'d, T> {
tx.set_as_af(tx.af_num(), AFType::OutputPushPull); tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(); let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled();
let can_ref_cell = RefCell::new(can); Self { can }
Self { can: can_ref_cell }
} }
pub fn set_bitrate(&mut self, bitrate: u32) { pub fn set_bitrate(&mut self, bitrate: u32) {
let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap();
self.can self.can
.borrow_mut()
.modify_config() .modify_config()
.set_bit_timing(bit_timing) .set_bit_timing(bit_timing)
.leave_disabled(); .leave_disabled();
@ -193,55 +190,56 @@ impl<'d, T: Instance> Can<'d, T> {
/// This will wait for 11 consecutive recessive bits (bus idle state). /// This will wait for 11 consecutive recessive bits (bus idle state).
/// Contrary to enable method from bxcan library, this will not freeze the executor while waiting. /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
pub async fn enable(&mut self) { pub async fn enable(&mut self) {
while self.borrow_mut().enable_non_blocking().is_err() { while self.enable_non_blocking().is_err() {
// SCE interrupt is only generated for entering sleep mode, but not leaving. // SCE interrupt is only generated for entering sleep mode, but not leaving.
// Yield to allow other tasks to execute while can bus is initializing. // Yield to allow other tasks to execute while can bus is initializing.
embassy_futures::yield_now().await; embassy_futures::yield_now().await;
} }
} }
/// Queues the message to be sent but exerts backpressure /// Queues the message to be sent but exerts backpressure
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
CanTx { can: &self.can }.write(frame).await self.split().0.write(frame).await
} }
/// Attempts to transmit a frame without blocking. /// Attempts to transmit a frame without blocking.
/// ///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> { pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
CanTx { can: &self.can }.try_write(frame) self.split().0.try_write(frame)
} }
/// Waits for a specific transmit mailbox to become empty /// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) { pub async fn flush(&self, mb: bxcan::Mailbox) {
CanTx { can: &self.can }.flush(mb).await CanTx::<T>::_flush(mb).await
} }
/// Waits until any of the transmit mailboxes become empty /// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) { pub async fn flush_any(&self) {
CanTx { can: &self.can }.flush_any().await CanTx::<T>::_flush_any().await
} }
/// Waits until all of the transmit mailboxes become empty /// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) { pub async fn flush_all(&self) {
CanTx { can: &self.can }.flush_all().await CanTx::<T>::_flush_all().await
} }
/// Returns a tuple of the time the message was received and the message frame /// Returns a tuple of the time the message was received and the message frame
pub async fn read(&mut self) -> Result<Envelope, BusError> { pub async fn read(&mut self) -> Result<Envelope, BusError> {
CanRx { can: &self.can }.read().await self.split().1.read().await
} }
/// Attempts to read a can frame without blocking. /// Attempts to read a can frame without blocking.
/// ///
/// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue.
pub fn try_read(&mut self) -> Result<Envelope, TryReadError> { pub fn try_read(&mut self) -> Result<Envelope, TryReadError> {
CanRx { can: &self.can }.try_read() self.split().1.try_read()
} }
/// Waits while receive queue is empty. /// Waits while receive queue is empty.
pub async fn wait_not_empty(&mut self) { pub async fn wait_not_empty(&mut self) {
CanRx { can: &self.can }.wait_not_empty().await self.split().1.wait_not_empty().await
} }
unsafe fn receive_fifo(fifo: RxFifo) { unsafe fn receive_fifo(fifo: RxFifo) {
@ -385,24 +383,25 @@ impl<'d, T: Instance> Can<'d, T> {
Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1)) Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler - 1))
} }
pub fn split<'c>(&'c self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { pub fn split<'c>(&'c mut self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) {
(CanTx { can: &self.can }, CanRx { can: &self.can }) let (tx, rx0, rx1) = self.can.split_by_ref();
(CanTx { tx }, CanRx { rx0, rx1 })
} }
pub fn as_mut(&self) -> RefMut<'_, bxcan::Can<BxcanInstance<'d, T>>> { pub fn as_mut(&mut self) -> &mut bxcan::Can<BxcanInstance<'d, T>> {
self.can.borrow_mut() &mut self.can
} }
} }
pub struct CanTx<'c, 'd, T: Instance> { pub struct CanTx<'c, 'd, T: Instance> {
can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>, tx: &'c mut bxcan::Tx<BxcanInstance<'d, T>>,
} }
impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
poll_fn(|cx| { poll_fn(|cx| {
T::state().tx_waker.register(cx.waker()); T::state().tx_waker.register(cx.waker());
if let Ok(status) = self.can.borrow_mut().transmit(frame) { if let Ok(status) = self.tx.transmit(frame) {
return Poll::Ready(status); return Poll::Ready(status);
} }
@ -415,11 +414,10 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
/// ///
/// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full.
pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> { pub fn try_write(&mut self, frame: &Frame) -> Result<bxcan::TransmitStatus, TryWriteError> {
self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full) self.tx.transmit(frame).map_err(|_| TryWriteError::Full)
} }
/// Waits for a specific transmit mailbox to become empty pub async fn _flush(mb: bxcan::Mailbox) {
pub async fn flush(&self, mb: bxcan::Mailbox) {
poll_fn(|cx| { poll_fn(|cx| {
T::state().tx_waker.register(cx.waker()); T::state().tx_waker.register(cx.waker());
if T::regs().tsr().read().tme(mb.index()) { if T::regs().tsr().read().tme(mb.index()) {
@ -431,8 +429,13 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
.await; .await;
} }
/// Waits for a specific transmit mailbox to become empty
pub async fn flush(&self, mb: bxcan::Mailbox) {
Self::_flush(mb).await
}
/// Waits until any of the transmit mailboxes become empty /// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) { pub async fn _flush_any() {
poll_fn(|cx| { poll_fn(|cx| {
T::state().tx_waker.register(cx.waker()); T::state().tx_waker.register(cx.waker());
@ -449,8 +452,13 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
.await; .await;
} }
/// Waits until any of the transmit mailboxes become empty
pub async fn flush_any(&self) {
Self::_flush_any().await
}
/// Waits until all of the transmit mailboxes become empty /// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) { pub async fn _flush_all() {
poll_fn(|cx| { poll_fn(|cx| {
T::state().tx_waker.register(cx.waker()); T::state().tx_waker.register(cx.waker());
@ -466,11 +474,19 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> {
}) })
.await; .await;
} }
/// Waits until all of the transmit mailboxes become empty
pub async fn flush_all(&self) {
Self::_flush_all().await
}
} }
#[allow(dead_code)] #[allow(dead_code)]
pub struct CanRx<'c, 'd, T: Instance> { pub struct CanRx<'c, 'd, T: Instance> {
can: &'c RefCell<bxcan::Can<BxcanInstance<'d, T>>>, rx0: &'c mut bxcan::Rx0<BxcanInstance<'d, T>>,
rx1: &'c mut bxcan::Rx1<BxcanInstance<'d, T>>,
} }
impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> {
@ -538,7 +554,7 @@ impl<'d, T: Instance> Drop for Can<'d, T> {
} }
impl<'d, T: Instance> Deref for Can<'d, T> { impl<'d, T: Instance> Deref for Can<'d, T> {
type Target = RefCell<bxcan::Can<BxcanInstance<'d, T>>>; type Target = bxcan::Can<BxcanInstance<'d, T>>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.can &self.can