Merge pull request #3956 from cschuhen/stm_can_count_instances_fix_3610
STM32 CAN: Count senders and receivers so that we don't close down early.
This commit is contained in:
commit
0cf951128d
@ -17,7 +17,7 @@ use self::registers::{Registers, RxFifo};
|
|||||||
pub use super::common::{BufferedCanReceiver, BufferedCanSender};
|
pub use super::common::{BufferedCanReceiver, BufferedCanSender};
|
||||||
use super::frame::{Envelope, Frame};
|
use super::frame::{Envelope, Frame};
|
||||||
use super::util;
|
use super::util;
|
||||||
use crate::can::enums::{BusError, TryReadError};
|
use crate::can::enums::{BusError, InternalOperation, TryReadError};
|
||||||
use crate::gpio::{AfType, OutputType, Pull, Speed};
|
use crate::gpio::{AfType, OutputType, Pull, Speed};
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
use crate::rcc::{self, RccPeripheral};
|
use crate::rcc::{self, RccPeripheral};
|
||||||
@ -685,22 +685,18 @@ impl<'d, const TX_BUF_SIZE: usize> BufferedCanTx<'d, TX_BUF_SIZE> {
|
|||||||
|
|
||||||
/// 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 {
|
||||||
|
(self.info.internal_operation)(InternalOperation::NotifySenderCreated);
|
||||||
BufferedCanSender {
|
BufferedCanSender {
|
||||||
tx_buf: self.tx_buf.sender().into(),
|
tx_buf: self.tx_buf.sender().into(),
|
||||||
waker: self.info.tx_waker,
|
waker: self.info.tx_waker,
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const TX_BUF_SIZE: usize> Drop for BufferedCanTx<'d, 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(|_| {
|
(self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +821,11 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
|
|||||||
|
|
||||||
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||||
pub fn reader(&self) -> BufferedCanReceiver {
|
pub fn reader(&self) -> BufferedCanReceiver {
|
||||||
self.rx_buf.receiver().into()
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
|
||||||
|
BufferedCanReceiver {
|
||||||
|
rx_buf: self.rx_buf.receiver().into(),
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accesses the filter banks owned by this CAN peripheral.
|
/// Accesses the filter banks owned by this CAN peripheral.
|
||||||
@ -839,13 +839,7 @@ impl<'d, const RX_BUF_SIZE: usize> BufferedCanRx<'d, RX_BUF_SIZE> {
|
|||||||
|
|
||||||
impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, 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(|_| {
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,6 +1042,8 @@ 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,
|
||||||
|
receiver_instance_count: usize,
|
||||||
|
sender_instance_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@ -1056,6 +1052,8 @@ impl State {
|
|||||||
rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
|
rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
|
||||||
tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
|
tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
|
||||||
err_waker: AtomicWaker::new(),
|
err_waker: AtomicWaker::new(),
|
||||||
|
receiver_instance_count: 1,
|
||||||
|
sender_instance_count: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1067,6 +1065,7 @@ pub(crate) struct Info {
|
|||||||
rx1_interrupt: crate::interrupt::Interrupt,
|
rx1_interrupt: crate::interrupt::Interrupt,
|
||||||
sce_interrupt: crate::interrupt::Interrupt,
|
sce_interrupt: crate::interrupt::Interrupt,
|
||||||
tx_waker: fn(),
|
tx_waker: fn(),
|
||||||
|
internal_operation: fn(InternalOperation),
|
||||||
|
|
||||||
/// The total number of filter banks available to the instance.
|
/// The total number of filter banks available to the instance.
|
||||||
///
|
///
|
||||||
@ -1079,6 +1078,7 @@ trait SealedInstance {
|
|||||||
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;
|
||||||
|
fn internal_operation(val: InternalOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CAN instance trait.
|
/// CAN instance trait.
|
||||||
@ -1136,6 +1136,7 @@ foreach_peripheral!(
|
|||||||
rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
|
rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
|
||||||
sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
|
sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
|
||||||
tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
|
tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
|
||||||
|
internal_operation: peripherals::$inst::internal_operation,
|
||||||
num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS,
|
num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS,
|
||||||
};
|
};
|
||||||
&INFO
|
&INFO
|
||||||
@ -1151,6 +1152,37 @@ foreach_peripheral!(
|
|||||||
fn state() -> &'static State {
|
fn state() -> &'static State {
|
||||||
unsafe { peripherals::$inst::mut_state() }
|
unsafe { peripherals::$inst::mut_state() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn internal_operation(val: InternalOperation) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
//let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
//let mut_state = state as *mut State;
|
||||||
|
let mut_state = peripherals::$inst::mut_state();
|
||||||
|
match val {
|
||||||
|
InternalOperation::NotifySenderCreated => {
|
||||||
|
mut_state.sender_instance_count += 1;
|
||||||
|
}
|
||||||
|
InternalOperation::NotifySenderDestroyed => {
|
||||||
|
mut_state.sender_instance_count -= 1;
|
||||||
|
if ( 0 == mut_state.sender_instance_count) {
|
||||||
|
(*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InternalOperation::NotifyReceiverCreated => {
|
||||||
|
mut_state.receiver_instance_count += 1;
|
||||||
|
}
|
||||||
|
InternalOperation::NotifyReceiverDestroyed => {
|
||||||
|
mut_state.receiver_instance_count -= 1;
|
||||||
|
if ( 0 == mut_state.receiver_instance_count) {
|
||||||
|
(*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance for peripherals::$inst {
|
impl Instance for peripherals::$inst {
|
||||||
|
|||||||
@ -22,22 +22,22 @@ pub(crate) struct FdBufferedTxInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sender that can be used for sending CAN frames.
|
/// Sender that can be used for sending CAN frames.
|
||||||
#[derive(Copy, Clone)]
|
pub struct BufferedSender<'ch, FRAME> {
|
||||||
pub struct BufferedCanSender {
|
pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'ch, FRAME>,
|
||||||
pub(crate) tx_buf: embassy_sync::channel::DynamicSender<'static, Frame>,
|
|
||||||
pub(crate) waker: fn(),
|
pub(crate) waker: fn(),
|
||||||
|
pub(crate) internal_operation: fn(InternalOperation),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferedCanSender {
|
impl<'ch, FRAME> BufferedSender<'ch, FRAME> {
|
||||||
/// Async write frame to TX buffer.
|
/// Async write frame to TX buffer.
|
||||||
pub fn try_write(&mut self, frame: Frame) -> Result<(), embassy_sync::channel::TrySendError<Frame>> {
|
pub fn try_write(&mut self, frame: FRAME) -> Result<(), embassy_sync::channel::TrySendError<FRAME>> {
|
||||||
self.tx_buf.try_send(frame)?;
|
self.tx_buf.try_send(frame)?;
|
||||||
(self.waker)();
|
(self.waker)();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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;
|
||||||
(self.waker)();
|
(self.waker)();
|
||||||
}
|
}
|
||||||
@ -48,5 +48,77 @@ impl BufferedCanSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ch, FRAME> Clone for BufferedSender<'ch, FRAME> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
(self.internal_operation)(InternalOperation::NotifySenderCreated);
|
||||||
|
Self {
|
||||||
|
tx_buf: self.tx_buf,
|
||||||
|
waker: self.waker,
|
||||||
|
internal_operation: self.internal_operation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ch, FRAME> Drop for BufferedSender<'ch, FRAME> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
(self.internal_operation)(InternalOperation::NotifySenderDestroyed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sender that can be used for sending Classic CAN frames.
|
||||||
|
pub type BufferedCanSender = BufferedSender<'static, Frame>;
|
||||||
|
|
||||||
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||||
pub type BufferedCanReceiver = embassy_sync::channel::DynamicReceiver<'static, Result<Envelope, BusError>>;
|
pub struct BufferedReceiver<'ch, ENVELOPE> {
|
||||||
|
pub(crate) rx_buf: embassy_sync::channel::DynamicReceiver<'ch, Result<ENVELOPE, BusError>>,
|
||||||
|
pub(crate) internal_operation: fn(InternalOperation),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ch, ENVELOPE> BufferedReceiver<'ch, ENVELOPE> {
|
||||||
|
/// Receive the next frame.
|
||||||
|
///
|
||||||
|
/// See [`Channel::receive()`].
|
||||||
|
pub fn receive(&self) -> embassy_sync::channel::DynamicReceiveFuture<'_, Result<ENVELOPE, BusError>> {
|
||||||
|
self.rx_buf.receive()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempt to immediately receive the next frame.
|
||||||
|
///
|
||||||
|
/// See [`Channel::try_receive()`]
|
||||||
|
pub fn try_receive(&self) -> Result<Result<ENVELOPE, BusError>, embassy_sync::channel::TryReceiveError> {
|
||||||
|
self.rx_buf.try_receive()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows a poll_fn to poll until the channel is ready to receive
|
||||||
|
///
|
||||||
|
/// See [`Channel::poll_ready_to_receive()`]
|
||||||
|
pub fn poll_ready_to_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
|
||||||
|
self.rx_buf.poll_ready_to_receive(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Poll the channel for the next frame
|
||||||
|
///
|
||||||
|
/// See [`Channel::poll_receive()`]
|
||||||
|
pub fn poll_receive(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<Result<ENVELOPE, BusError>> {
|
||||||
|
self.rx_buf.poll_receive(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ch, ENVELOPE> Clone for BufferedReceiver<'ch, ENVELOPE> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
(self.internal_operation)(InternalOperation::NotifyReceiverCreated);
|
||||||
|
Self {
|
||||||
|
rx_buf: self.rx_buf,
|
||||||
|
internal_operation: self.internal_operation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ch, ENVELOPE> Drop for BufferedReceiver<'ch, ENVELOPE> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
(self.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A BufferedCanReceiver for Classic CAN frames.
|
||||||
|
pub type BufferedCanReceiver = BufferedReceiver<'static, Envelope>;
|
||||||
|
|||||||
@ -68,3 +68,17 @@ pub enum TryReadError {
|
|||||||
/// Receive buffer is empty
|
/// Receive buffer is empty
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal Operation
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum InternalOperation {
|
||||||
|
/// Notify receiver created
|
||||||
|
NotifyReceiverCreated,
|
||||||
|
/// Notify receiver destroyed
|
||||||
|
NotifyReceiverDestroyed,
|
||||||
|
/// Notify sender created
|
||||||
|
NotifySenderCreated,
|
||||||
|
/// Notify sender destroyed
|
||||||
|
NotifySenderDestroyed,
|
||||||
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use core::task::Poll;
|
|||||||
use embassy_hal_internal::interrupt::InterruptExt;
|
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, DynamicReceiver, DynamicSender};
|
use embassy_sync::channel::Channel;
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
use crate::can::fd::peripheral::Registers;
|
use crate::can::fd::peripheral::Registers;
|
||||||
@ -478,28 +478,28 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d,
|
|||||||
|
|
||||||
/// 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 {
|
||||||
|
(self.info.internal_operation)(InternalOperation::NotifySenderCreated);
|
||||||
BufferedCanSender {
|
BufferedCanSender {
|
||||||
tx_buf: self.tx_buf.sender().into(),
|
tx_buf: self.tx_buf.sender().into(),
|
||||||
waker: self.info.tx_waker,
|
waker: self.info.tx_waker,
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||||
pub fn reader(&self) -> BufferedCanReceiver {
|
pub fn reader(&self) -> BufferedCanReceiver {
|
||||||
self.rx_buf.receiver().into()
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
|
||||||
|
BufferedCanReceiver {
|
||||||
|
rx_buf: self.rx_buf.receiver().into(),
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
critical_section::with(|_| {
|
(self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
|
||||||
let state = self.state as *const State;
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
|
||||||
unsafe {
|
|
||||||
let mut_state = state as *mut State;
|
|
||||||
(*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
|
||||||
(*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,35 +509,11 @@ pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Resul
|
|||||||
/// User supplied buffer for TX buffering
|
/// User supplied buffer for TX buffering
|
||||||
pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
|
pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
|
||||||
|
|
||||||
/// Sender that can be used for sending CAN frames.
|
/// Sender that can be used for sending Classic CAN frames.
|
||||||
#[derive(Copy, Clone)]
|
pub type BufferedFdCanSender = super::common::BufferedSender<'static, FdFrame>;
|
||||||
pub struct BufferedFdCanSender {
|
|
||||||
tx_buf: DynamicSender<'static, FdFrame>,
|
|
||||||
waker: fn(),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BufferedFdCanSender {
|
|
||||||
/// Async write frame to TX buffer.
|
|
||||||
pub fn try_write(&mut self, frame: FdFrame) -> Result<(), embassy_sync::channel::TrySendError<FdFrame>> {
|
|
||||||
self.tx_buf.try_send(frame)?;
|
|
||||||
(self.waker)();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Async write frame to TX buffer.
|
|
||||||
pub async fn write(&mut self, frame: FdFrame) {
|
|
||||||
self.tx_buf.send(frame).await;
|
|
||||||
(self.waker)();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allows a poll_fn to poll until the channel is ready to write
|
|
||||||
pub fn poll_ready_to_send(&self, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
|
|
||||||
self.tx_buf.poll_ready_to_send(cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||||
pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>;
|
pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnvelope>;
|
||||||
|
|
||||||
/// Buffered FDCAN Instance
|
/// Buffered FDCAN Instance
|
||||||
pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
|
||||||
@ -608,28 +584,28 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'
|
|||||||
|
|
||||||
/// 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) -> BufferedFdCanSender {
|
pub fn writer(&self) -> BufferedFdCanSender {
|
||||||
|
(self.info.internal_operation)(InternalOperation::NotifySenderCreated);
|
||||||
BufferedFdCanSender {
|
BufferedFdCanSender {
|
||||||
tx_buf: self.tx_buf.sender().into(),
|
tx_buf: self.tx_buf.sender().into(),
|
||||||
waker: self.info.tx_waker,
|
waker: self.info.tx_waker,
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
/// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
|
||||||
pub fn reader(&self) -> BufferedFdCanReceiver {
|
pub fn reader(&self) -> BufferedFdCanReceiver {
|
||||||
self.rx_buf.receiver().into()
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverCreated);
|
||||||
|
BufferedFdCanReceiver {
|
||||||
|
rx_buf: self.rx_buf.receiver().into(),
|
||||||
|
internal_operation: self.info.internal_operation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop for BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
critical_section::with(|_| {
|
(self.info.internal_operation)(InternalOperation::NotifySenderDestroyed);
|
||||||
let state = self.state as *const State;
|
(self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed);
|
||||||
unsafe {
|
|
||||||
let mut_state = state as *mut State;
|
|
||||||
(*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
|
||||||
(*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,6 +898,8 @@ struct State {
|
|||||||
pub rx_mode: RxMode,
|
pub rx_mode: RxMode,
|
||||||
pub tx_mode: TxMode,
|
pub tx_mode: TxMode,
|
||||||
pub ns_per_timer_tick: u64,
|
pub ns_per_timer_tick: u64,
|
||||||
|
receiver_instance_count: usize,
|
||||||
|
sender_instance_count: usize,
|
||||||
|
|
||||||
pub err_waker: AtomicWaker,
|
pub err_waker: AtomicWaker,
|
||||||
}
|
}
|
||||||
@ -933,6 +911,8 @@ impl State {
|
|||||||
tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
|
tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
|
||||||
ns_per_timer_tick: 0,
|
ns_per_timer_tick: 0,
|
||||||
err_waker: AtomicWaker::new(),
|
err_waker: AtomicWaker::new(),
|
||||||
|
receiver_instance_count: 1,
|
||||||
|
sender_instance_count: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -942,6 +922,7 @@ struct Info {
|
|||||||
interrupt0: crate::interrupt::Interrupt,
|
interrupt0: crate::interrupt::Interrupt,
|
||||||
_interrupt1: crate::interrupt::Interrupt,
|
_interrupt1: crate::interrupt::Interrupt,
|
||||||
tx_waker: fn(),
|
tx_waker: fn(),
|
||||||
|
internal_operation: fn(InternalOperation),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Info {
|
impl Info {
|
||||||
@ -970,6 +951,7 @@ trait SealedInstance {
|
|||||||
fn registers() -> crate::can::fd::peripheral::Registers;
|
fn registers() -> crate::can::fd::peripheral::Registers;
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
unsafe fn mut_state() -> &'static mut State;
|
unsafe fn mut_state() -> &'static mut State;
|
||||||
|
fn internal_operation(val: InternalOperation);
|
||||||
fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp;
|
fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,12 +974,42 @@ macro_rules! impl_fdcan {
|
|||||||
impl SealedInstance for peripherals::$inst {
|
impl SealedInstance for peripherals::$inst {
|
||||||
const MSG_RAM_OFFSET: usize = $msg_ram_offset;
|
const MSG_RAM_OFFSET: usize = $msg_ram_offset;
|
||||||
|
|
||||||
|
fn internal_operation(val: InternalOperation) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
//let state = self.state as *const State;
|
||||||
|
unsafe {
|
||||||
|
//let mut_state = state as *mut State;
|
||||||
|
let mut_state = peripherals::$inst::mut_state();
|
||||||
|
match val {
|
||||||
|
InternalOperation::NotifySenderCreated => {
|
||||||
|
mut_state.sender_instance_count += 1;
|
||||||
|
}
|
||||||
|
InternalOperation::NotifySenderDestroyed => {
|
||||||
|
mut_state.sender_instance_count -= 1;
|
||||||
|
if ( 0 == mut_state.sender_instance_count) {
|
||||||
|
(*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InternalOperation::NotifyReceiverCreated => {
|
||||||
|
mut_state.receiver_instance_count += 1;
|
||||||
|
}
|
||||||
|
InternalOperation::NotifyReceiverDestroyed => {
|
||||||
|
mut_state.receiver_instance_count -= 1;
|
||||||
|
if ( 0 == mut_state.receiver_instance_count) {
|
||||||
|
(*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
fn info() -> &'static Info {
|
fn info() -> &'static Info {
|
||||||
static INFO: Info = Info {
|
static INFO: Info = Info {
|
||||||
regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset},
|
regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset},
|
||||||
interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ,
|
interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ,
|
||||||
_interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ,
|
_interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ,
|
||||||
tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend,
|
tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend,
|
||||||
|
internal_operation: peripherals::$inst::internal_operation,
|
||||||
};
|
};
|
||||||
&INFO
|
&INFO
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user