Remove generics for BXCAN.
This commit is contained in:
parent
62f4b4ee1e
commit
245c895d09
3 changed files with 200 additions and 112 deletions
|
@ -5,6 +5,7 @@ use core::future::poll_fn;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy_hal_internal::interrupt::InterruptExt;
|
||||||
use embassy_hal_internal::{into_ref, PeripheralRef};
|
use embassy_hal_internal::{into_ref, PeripheralRef};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
|
@ -154,7 +155,10 @@ impl<T: Instance> Drop for CanConfig<'_, T> {
|
||||||
|
|
||||||
/// CAN driver
|
/// CAN driver
|
||||||
pub struct Can<'d, T: Instance> {
|
pub struct Can<'d, T: Instance> {
|
||||||
peri: PeripheralRef<'d, T>,
|
_peri: PeripheralRef<'d, T>,
|
||||||
|
instance: &'d crate::pac::can::Can,
|
||||||
|
info: &'static Info,
|
||||||
|
state: &'static State,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error returned by `try_write`
|
/// Error returned by `try_write`
|
||||||
|
@ -179,6 +183,8 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
+ 'd,
|
+ 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, rx, tx);
|
into_ref!(peri, rx, tx);
|
||||||
|
let info = T::info();
|
||||||
|
let regs = &T::info().regs;
|
||||||
|
|
||||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||||
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
|
||||||
|
@ -186,7 +192,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
T::enable_and_reset();
|
T::enable_and_reset();
|
||||||
|
|
||||||
{
|
{
|
||||||
T::regs().ier().write(|w| {
|
regs.0.ier().write(|w| {
|
||||||
w.set_errie(true);
|
w.set_errie(true);
|
||||||
w.set_fmpie(0, true);
|
w.set_fmpie(0, true);
|
||||||
w.set_fmpie(1, true);
|
w.set_fmpie(1, true);
|
||||||
|
@ -197,7 +203,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
w.set_lecie(true);
|
w.set_lecie(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
T::regs().mcr().write(|w| {
|
regs.0.mcr().write(|w| {
|
||||||
// Enable timestamps on rx messages
|
// Enable timestamps on rx messages
|
||||||
|
|
||||||
w.set_ttcm(true);
|
w.set_ttcm(true);
|
||||||
|
@ -205,17 +211,14 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
T::TXInterrupt::unpend();
|
info.tx_interrupt.unpend();
|
||||||
T::TXInterrupt::enable();
|
info.tx_interrupt.enable();
|
||||||
|
info.rx0_interrupt.unpend();
|
||||||
T::RX0Interrupt::unpend();
|
info.rx0_interrupt.enable();
|
||||||
T::RX0Interrupt::enable();
|
info.rx1_interrupt.unpend();
|
||||||
|
info.rx1_interrupt.enable();
|
||||||
T::RX1Interrupt::unpend();
|
info.sce_interrupt.unpend();
|
||||||
T::RX1Interrupt::enable();
|
info.sce_interrupt.enable();
|
||||||
|
|
||||||
T::SCEInterrupt::unpend();
|
|
||||||
T::SCEInterrupt::enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rx.set_as_af(rx.af_num(), AFType::Input);
|
rx.set_as_af(rx.af_num(), AFType::Input);
|
||||||
|
@ -223,7 +226,12 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
|
|
||||||
Registers(T::regs()).leave_init_mode();
|
Registers(T::regs()).leave_init_mode();
|
||||||
|
|
||||||
Self { peri }
|
Self {
|
||||||
|
_peri: peri,
|
||||||
|
instance: &T::info().regs.0,
|
||||||
|
info: T::info(),
|
||||||
|
state: T::state(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set CAN bit rate.
|
/// Set CAN bit rate.
|
||||||
|
@ -265,12 +273,12 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
/// Waking the peripheral manually does not trigger a wake-up interrupt.
|
/// Waking the peripheral manually does not trigger a wake-up interrupt.
|
||||||
/// This will wait until the peripheral has acknowledged it has awoken from sleep mode
|
/// This will wait until the peripheral has acknowledged it has awoken from sleep mode
|
||||||
pub fn wakeup(&mut self) {
|
pub fn wakeup(&mut self) {
|
||||||
Registers(T::regs()).wakeup()
|
self.info.regs.wakeup()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the peripheral is currently in sleep mode
|
/// Check if the peripheral is currently in sleep mode
|
||||||
pub fn is_sleeping(&self) -> bool {
|
pub fn is_sleeping(&self) -> bool {
|
||||||
T::regs().msr().read().slak()
|
self.info.regs.0.msr().read().slak()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put the peripheral in sleep mode
|
/// Put the peripheral in sleep mode
|
||||||
|
@ -282,11 +290,11 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
/// If the peripheral has automatic wakeup enabled, when a Start-of-Frame is detected
|
/// If the peripheral has automatic wakeup enabled, when a Start-of-Frame is detected
|
||||||
/// the peripheral will automatically wake and receive the incoming message.
|
/// the peripheral will automatically wake and receive the incoming message.
|
||||||
pub async fn sleep(&mut self) {
|
pub async fn sleep(&mut self) {
|
||||||
T::regs().ier().modify(|i| i.set_slkie(true));
|
self.info.regs.0.ier().modify(|i| i.set_slkie(true));
|
||||||
T::regs().mcr().modify(|m| m.set_sleep(true));
|
self.info.regs.0.mcr().modify(|m| m.set_sleep(true));
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().err_waker.register(cx.waker());
|
self.state.err_waker.register(cx.waker());
|
||||||
if self.is_sleeping() {
|
if self.is_sleeping() {
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -295,7 +303,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
T::regs().ier().modify(|i| i.set_slkie(false));
|
self.info.regs.0.ier().modify(|i| i.set_slkie(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable FIFO scheduling of outgoing frames.
|
/// Enable FIFO scheduling of outgoing frames.
|
||||||
|
@ -337,7 +345,13 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
|
|
||||||
/// Waits for a specific transmit mailbox to become empty
|
/// Waits for a specific transmit mailbox to become empty
|
||||||
pub async fn flush(&self, mb: Mailbox) {
|
pub async fn flush(&self, mb: Mailbox) {
|
||||||
CanTx::<T>::flush_inner(mb).await
|
CanTx {
|
||||||
|
_instance: &self.instance,
|
||||||
|
info: self.info,
|
||||||
|
state: self.state,
|
||||||
|
}
|
||||||
|
.flush_inner(mb)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Waits until any of the transmit mailboxes become empty
|
/// Waits until any of the transmit mailboxes become empty
|
||||||
|
@ -347,12 +361,24 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
/// This will happen if FIFO scheduling of outgoing frames is not enabled,
|
/// This will happen if FIFO scheduling of outgoing frames is not enabled,
|
||||||
/// and a frame with equal priority is already queued for transmission.
|
/// and a frame with equal priority is already queued for transmission.
|
||||||
pub async fn flush_any(&self) {
|
pub async fn flush_any(&self) {
|
||||||
CanTx::<T>::flush_any_inner().await
|
CanTx {
|
||||||
|
_instance: &self.instance,
|
||||||
|
info: self.info,
|
||||||
|
state: self.state,
|
||||||
|
}
|
||||||
|
.flush_any_inner()
|
||||||
|
.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::<T>::flush_all_inner().await
|
CanTx {
|
||||||
|
_instance: &self.instance,
|
||||||
|
info: self.info,
|
||||||
|
state: self.state,
|
||||||
|
}
|
||||||
|
.flush_all_inner()
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to abort the sending of a frame that is pending in a mailbox.
|
/// Attempts to abort the sending of a frame that is pending in a mailbox.
|
||||||
|
@ -363,12 +389,12 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
||||||
/// returns `true`.
|
/// returns `true`.
|
||||||
pub fn abort(&mut self, mailbox: Mailbox) -> bool {
|
pub fn abort(&mut self, mailbox: Mailbox) -> bool {
|
||||||
Registers(T::regs()).abort(mailbox)
|
self.info.regs.abort(mailbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if no frame is pending for transmission.
|
/// Returns `true` if no frame is pending for transmission.
|
||||||
pub fn is_transmitter_idle(&self) -> bool {
|
pub fn is_transmitter_idle(&self) -> bool {
|
||||||
Registers(T::regs()).is_idle()
|
self.info.regs.is_idle()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a CAN frame.
|
/// Read a CAN frame.
|
||||||
|
@ -377,31 +403,35 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
///
|
///
|
||||||
/// 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> {
|
||||||
T::state().rx_mode.read::<T>().await
|
self.state.rx_mode.read(self.info, self.state).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> {
|
||||||
T::state().rx_mode.try_read::<T>()
|
self.state.rx_mode.try_read(self.info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) {
|
||||||
T::state().rx_mode.wait_not_empty::<T>().await
|
self.state.rx_mode.wait_not_empty(self.info, self.state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split the CAN driver into transmit and receive halves.
|
/// Split the CAN driver into transmit and receive halves.
|
||||||
///
|
///
|
||||||
/// Useful for doing separate transmit/receive tasks.
|
/// Useful for doing separate transmit/receive tasks.
|
||||||
pub fn split<'c>(&'c mut self) -> (CanTx<'d, T>, CanRx<'d, T>) {
|
pub fn split<'c>(&'c mut self) -> (CanTx<'d>, CanRx<'d>) {
|
||||||
(
|
(
|
||||||
CanTx {
|
CanTx {
|
||||||
_peri: unsafe { self.peri.clone_unchecked() },
|
_instance: &self.instance,
|
||||||
|
info: self.info,
|
||||||
|
state: self.state,
|
||||||
},
|
},
|
||||||
CanRx {
|
CanRx {
|
||||||
peri: unsafe { self.peri.clone_unchecked() },
|
instance: &self.instance,
|
||||||
|
info: self.info,
|
||||||
|
state: self.state,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -411,7 +441,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
||||||
&'c mut self,
|
&'c mut self,
|
||||||
txb: &'static mut TxBuf<TX_BUF_SIZE>,
|
txb: &'static mut TxBuf<TX_BUF_SIZE>,
|
||||||
rxb: &'static mut RxBuf<RX_BUF_SIZE>,
|
rxb: &'static mut RxBuf<RX_BUF_SIZE>,
|
||||||
) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
|
) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
||||||
let (tx, rx) = self.split();
|
let (tx, rx) = self.split();
|
||||||
BufferedCan {
|
BufferedCan {
|
||||||
tx: tx.buffered(txb),
|
tx: tx.buffered(txb),
|
||||||
|
@ -426,17 +456,17 @@ impl<'d, T: FilterOwner> Can<'d, T> {
|
||||||
/// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
|
/// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
|
||||||
/// peripheral instead.
|
/// peripheral instead.
|
||||||
pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
|
pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
|
||||||
unsafe { MasterFilters::new(T::regs()) }
|
unsafe { MasterFilters::new(self.info.regs.0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Buffered CAN driver.
|
/// Buffered CAN driver.
|
||||||
pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
||||||
tx: BufferedCanTx<'d, T, TX_BUF_SIZE>,
|
tx: BufferedCanTx<'d, TX_BUF_SIZE>,
|
||||||
rx: BufferedCanRx<'d, T, RX_BUF_SIZE>,
|
rx: BufferedCanRx<'d, RX_BUF_SIZE>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
|
impl<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
||||||
/// Async write frame to TX buffer.
|
/// Async write frame to TX buffer.
|
||||||
pub async fn write(&mut self, frame: &Frame) {
|
pub async fn write(&mut self, frame: &Frame) {
|
||||||
self.tx.write(frame).await
|
self.tx.write(frame).await
|
||||||
|
@ -471,18 +501,20 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CAN driver, transmit half.
|
/// CAN driver, transmit half.
|
||||||
pub struct CanTx<'d, T: Instance> {
|
pub struct CanTx<'d> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
_instance: &'d crate::pac::can::Can,
|
||||||
|
info: &'static Info,
|
||||||
|
state: &'static State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> CanTx<'d, T> {
|
impl<'d> CanTx<'d> {
|
||||||
/// Queues the message to be sent.
|
/// Queues the message to be sent.
|
||||||
///
|
///
|
||||||
/// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
|
/// If the TX queue is full, this will wait until there is space, therefore exerting backpressure.
|
||||||
pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
|
pub async fn write(&mut self, frame: &Frame) -> TransmitStatus {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().tx_mode.register(cx.waker());
|
self.state.tx_mode.register(cx.waker());
|
||||||
if let Ok(status) = Registers(T::regs()).transmit(frame) {
|
if let Ok(status) = self.info.regs.transmit(frame) {
|
||||||
return Poll::Ready(status);
|
return Poll::Ready(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,13 +533,13 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
/// This is done to work around a hardware limitation that could lead to out-of-order delivery
|
/// This is done to work around a hardware limitation that could lead to out-of-order delivery
|
||||||
/// of frames with the same priority.
|
/// of frames with the same priority.
|
||||||
pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
|
pub fn try_write(&mut self, frame: &Frame) -> Result<TransmitStatus, TryWriteError> {
|
||||||
Registers(T::regs()).transmit(frame).map_err(|_| TryWriteError::Full)
|
self.info.regs.transmit(frame).map_err(|_| TryWriteError::Full)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn flush_inner(mb: Mailbox) {
|
async fn flush_inner(&self, mb: Mailbox) {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().tx_mode.register(cx.waker());
|
self.state.tx_mode.register(cx.waker());
|
||||||
if T::regs().tsr().read().tme(mb.index()) {
|
if self.info.regs.0.tsr().read().tme(mb.index()) {
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,14 +550,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
|
|
||||||
/// Waits for a specific transmit mailbox to become empty
|
/// Waits for a specific transmit mailbox to become empty
|
||||||
pub async fn flush(&self, mb: Mailbox) {
|
pub async fn flush(&self, mb: Mailbox) {
|
||||||
Self::flush_inner(mb).await
|
self.flush_inner(mb).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn flush_any_inner() {
|
async fn flush_any_inner(&self) {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().tx_mode.register(cx.waker());
|
self.state.tx_mode.register(cx.waker());
|
||||||
|
|
||||||
let tsr = T::regs().tsr().read();
|
let tsr = self.info.regs.0.tsr().read();
|
||||||
if tsr.tme(Mailbox::Mailbox0.index())
|
if tsr.tme(Mailbox::Mailbox0.index())
|
||||||
|| tsr.tme(Mailbox::Mailbox1.index())
|
|| tsr.tme(Mailbox::Mailbox1.index())
|
||||||
|| tsr.tme(Mailbox::Mailbox2.index())
|
|| tsr.tme(Mailbox::Mailbox2.index())
|
||||||
|
@ -545,14 +577,14 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
/// This will happen if FIFO scheduling of outgoing frames is not enabled,
|
/// This will happen if FIFO scheduling of outgoing frames is not enabled,
|
||||||
/// and a frame with equal priority is already queued for transmission.
|
/// and a frame with equal priority is already queued for transmission.
|
||||||
pub async fn flush_any(&self) {
|
pub async fn flush_any(&self) {
|
||||||
Self::flush_any_inner().await
|
self.flush_any_inner().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn flush_all_inner() {
|
async fn flush_all_inner(&self) {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().tx_mode.register(cx.waker());
|
self.state.tx_mode.register(cx.waker());
|
||||||
|
|
||||||
let tsr = T::regs().tsr().read();
|
let tsr = self.info.regs.0.tsr().read();
|
||||||
if tsr.tme(Mailbox::Mailbox0.index())
|
if tsr.tme(Mailbox::Mailbox0.index())
|
||||||
&& tsr.tme(Mailbox::Mailbox1.index())
|
&& tsr.tme(Mailbox::Mailbox1.index())
|
||||||
&& tsr.tme(Mailbox::Mailbox2.index())
|
&& tsr.tme(Mailbox::Mailbox2.index())
|
||||||
|
@ -567,7 +599,7 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
|
|
||||||
/// 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) {
|
||||||
Self::flush_all_inner().await
|
self.flush_all_inner().await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to abort the sending of a frame that is pending in a mailbox.
|
/// Attempts to abort the sending of a frame that is pending in a mailbox.
|
||||||
|
@ -578,20 +610,20 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
||||||
/// returns `true`.
|
/// returns `true`.
|
||||||
pub fn abort(&mut self, mailbox: Mailbox) -> bool {
|
pub fn abort(&mut self, mailbox: Mailbox) -> bool {
|
||||||
Registers(T::regs()).abort(mailbox)
|
self.info.regs.abort(mailbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if no frame is pending for transmission.
|
/// Returns `true` if no frame is pending for transmission.
|
||||||
pub fn is_idle(&self) -> bool {
|
pub fn is_idle(&self) -> bool {
|
||||||
Registers(T::regs()).is_idle()
|
self.info.regs.is_idle()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a buffered instance of driver. User must supply Buffers
|
/// Return a buffered instance of driver. User must supply Buffers
|
||||||
pub fn buffered<const TX_BUF_SIZE: usize>(
|
pub fn buffered<const TX_BUF_SIZE: usize>(
|
||||||
self,
|
self,
|
||||||
txb: &'static mut TxBuf<TX_BUF_SIZE>,
|
txb: &'static mut TxBuf<TX_BUF_SIZE>,
|
||||||
) -> BufferedCanTx<'d, T, TX_BUF_SIZE> {
|
) -> BufferedCanTx<'d, TX_BUF_SIZE> {
|
||||||
BufferedCanTx::new(self, txb)
|
BufferedCanTx::new(self.info, self.state, self, txb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,23 +631,35 @@ impl<'d, T: Instance> CanTx<'d, T> {
|
||||||
pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
|
pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
|
||||||
|
|
||||||
/// Buffered CAN driver, transmit half.
|
/// Buffered CAN driver, transmit half.
|
||||||
pub struct BufferedCanTx<'d, T: Instance, const TX_BUF_SIZE: usize> {
|
pub struct BufferedCanTx<'d, const TX_BUF_SIZE: usize> {
|
||||||
_tx: CanTx<'d, T>,
|
info: &'static Info,
|
||||||
|
state: &'static State,
|
||||||
|
_tx: CanTx<'d>,
|
||||||
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
|
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE> {
|
impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
|
||||||
fn new(_tx: CanTx<'d, T>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
|
fn new(info: &'static Info, state: &'static State, _tx: CanTx<'d>, tx_buf: &'static TxBuf<TX_BUF_SIZE>) -> Self {
|
||||||
Self { _tx, tx_buf }.setup()
|
Self {
|
||||||
|
info,
|
||||||
|
state,
|
||||||
|
_tx,
|
||||||
|
tx_buf,
|
||||||
|
}
|
||||||
|
.setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(self) -> Self {
|
fn setup(self) -> Self {
|
||||||
// We don't want interrupts being processed while we change modes.
|
// We don't want interrupts being processed while we change modes.
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| {
|
||||||
let tx_inner = super::common::ClassicBufferedTxInner {
|
let tx_inner = super::common::ClassicBufferedTxInner {
|
||||||
tx_receiver: self.tx_buf.receiver().into(),
|
tx_receiver: self.tx_buf.receiver().into(),
|
||||||
};
|
};
|
||||||
T::mut_state().tx_mode = TxMode::Buffered(tx_inner);
|
let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
let mut_state = state as *mut State;
|
||||||
|
(*mut_state).tx_mode = TxMode::Buffered(tx_inner);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -623,60 +667,67 @@ impl<'d, T: Instance, const TX_BUF_SIZE: usize> BufferedCanTx<'d, T, TX_BUF_SIZE
|
||||||
/// Async write frame to TX buffer.
|
/// Async write frame to TX buffer.
|
||||||
pub async fn write(&mut self, frame: &Frame) {
|
pub async fn write(&mut self, frame: &Frame) {
|
||||||
self.tx_buf.send(*frame).await;
|
self.tx_buf.send(*frame).await;
|
||||||
T::TXInterrupt::pend(); // Wake for Tx
|
let waker = self.info.tx_waker;
|
||||||
|
waker(); // Wake for Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a sender that can be used for sending CAN frames.
|
/// Returns a sender that can be used for sending CAN frames.
|
||||||
pub fn writer(&self) -> BufferedCanSender {
|
pub fn writer(&self) -> BufferedCanSender {
|
||||||
BufferedCanSender {
|
BufferedCanSender {
|
||||||
tx_buf: self.tx_buf.sender().into(),
|
tx_buf: self.tx_buf.sender().into(),
|
||||||
waker: T::TXInterrupt::pend,
|
waker: self.info.tx_waker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, T, TX_BUF_SIZE> {
|
impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, TX_BUF_SIZE> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| {
|
||||||
T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
let mut_state = state as *mut State;
|
||||||
|
(*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CAN driver, receive half.
|
/// CAN driver, receive half.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct CanRx<'d, T: Instance> {
|
pub struct CanRx<'d> {
|
||||||
peri: PeripheralRef<'d, T>,
|
instance: &'d crate::pac::can::Can,
|
||||||
|
info: &'static Info,
|
||||||
|
state: &'static State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> CanRx<'d, T> {
|
impl<'d> CanRx<'d> {
|
||||||
/// Read a CAN frame.
|
/// Read a CAN frame.
|
||||||
///
|
///
|
||||||
/// If no CAN frame is in the RX buffer, this will wait until there is one.
|
/// If no CAN frame is in the RX buffer, this will wait until there is one.
|
||||||
///
|
///
|
||||||
/// 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> {
|
||||||
T::state().rx_mode.read::<T>().await
|
self.state.rx_mode.read(self.info, self.state).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> {
|
||||||
T::state().rx_mode.try_read::<T>()
|
self.state.rx_mode.try_read(self.info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) {
|
||||||
T::state().rx_mode.wait_not_empty::<T>().await
|
self.state.rx_mode.wait_not_empty(self.info, self.state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a buffered instance of driver. User must supply Buffers
|
/// Return a buffered instance of driver. User must supply Buffers
|
||||||
pub fn buffered<const RX_BUF_SIZE: usize>(
|
pub fn buffered<const RX_BUF_SIZE: usize>(
|
||||||
self,
|
self,
|
||||||
rxb: &'static mut RxBuf<RX_BUF_SIZE>,
|
rxb: &'static mut RxBuf<RX_BUF_SIZE>,
|
||||||
) -> BufferedCanRx<'d, T, RX_BUF_SIZE> {
|
) -> BufferedCanRx<'d, RX_BUF_SIZE> {
|
||||||
BufferedCanRx::new(self, rxb)
|
BufferedCanRx::new(self.info, self.state, self, rxb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,23 +735,35 @@ impl<'d, T: Instance> CanRx<'d, T> {
|
||||||
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
|
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
|
||||||
|
|
||||||
/// CAN driver, receive half in Buffered mode.
|
/// CAN driver, receive half in Buffered mode.
|
||||||
pub struct BufferedCanRx<'d, T: Instance, const RX_BUF_SIZE: usize> {
|
pub struct BufferedCanRx<'d, const RX_BUF_SIZE: usize> {
|
||||||
_rx: CanRx<'d, T>,
|
info: &'static Info,
|
||||||
|
state: &'static State,
|
||||||
|
_rx: CanRx<'d>,
|
||||||
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
|
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE> {
|
impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
|
||||||
fn new(_rx: CanRx<'d, T>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
|
fn new(info: &'static Info, state: &'static State, _rx: CanRx<'d>, rx_buf: &'static RxBuf<RX_BUF_SIZE>) -> Self {
|
||||||
BufferedCanRx { _rx, rx_buf }.setup()
|
BufferedCanRx {
|
||||||
|
info,
|
||||||
|
state,
|
||||||
|
_rx,
|
||||||
|
rx_buf,
|
||||||
|
}
|
||||||
|
.setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(self) -> Self {
|
fn setup(self) -> Self {
|
||||||
// We don't want interrupts being processed while we change modes.
|
// We don't want interrupts being processed while we change modes.
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| {
|
||||||
let rx_inner = super::common::ClassicBufferedRxInner {
|
let rx_inner = super::common::ClassicBufferedRxInner {
|
||||||
rx_sender: self.rx_buf.sender().into(),
|
rx_sender: self.rx_buf.sender().into(),
|
||||||
};
|
};
|
||||||
T::mut_state().rx_mode = RxMode::Buffered(rx_inner);
|
let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
let mut_state = state as *mut State;
|
||||||
|
(*mut_state).rx_mode = RxMode::Buffered(rx_inner);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -714,7 +777,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
|
||||||
///
|
///
|
||||||
/// 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> {
|
||||||
match &T::state().rx_mode {
|
match &self.state.rx_mode {
|
||||||
RxMode::Buffered(_) => {
|
RxMode::Buffered(_) => {
|
||||||
if let Ok(result) = self.rx_buf.try_receive() {
|
if let Ok(result) = self.rx_buf.try_receive() {
|
||||||
match result {
|
match result {
|
||||||
|
@ -722,7 +785,7 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
|
||||||
Err(e) => Err(TryReadError::BusError(e)),
|
Err(e) => Err(TryReadError::BusError(e)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(err) = Registers(T::regs()).curr_error() {
|
if let Some(err) = self.info.regs.curr_error() {
|
||||||
return Err(TryReadError::BusError(err));
|
return Err(TryReadError::BusError(err));
|
||||||
} else {
|
} else {
|
||||||
Err(TryReadError::Empty)
|
Err(TryReadError::Empty)
|
||||||
|
@ -746,10 +809,14 @@ impl<'d, T: Instance, const RX_BUF_SIZE: usize> BufferedCanRx<'d, T, RX_BUF_SIZE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, T, RX_BUF_SIZE> {
|
impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| {
|
||||||
T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
let mut_state = state as *mut State;
|
||||||
|
(*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -839,13 +906,13 @@ impl RxMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read<T: Instance>(&self) -> Result<Envelope, BusError> {
|
pub(crate) async fn read(&self, info: &Info, state: &State) -> Result<Envelope, BusError> {
|
||||||
match self {
|
match self {
|
||||||
Self::NonBuffered(waker) => {
|
Self::NonBuffered(waker) => {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().err_waker.register(cx.waker());
|
state.err_waker.register(cx.waker());
|
||||||
waker.register(cx.waker());
|
waker.register(cx.waker());
|
||||||
match self.try_read::<T>() {
|
match self.try_read(info) {
|
||||||
Ok(result) => Poll::Ready(Ok(result)),
|
Ok(result) => Poll::Ready(Ok(result)),
|
||||||
Err(TryReadError::Empty) => Poll::Pending,
|
Err(TryReadError::Empty) => Poll::Pending,
|
||||||
Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
|
Err(TryReadError::BusError(be)) => Poll::Ready(Err(be)),
|
||||||
|
@ -858,17 +925,17 @@ impl RxMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn try_read<T: Instance>(&self) -> Result<Envelope, TryReadError> {
|
pub(crate) fn try_read(&self, info: &Info) -> Result<Envelope, TryReadError> {
|
||||||
match self {
|
match self {
|
||||||
Self::NonBuffered(_) => {
|
Self::NonBuffered(_) => {
|
||||||
let registers = Registers(T::regs());
|
let registers = &info.regs;
|
||||||
if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
|
if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) {
|
||||||
T::regs().ier().write(|w| {
|
registers.0.ier().write(|w| {
|
||||||
w.set_fmpie(0, true);
|
w.set_fmpie(0, true);
|
||||||
});
|
});
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
} else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) {
|
} else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) {
|
||||||
T::regs().ier().write(|w| {
|
registers.0.ier().write(|w| {
|
||||||
w.set_fmpie(1, true);
|
w.set_fmpie(1, true);
|
||||||
});
|
});
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
|
@ -883,12 +950,12 @@ impl RxMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn wait_not_empty<T: Instance>(&self) {
|
pub(crate) async fn wait_not_empty(&self, info: &Info, state: &State) {
|
||||||
match &T::state().rx_mode {
|
match &state.rx_mode {
|
||||||
Self::NonBuffered(waker) => {
|
Self::NonBuffered(waker) => {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
waker.register(cx.waker());
|
waker.register(cx.waker());
|
||||||
if Registers(T::regs()).receive_frame_available() {
|
if info.regs.receive_frame_available() {
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
|
@ -903,7 +970,7 @@ impl RxMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TxMode {
|
pub(crate) enum TxMode {
|
||||||
NonBuffered(AtomicWaker),
|
NonBuffered(AtomicWaker),
|
||||||
Buffered(super::common::ClassicBufferedTxInner),
|
Buffered(super::common::ClassicBufferedTxInner),
|
||||||
}
|
}
|
||||||
|
@ -943,7 +1010,7 @@ impl TxMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
pub(crate) struct State {
|
||||||
pub(crate) rx_mode: RxMode,
|
pub(crate) rx_mode: RxMode,
|
||||||
pub(crate) tx_mode: TxMode,
|
pub(crate) tx_mode: TxMode,
|
||||||
pub err_waker: AtomicWaker,
|
pub err_waker: AtomicWaker,
|
||||||
|
@ -959,7 +1026,17 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct Info {
|
||||||
|
regs: Registers,
|
||||||
|
tx_interrupt: crate::interrupt::Interrupt,
|
||||||
|
rx0_interrupt: crate::interrupt::Interrupt,
|
||||||
|
rx1_interrupt: crate::interrupt::Interrupt,
|
||||||
|
sce_interrupt: crate::interrupt::Interrupt,
|
||||||
|
tx_waker: fn(),
|
||||||
|
}
|
||||||
|
|
||||||
trait SealedInstance {
|
trait SealedInstance {
|
||||||
|
fn info() -> &'static Info;
|
||||||
fn regs() -> crate::pac::can::Can;
|
fn regs() -> crate::pac::can::Can;
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
unsafe fn mut_state() -> &'static mut State;
|
unsafe fn mut_state() -> &'static mut State;
|
||||||
|
@ -1012,6 +1089,17 @@ foreach_peripheral!(
|
||||||
(can, $inst:ident) => {
|
(can, $inst:ident) => {
|
||||||
impl SealedInstance for peripherals::$inst {
|
impl SealedInstance for peripherals::$inst {
|
||||||
|
|
||||||
|
fn info() -> &'static Info {
|
||||||
|
static INFO: Info = Info {
|
||||||
|
regs: Registers(crate::pac::$inst),
|
||||||
|
tx_interrupt: crate::_generated::peripheral_interrupts::$inst::TX::IRQ,
|
||||||
|
rx0_interrupt: crate::_generated::peripheral_interrupts::$inst::RX0::IRQ,
|
||||||
|
rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
|
||||||
|
sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
|
||||||
|
tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
|
||||||
|
};
|
||||||
|
&INFO
|
||||||
|
}
|
||||||
fn regs() -> crate::pac::can::Can {
|
fn regs() -> crate::pac::can::Can {
|
||||||
crate::pac::$inst
|
crate::pac::$inst
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ impl Registers {
|
||||||
/// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
|
/// Note that this will not trigger [`Interrupt::Wakeup`], only reception of an incoming CAN
|
||||||
/// frame will cause that interrupt.
|
/// frame will cause that interrupt.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn wakeup(&mut self) {
|
pub fn wakeup(&self) {
|
||||||
self.0.mcr().modify(|reg| {
|
self.0.mcr().modify(|reg| {
|
||||||
reg.set_sleep(false);
|
reg.set_sleep(false);
|
||||||
reg.set_inrq(false);
|
reg.set_inrq(false);
|
||||||
|
@ -216,7 +216,7 @@ impl Registers {
|
||||||
/// If FIFO scheduling is enabled, frames are transmitted in the order that they are passed to this function.
|
/// If FIFO scheduling is enabled, frames are transmitted in the order that they are passed to this function.
|
||||||
///
|
///
|
||||||
/// If all transmit mailboxes are full, this function returns [`nb::Error::WouldBlock`].
|
/// If all transmit mailboxes are full, this function returns [`nb::Error::WouldBlock`].
|
||||||
pub fn transmit(&mut self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
|
pub fn transmit(&self, frame: &Frame) -> nb::Result<TransmitStatus, Infallible> {
|
||||||
// Check if FIFO scheduling is enabled.
|
// Check if FIFO scheduling is enabled.
|
||||||
let fifo_scheduling = self.0.mcr().read().txfp();
|
let fifo_scheduling = self.0.mcr().read().txfp();
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ impl Registers {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_mailbox(&mut self, idx: usize, frame: &Frame) {
|
fn write_mailbox(&self, idx: usize, frame: &Frame) {
|
||||||
debug_assert!(idx < 3);
|
debug_assert!(idx < 3);
|
||||||
|
|
||||||
let mb = self.0.tx(idx);
|
let mb = self.0.tx(idx);
|
||||||
|
@ -309,7 +309,7 @@ impl Registers {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_pending_mailbox(&mut self, idx: usize) -> Option<Frame> {
|
fn read_pending_mailbox(&self, idx: usize) -> Option<Frame> {
|
||||||
if self.abort_by_index(idx) {
|
if self.abort_by_index(idx) {
|
||||||
debug_assert!(idx < 3);
|
debug_assert!(idx < 3);
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ impl Registers {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to abort a pending frame. Returns `true` when aborted.
|
/// Tries to abort a pending frame. Returns `true` when aborted.
|
||||||
fn abort_by_index(&mut self, idx: usize) -> bool {
|
fn abort_by_index(&self, idx: usize) -> bool {
|
||||||
self.0.tsr().write(|reg| reg.set_abrq(idx, true));
|
self.0.tsr().write(|reg| reg.set_abrq(idx, true));
|
||||||
|
|
||||||
// Wait for the abort request to be finished.
|
// Wait for the abort request to be finished.
|
||||||
|
@ -351,7 +351,7 @@ impl Registers {
|
||||||
///
|
///
|
||||||
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
/// If there is a frame in the provided mailbox, and it is canceled successfully, this function
|
||||||
/// returns `true`.
|
/// returns `true`.
|
||||||
pub fn abort(&mut self, mailbox: Mailbox) -> bool {
|
pub fn abort(&self, mailbox: Mailbox) -> bool {
|
||||||
// If the mailbox is empty, the value of TXOKx depends on what happened with the previous
|
// If the mailbox is empty, the value of TXOKx depends on what happened with the previous
|
||||||
// frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
|
// frame in that mailbox. Only call abort_by_index() if the mailbox is not empty.
|
||||||
let tsr = self.0.tsr().read();
|
let tsr = self.0.tsr().read();
|
||||||
|
|
|
@ -19,8 +19,8 @@ mod can_common;
|
||||||
use can_common::*;
|
use can_common::*;
|
||||||
|
|
||||||
type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>;
|
type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>;
|
||||||
type CanTx<'d> = embassy_stm32::can::CanTx<'d, embassy_stm32::peripherals::CAN1>;
|
type CanTx<'d> = embassy_stm32::can::CanTx<'d>;
|
||||||
type CanRx<'d> = embassy_stm32::can::CanRx<'d, embassy_stm32::peripherals::CAN1>;
|
type CanRx<'d> = embassy_stm32::can::CanRx<'d>;
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
CAN1_RX0 => Rx0InterruptHandler<CAN1>;
|
CAN1_RX0 => Rx0InterruptHandler<CAN1>;
|
||||||
|
|
Loading…
Add table
Reference in a new issue