#[allow(unused_variables)]
use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::PeripheralType;
use embassy_hal_internal::interrupt::InterruptExt;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use embassy_sync::waitqueue::AtomicWaker;
use crate::can::fd::peripheral::Registers;
use crate::gpio::{AfType, OutputType, Pull, SealedPin as _, Speed};
use crate::interrupt::typelevel::Interrupt;
use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral};
use crate::{Peri, interrupt, peripherals};
pub(crate) mod fd;
use self::fd::config::*;
use self::fd::filter::*;
pub use self::fd::{config, filter};
pub use super::common::{BufferedCanReceiver, BufferedCanSender};
use super::common::{InfoRef, RxInfoRef, TxInfoRef};
use super::enums::*;
use super::frame::*;
use super::util;
#[cfg(feature = "time")]
pub type Timestamp = embassy_time::Instant;
#[cfg(not(feature = "time"))]
pub type Timestamp = u16;
pub struct IT0InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> {
unsafe fn on_interrupt() {
let regs = T::registers().regs;
let ir = regs.ir().read();
if ir.tc() {
regs.ir().write(|w| w.set_tc(true));
}
if ir.tefn() {
regs.ir().write(|w| w.set_tefn(true));
}
let recover_from_bo = T::info().state.lock(|s| {
let state = s.borrow_mut();
match &state.tx_mode {
TxMode::NonBuffered(waker) => waker.wake(),
TxMode::ClassicBuffered(buf) => {
if !T::registers().tx_queue_is_full() {
match buf.tx_receiver.try_receive() {
Ok(frame) => {
_ = T::registers().write(&frame);
}
Err(_) => {}
}
}
}
TxMode::FdBuffered(buf) => {
if !T::registers().tx_queue_is_full() {
match buf.tx_receiver.try_receive() {
Ok(frame) => {
_ = T::registers().write(&frame);
}
Err(_) => {}
}
}
}
}
if ir.rfn(0) {
state.rx_mode.on_interrupt::<T>(0, state.ns_per_timer_tick);
}
if ir.rfn(1) {
state.rx_mode.on_interrupt::<T>(1, state.ns_per_timer_tick);
}
state.automatic_bus_off_recovery
});
if ir.bo() {
regs.ir().write(|w| w.set_bo(true));
if let Some(true) = recover_from_bo
&& regs.psr().read().bo()
{
regs.cccr().modify(|w| w.set_init(false));
}
}
}
}
pub struct IT1InterruptHandler<T: Instance> {
_phantom: PhantomData<T>,
}
impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1InterruptHandler<T> {
unsafe fn on_interrupt() {}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OperatingMode {
InternalLoopbackMode,
ExternalLoopbackMode,
NormalOperationMode,
RestrictedOperationMode,
BusMonitoringMode,
}
fn calc_ns_per_timer_tick(
info: &'static Info,
freq: crate::time::Hertz,
mode: crate::can::fd::config::FrameTransmissionConfig,
) -> u64 {
match mode {
crate::can::fd::config::FrameTransmissionConfig::ClassicCanOnly => {
let prescale: u64 = ({ info.regs.regs.nbtp().read().nbrp() } + 1) as u64
* ({ info.regs.regs.tscc().read().tcp() } + 1) as u64;
1_000_000_000 as u64 / (freq.0 as u64 * prescale)
}
_ => 0,
}
}
pub struct CanConfigurator<'d> {
_phantom: PhantomData<&'d ()>,
config: crate::can::fd::config::FdCanConfig,
properties: Properties,
periph_clock: crate::time::Hertz,
info: InfoRef,
}
impl<'d> CanConfigurator<'d> {
pub fn new<T: Instance>(
_peri: Peri<'d, T>,
rx: Peri<'d, impl RxPin<T>>,
tx: Peri<'d, impl TxPin<T>>,
_irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
+ interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
+ 'd,
) -> CanConfigurator<'d> {
set_as_af!(rx, AfType::input(Pull::None));
set_as_af!(tx, AfType::output(OutputType::PushPull, Speed::VeryHigh));
rcc::enable_and_reset::<T>();
let info = T::info();
T::info().state.lock(|s| {
s.borrow_mut().tx_pin_port = Some(tx.pin_port());
s.borrow_mut().rx_pin_port = Some(rx.pin_port());
});
let mut config = crate::can::fd::config::FdCanConfig::default();
config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1);
T::registers().into_config_mode(config);
unsafe {
T::IT0Interrupt::unpend(); T::IT0Interrupt::enable();
T::IT1Interrupt::unpend(); T::IT1Interrupt::enable();
}
Self {
_phantom: PhantomData,
config,
properties: Properties::new(T::info()),
periph_clock: T::frequency(),
info: InfoRef::new(info),
}
}
pub fn properties(&self) -> &Properties {
&self.properties
}
pub fn config(&self) -> crate::can::fd::config::FdCanConfig {
return self.config;
}
pub fn set_config(&mut self, config: crate::can::fd::config::FdCanConfig) {
self.config = config;
}
pub fn set_bitrate(&mut self, bitrate: u32) {
let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap();
let nbtr = crate::can::fd::config::NominalBitTiming {
sync_jump_width: bit_timing.sync_jump_width,
prescaler: bit_timing.prescaler,
seg1: bit_timing.seg1,
seg2: bit_timing.seg2,
};
self.config = self.config.set_nominal_bit_timing(nbtr);
}
pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) {
let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap();
let nbtr = crate::can::fd::config::DataBitTiming {
transceiver_delay_compensation,
sync_jump_width: bit_timing.sync_jump_width,
prescaler: bit_timing.prescaler,
seg1: bit_timing.seg1,
seg2: bit_timing.seg2,
};
self.config.frame_transmit = FrameTransmissionConfig::AllowFdCanAndBRS;
self.config = self.config.set_data_bit_timing(nbtr);
}
pub fn start(self, mode: OperatingMode) -> Can<'d> {
let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit);
self.info.state.lock(|s| {
let mut state = s.borrow_mut();
state.ns_per_timer_tick = ns_per_timer_tick;
state.automatic_bus_off_recovery = Some(self.config.automatic_bus_off_recovery);
});
self.info.regs.into_mode(self.config, mode);
Can {
_phantom: PhantomData,
config: self.config,
_mode: mode,
properties: Properties::new(&self.info),
info: InfoRef::new(&self.info),
}
}
pub fn into_normal_mode(self) -> Can<'d> {
self.start(OperatingMode::NormalOperationMode)
}
pub fn into_internal_loopback_mode(self) -> Can<'d> {
self.start(OperatingMode::InternalLoopbackMode)
}
pub fn into_external_loopback_mode(self) -> Can<'d> {
self.start(OperatingMode::ExternalLoopbackMode)
}
}
pub struct Can<'d> {
_phantom: PhantomData<&'d ()>,
config: crate::can::fd::config::FdCanConfig,
_mode: OperatingMode,
properties: Properties,
info: InfoRef,
}
impl<'d> Can<'d> {
pub fn properties(&self) -> &Properties {
&self.properties
}
pub async fn flush(&self, idx: usize) {
poll_fn(|cx| {
self.info.state.lock(|s| {
s.borrow_mut().tx_mode.register(cx.waker());
});
if idx > 3 {
panic!("Bad mailbox");
}
let idx = 1 << idx;
if !self.info.regs.regs.txbrp().read().trp(idx) {
return Poll::Ready(());
}
Poll::Pending
})
.await;
}
pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
TxMode::write(&self.info, frame).await
}
pub async fn read(&mut self) -> Result<Envelope, BusError> {
RxMode::read_classic(&self.info).await
}
pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
TxMode::write_fd(&self.info, frame).await
}
pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
RxMode::read_fd(&self.info).await
}
pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) {
(
CanTx {
_phantom: PhantomData,
config: self.config,
_mode: self._mode,
info: TxInfoRef::new(&self.info),
},
CanRx {
_phantom: PhantomData,
_mode: self._mode,
info: RxInfoRef::new(&self.info),
},
Properties {
info: self.properties.info,
},
)
}
pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self {
Can {
_phantom: PhantomData,
config: tx.config,
_mode: rx._mode,
properties: Properties::new(&tx.info),
info: InfoRef::new(&tx.info),
}
}
pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
self,
tx_buf: &'static mut TxBuf<TX_BUF_SIZE>,
rxb: &'static mut RxBuf<RX_BUF_SIZE>,
) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
BufferedCan::new(&self.info, self._mode, tx_buf, rxb)
}
pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
self,
tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>,
rxb: &'static mut RxFdBuf<RX_BUF_SIZE>,
) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
BufferedCanFd::new(&self.info, self._mode, tx_buf, rxb)
}
}
pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
_phantom: PhantomData<&'d ()>,
_mode: OperatingMode,
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
properties: Properties,
info: InfoRef,
}
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
fn new(
info: &'static Info,
_mode: OperatingMode,
tx_buf: &'static TxBuf<TX_BUF_SIZE>,
rx_buf: &'static RxBuf<RX_BUF_SIZE>,
) -> Self {
BufferedCan {
_phantom: PhantomData,
_mode,
tx_buf,
rx_buf,
properties: Properties::new(info),
info: InfoRef::new(info),
}
.setup()
}
pub fn properties(&self) -> &Properties {
&self.properties
}
fn setup(self) -> Self {
self.info.state.lock(|s| {
let rx_inner = super::common::ClassicBufferedRxInner {
rx_sender: self.rx_buf.sender().into(),
};
let tx_inner = super::common::ClassicBufferedTxInner {
tx_receiver: self.tx_buf.receiver().into(),
};
s.borrow_mut().rx_mode = RxMode::ClassicBuffered(rx_inner);
s.borrow_mut().tx_mode = TxMode::ClassicBuffered(tx_inner);
});
self
}
pub async fn write(&mut self, frame: Frame) {
self.tx_buf.send(frame).await;
self.info.interrupt0.pend(); }
pub async fn read(&mut self) -> Result<Envelope, BusError> {
self.rx_buf.receive().await
}
pub fn writer(&self) -> BufferedCanSender {
BufferedCanSender {
tx_buf: self.tx_buf.sender().into(),
info: TxInfoRef::new(&self.info),
}
}
pub fn reader(&self) -> BufferedCanReceiver {
BufferedCanReceiver {
rx_buf: self.rx_buf.receiver().into(),
info: RxInfoRef::new(&self.info),
}
}
}
pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>;
pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
pub type BufferedFdCanSender = super::common::BufferedSender<'static, FdFrame>;
pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnvelope>;
pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
_phantom: PhantomData<&'d ()>,
_mode: OperatingMode,
tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
properties: Properties,
info: InfoRef,
}
impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
fn new(
info: &'static Info,
_mode: OperatingMode,
tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
) -> Self {
BufferedCanFd {
_phantom: PhantomData,
_mode,
tx_buf,
rx_buf,
properties: Properties::new(info),
info: InfoRef::new(info),
}
.setup()
}
pub fn properties(&self) -> &Properties {
&self.properties
}
fn setup(self) -> Self {
self.info.state.lock(|s| {
let rx_inner = super::common::FdBufferedRxInner {
rx_sender: self.rx_buf.sender().into(),
};
let tx_inner = super::common::FdBufferedTxInner {
tx_receiver: self.tx_buf.receiver().into(),
};
s.borrow_mut().rx_mode = RxMode::FdBuffered(rx_inner);
s.borrow_mut().tx_mode = TxMode::FdBuffered(tx_inner);
});
self
}
pub async fn write(&mut self, frame: FdFrame) {
self.tx_buf.send(frame).await;
self.info.interrupt0.pend(); }
pub async fn read(&mut self) -> Result<FdEnvelope, BusError> {
self.rx_buf.receive().await
}
pub fn writer(&self) -> BufferedFdCanSender {
BufferedFdCanSender {
tx_buf: self.tx_buf.sender().into(),
info: TxInfoRef::new(&self.info),
}
}
pub fn reader(&self) -> BufferedFdCanReceiver {
BufferedFdCanReceiver {
rx_buf: self.rx_buf.receiver().into(),
info: RxInfoRef::new(&self.info),
}
}
}
pub struct CanRx<'d> {
_phantom: PhantomData<&'d ()>,
_mode: OperatingMode,
info: RxInfoRef,
}
impl<'d> CanRx<'d> {
pub async fn read(&mut self) -> Result<Envelope, BusError> {
RxMode::read_classic(&self.info).await
}
pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
RxMode::read_fd(&self.info).await
}
}
pub struct CanTx<'d> {
_phantom: PhantomData<&'d ()>,
config: crate::can::fd::config::FdCanConfig,
_mode: OperatingMode,
info: TxInfoRef,
}
impl<'c, 'd> CanTx<'d> {
pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
TxMode::write(&self.info, frame).await
}
pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
TxMode::write_fd(&self.info, frame).await
}
}
enum RxMode {
NonBuffered(AtomicWaker),
ClassicBuffered(super::common::ClassicBufferedRxInner),
FdBuffered(super::common::FdBufferedRxInner),
}
impl RxMode {
fn register(&self, arg: &core::task::Waker) {
match self {
RxMode::NonBuffered(waker) => waker.register(arg),
_ => {
panic!("Bad Mode")
}
}
}
fn on_interrupt<T: Instance>(&self, fifonr: usize, ns_per_timer_tick: u64) {
match self {
RxMode::NonBuffered(waker) => {
T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true));
waker.wake();
}
RxMode::ClassicBuffered(buf) => {
T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true));
loop {
match self.try_read::<T>(ns_per_timer_tick) {
Some(Ok(envelope)) => {
let _ = buf.rx_sender.try_send(Ok(envelope));
}
Some(Err(err)) => {
let _ = buf.rx_sender.try_send(Err(err));
break;
}
None => break,
}
}
}
RxMode::FdBuffered(buf) => {
T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true));
loop {
match self.try_read_fd::<T>(ns_per_timer_tick) {
Some(Ok(envelope)) => {
let _ = buf.rx_sender.try_send(Ok(envelope));
}
Some(Err(err)) => {
let _ = buf.rx_sender.try_send(Err(err));
break;
}
None => break,
}
}
}
}
}
fn try_read<T: Instance>(&self, ns_per_timer_tick: u64) -> Option<Result<Envelope, BusError>> {
if let Some((frame, ts)) = T::registers().read(0) {
let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
Some(Ok(Envelope { ts, frame }))
} else if let Some((frame, ts)) = T::registers().read(1) {
let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
Some(Ok(Envelope { ts, frame }))
} else if let Some(err) = T::registers().curr_error() {
Some(Err(err))
} else {
None
}
}
fn try_read_fd<T: Instance>(&self, ns_per_timer_tick: u64) -> Option<Result<FdEnvelope, BusError>> {
if let Some((frame, ts)) = T::registers().read(0) {
let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
Some(Ok(FdEnvelope { ts, frame }))
} else if let Some((frame, ts)) = T::registers().read(1) {
let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
Some(Ok(FdEnvelope { ts, frame }))
} else if let Some(err) = T::registers().curr_error() {
Some(Err(err))
} else {
None
}
}
fn read<F: CanHeader>(info: &'static Info, ns_per_timer_tick: u64) -> Option<Result<(F, Timestamp), BusError>> {
if let Some((msg, ts)) = info.regs.read(0) {
let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts);
Some(Ok((msg, ts)))
} else if let Some((msg, ts)) = info.regs.read(1) {
let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts);
Some(Ok((msg, ts)))
} else if let Some(err) = info.regs.curr_error() {
Some(Err(err))
} else {
None
}
}
async fn read_async<F: CanHeader>(info: &'static Info) -> Result<(F, Timestamp), BusError> {
poll_fn(move |cx| {
let ns_per_timer_tick = info.state.lock(|s| {
let state = s.borrow_mut();
state.err_waker.register(cx.waker());
state.rx_mode.register(cx.waker());
state.ns_per_timer_tick
});
match RxMode::read::<_>(info, ns_per_timer_tick) {
Some(result) => Poll::Ready(result),
None => Poll::Pending,
}
})
.await
}
async fn read_classic(info: &'static Info) -> Result<Envelope, BusError> {
match RxMode::read_async::<_>(info).await {
Ok((frame, ts)) => Ok(Envelope { ts, frame }),
Err(e) => Err(e),
}
}
async fn read_fd(info: &'static Info) -> Result<FdEnvelope, BusError> {
match RxMode::read_async::<_>(info).await {
Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }),
Err(e) => Err(e),
}
}
}
enum TxMode {
NonBuffered(AtomicWaker),
ClassicBuffered(super::common::ClassicBufferedTxInner),
FdBuffered(super::common::FdBufferedTxInner),
}
impl TxMode {
fn register(&self, arg: &core::task::Waker) {
match self {
TxMode::NonBuffered(waker) => {
waker.register(arg);
}
_ => {
panic!("Bad mode");
}
}
}
async fn write_generic<F: embedded_can::Frame + CanHeader>(info: &'static Info, frame: &F) -> Option<F> {
poll_fn(|cx| {
info.state.lock(|s| {
s.borrow_mut().tx_mode.register(cx.waker());
});
if let Ok(dropped) = info.regs.write(frame) {
return Poll::Ready(dropped);
}
Poll::Pending
})
.await
}
async fn write(info: &'static Info, frame: &Frame) -> Option<Frame> {
TxMode::write_generic::<_>(info, frame).await
}
async fn write_fd(info: &'static Info, frame: &FdFrame) -> Option<FdFrame> {
TxMode::write_generic::<_>(info, frame).await
}
}
pub struct Properties {
info: &'static Info,
}
impl Properties {
fn new(info: &'static Info) -> Self {
Self {
info,
}
}
#[inline]
pub fn set_standard_filter(&self, slot: StandardFilterSlot, filter: StandardFilter) {
self.info.regs.msg_ram_mut().filters.flssa[slot as usize].activate(filter);
}
pub fn set_standard_filters(&self, filters: &[StandardFilter; STANDARD_FILTER_MAX as usize]) {
for (i, f) in filters.iter().enumerate() {
self.info.regs.msg_ram_mut().filters.flssa[i].activate(*f);
}
}
#[inline]
pub fn set_extended_filter(&self, slot: ExtendedFilterSlot, filter: ExtendedFilter) {
self.info.regs.msg_ram_mut().filters.flesa[slot as usize].activate(filter);
}
pub fn set_extended_filters(&self, filters: &[ExtendedFilter; EXTENDED_FILTER_MAX as usize]) {
for (i, f) in filters.iter().enumerate() {
self.info.regs.msg_ram_mut().filters.flesa[i].activate(*f);
}
}
pub fn rx_error_count(&self) -> u8 {
self.info.regs.regs.ecr().read().rec()
}
pub fn tx_error_count(&self) -> u8 {
self.info.regs.regs.ecr().read().tec()
}
pub fn bus_error_mode(&self) -> BusErrorMode {
let psr = self.info.regs.regs.psr().read();
match (psr.bo(), psr.ep()) {
(false, false) => BusErrorMode::ErrorActive,
(false, true) => BusErrorMode::ErrorPassive,
(true, _) => BusErrorMode::BusOff,
}
}
}
struct State {
pub rx_mode: RxMode,
pub tx_mode: TxMode,
pub ns_per_timer_tick: u64,
receiver_instance_count: usize,
sender_instance_count: usize,
tx_pin_port: Option<u8>,
rx_pin_port: Option<u8>,
automatic_bus_off_recovery: Option<bool>, pub err_waker: AtomicWaker,
}
impl State {
const fn new() -> Self {
Self {
rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
ns_per_timer_tick: 0,
err_waker: AtomicWaker::new(),
receiver_instance_count: 0,
sender_instance_count: 0,
tx_pin_port: None,
rx_pin_port: None,
automatic_bus_off_recovery: None,
}
}
}
type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<State>>;
pub(crate) struct Info {
regs: Registers,
interrupt0: crate::interrupt::Interrupt,
_interrupt1: crate::interrupt::Interrupt,
pub(crate) tx_waker: fn(),
state: SharedState,
rcc_info: RccInfo,
}
impl Info {
pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) {
self.state.lock(|s| {
let mut mut_state = s.borrow_mut();
match val {
RefCountOp::NotifySenderCreated => {
mut_state.sender_instance_count += 1;
}
RefCountOp::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());
}
}
RefCountOp::NotifyReceiverCreated => {
mut_state.receiver_instance_count += 1;
}
RefCountOp::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());
}
}
}
if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 {
unsafe {
let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap());
tx_pin.set_as_disconnected();
let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap());
rx_pin.set_as_disconnected();
self.interrupt0.disable();
self.rcc_info.disable();
}
}
});
}
}
trait SealedInstance {
const MSG_RAM_OFFSET: usize;
fn info() -> &'static Info;
fn registers() -> crate::can::fd::peripheral::Registers;
}
#[allow(private_bounds)]
pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + 'static {
type IT0Interrupt: crate::interrupt::typelevel::Interrupt;
type IT1Interrupt: crate::interrupt::typelevel::Interrupt;
}
pub struct FdcanInstance<'a, T: Instance>(Peri<'a, T>);
macro_rules! impl_fdcan {
($inst:ident,
//$irq0:ident, $irq1:ident,
$msg_ram_inst:ident, $msg_ram_offset:literal) => {
impl SealedInstance for peripherals::$inst {
const MSG_RAM_OFFSET: usize = $msg_ram_offset;
fn info() -> &'static Info {
static INFO: Info = Info {
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,
_interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ,
tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend,
state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())),
rcc_info: crate::peripherals::$inst::RCC_INFO,
};
&INFO
}
fn registers() -> Registers {
Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET}
}
}
#[allow(non_snake_case)]
pub(crate) mod $inst {
foreach_interrupt!(
($inst,can,FDCAN,IT0,$irq:ident) => {
pub type Interrupt0 = crate::interrupt::typelevel::$irq;
};
($inst,can,FDCAN,IT1,$irq:ident) => {
pub type Interrupt1 = crate::interrupt::typelevel::$irq;
};
);
}
impl Instance for peripherals::$inst {
type IT0Interrupt = $inst::Interrupt0;
type IT1Interrupt = $inst::Interrupt1;
}
};
($inst:ident, $msg_ram_inst:ident) => {
impl_fdcan!($inst, $msg_ram_inst, 0);
};
}
#[cfg(not(can_fdcan_h7))]
foreach_peripheral!(
(can, FDCAN) => { impl_fdcan!(FDCAN, FDCANRAM); };
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM1); };
(can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM2); };
(can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM3); };
);
#[cfg(can_fdcan_h7)]
foreach_peripheral!(
(can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM, 0x0000); };
(can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM, 0x0C00); };
(can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM, 0x1800); };
);
pin_trait!(RxPin, Instance);
pin_trait!(TxPin, Instance);