embassy_stm32/can/
fdcan.rs

1#[allow(unused_variables)]
2use core::future::poll_fn;
3use core::marker::PhantomData;
4use core::task::Poll;
5
6use embassy_hal_internal::interrupt::InterruptExt;
7use embassy_hal_internal::PeripheralType;
8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9use embassy_sync::channel::Channel;
10use embassy_sync::waitqueue::AtomicWaker;
11
12use crate::can::fd::peripheral::Registers;
13use crate::gpio::{AfType, OutputType, Pull, SealedPin as _, Speed};
14use crate::interrupt::typelevel::Interrupt;
15use crate::rcc::{self, RccPeripheral};
16use crate::{interrupt, peripherals, Peri};
17
18pub(crate) mod fd;
19
20use self::fd::config::*;
21use self::fd::filter::*;
22pub use self::fd::{config, filter};
23pub use super::common::{BufferedCanReceiver, BufferedCanSender};
24use super::common::{InfoRef, RxInfoRef, TxInfoRef};
25use super::enums::*;
26use super::frame::*;
27use super::util;
28
29/// Timestamp for incoming packets. Use Embassy time when enabled.
30#[cfg(feature = "time")]
31pub type Timestamp = embassy_time::Instant;
32
33/// Timestamp for incoming packets.
34#[cfg(not(feature = "time"))]
35pub type Timestamp = u16;
36
37/// Interrupt handler channel 0.
38pub struct IT0InterruptHandler<T: Instance> {
39    _phantom: PhantomData<T>,
40}
41
42// We use IT0 for everything currently
43impl<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> for IT0InterruptHandler<T> {
44    unsafe fn on_interrupt() {
45        let regs = T::registers().regs;
46
47        let ir = regs.ir().read();
48
49        if ir.tc() {
50            regs.ir().write(|w| w.set_tc(true));
51        }
52        if ir.tefn() {
53            regs.ir().write(|w| w.set_tefn(true));
54        }
55
56        T::info().state.lock(|s| {
57            let state = s.borrow_mut();
58            match &state.tx_mode {
59                TxMode::NonBuffered(waker) => waker.wake(),
60                TxMode::ClassicBuffered(buf) => {
61                    if !T::registers().tx_queue_is_full() {
62                        match buf.tx_receiver.try_receive() {
63                            Ok(frame) => {
64                                _ = T::registers().write(&frame);
65                            }
66                            Err(_) => {}
67                        }
68                    }
69                }
70                TxMode::FdBuffered(buf) => {
71                    if !T::registers().tx_queue_is_full() {
72                        match buf.tx_receiver.try_receive() {
73                            Ok(frame) => {
74                                _ = T::registers().write(&frame);
75                            }
76                            Err(_) => {}
77                        }
78                    }
79                }
80            }
81
82            if ir.rfn(0) {
83                state.rx_mode.on_interrupt::<T>(0, state.ns_per_timer_tick);
84            }
85            if ir.rfn(1) {
86                state.rx_mode.on_interrupt::<T>(1, state.ns_per_timer_tick);
87            }
88        });
89
90        if ir.bo() {
91            regs.ir().write(|w| w.set_bo(true));
92            if regs.psr().read().bo() {
93                // Initiate bus-off recovery sequence by resetting CCCR.INIT
94                regs.cccr().modify(|w| w.set_init(false));
95            }
96        }
97    }
98}
99
100/// Interrupt handler channel 1.
101pub struct IT1InterruptHandler<T: Instance> {
102    _phantom: PhantomData<T>,
103}
104
105impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1InterruptHandler<T> {
106    unsafe fn on_interrupt() {}
107}
108
109#[derive(Debug, Copy, Clone, Eq, PartialEq)]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111/// Different operating modes
112pub enum OperatingMode {
113    //PoweredDownMode,
114    //ConfigMode,
115    /// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without
116    /// affecting a running CAN system connected to the FDCAN_TX and FDCAN_RX pins. In this
117    /// mode, FDCAN_RX pin is disconnected from the FDCAN and FDCAN_TX pin is held
118    /// recessive.
119    InternalLoopbackMode,
120    /// This mode is provided for hardware self-test. To be independent from external stimulation,
121    /// the FDCAN ignores acknowledge errors (recessive bit sampled in the acknowledge slot of a
122    /// data / remote frame) in Loop Back mode. In this mode the FDCAN performs an internal
123    /// feedback from its transmit output to its receive input. The actual value of the FDCAN_RX
124    /// input pin is disregarded by the FDCAN. The transmitted messages can be monitored at the
125    /// FDCAN_TX transmit pin.
126    ExternalLoopbackMode,
127    /// The normal use of the Fdcan instance after configurations
128    NormalOperationMode,
129    /// In Restricted operation mode the node is able to receive data and remote frames and to give
130    /// acknowledge to valid frames, but it does not send data frames, remote frames, active error
131    /// frames, or overload frames. In case of an error condition or overload condition, it does not
132    /// send dominant bits, instead it waits for the occurrence of bus idle condition to resynchronize
133    /// itself to the CAN communication. The error counters for transmit and receive are frozen while
134    /// error logging (can_errors) is active. TODO: automatically enter in this mode?
135    RestrictedOperationMode,
136    ///  In Bus monitoring mode (for more details refer to ISO11898-1, 10.12 Bus monitoring),
137    /// the FDCAN is able to receive valid data frames and valid remote frames, but cannot start a
138    /// transmission. In this mode, it sends only recessive bits on the CAN bus. If the FDCAN is
139    /// required to send a dominant bit (ACK bit, overload flag, active error flag), the bit is
140    /// rerouted internally so that the FDCAN can monitor it, even if the CAN bus remains in recessive
141    /// state. In Bus monitoring mode the TXBRP register is held in reset state. The Bus monitoring
142    /// mode can be used to analyze the traffic on a CAN bus without affecting it by the transmission
143    /// of dominant bits.
144    BusMonitoringMode,
145    //TestMode,
146}
147
148fn calc_ns_per_timer_tick(
149    info: &'static Info,
150    freq: crate::time::Hertz,
151    mode: crate::can::fd::config::FrameTransmissionConfig,
152) -> u64 {
153    match mode {
154        // Use timestamp from Rx FIFO to adjust timestamp reported to user
155        crate::can::fd::config::FrameTransmissionConfig::ClassicCanOnly => {
156            let prescale: u64 = ({ info.regs.regs.nbtp().read().nbrp() } + 1) as u64
157                * ({ info.regs.regs.tscc().read().tcp() } + 1) as u64;
158            1_000_000_000 as u64 / (freq.0 as u64 * prescale)
159        }
160        // For VBR this is too hard because the FDCAN timer switches clock rate you need to configure to use
161        // timer3 instead which is too hard to do from this module.
162        _ => 0,
163    }
164}
165
166/// FDCAN Configuration instance instance
167/// Create instance of this first
168pub struct CanConfigurator<'d> {
169    _phantom: PhantomData<&'d ()>,
170    config: crate::can::fd::config::FdCanConfig,
171    /// Reference to internals.
172    properties: Properties,
173    periph_clock: crate::time::Hertz,
174    info: InfoRef,
175}
176
177impl<'d> CanConfigurator<'d> {
178    /// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
179    /// You must call [Fdcan::enable_non_blocking] to use the peripheral.
180    pub fn new<T: Instance>(
181        _peri: Peri<'d, T>,
182        rx: Peri<'d, impl RxPin<T>>,
183        tx: Peri<'d, impl TxPin<T>>,
184        _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
185            + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
186            + 'd,
187    ) -> CanConfigurator<'d> {
188        rx.set_as_af(rx.af_num(), AfType::input(Pull::None));
189        tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
190
191        rcc::enable_and_reset::<T>();
192
193        let info = T::info();
194        T::info().state.lock(|s| {
195            s.borrow_mut().tx_pin_port = Some(tx.pin_port());
196            s.borrow_mut().rx_pin_port = Some(rx.pin_port());
197        });
198
199        let mut config = crate::can::fd::config::FdCanConfig::default();
200        config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1);
201        T::registers().into_config_mode(config);
202
203        unsafe {
204            T::IT0Interrupt::unpend(); // Not unsafe
205            T::IT0Interrupt::enable();
206
207            T::IT1Interrupt::unpend(); // Not unsafe
208            T::IT1Interrupt::enable();
209        }
210        Self {
211            _phantom: PhantomData,
212            config,
213            properties: Properties::new(T::info()),
214            periph_clock: T::frequency(),
215            info: InfoRef::new(info),
216        }
217    }
218
219    /// Get driver properties
220    pub fn properties(&self) -> &Properties {
221        &self.properties
222    }
223
224    /// Get configuration
225    pub fn config(&self) -> crate::can::fd::config::FdCanConfig {
226        return self.config;
227    }
228
229    /// Set configuration
230    pub fn set_config(&mut self, config: crate::can::fd::config::FdCanConfig) {
231        self.config = config;
232    }
233
234    /// Configures the bit timings calculated from supplied bitrate.
235    pub fn set_bitrate(&mut self, bitrate: u32) {
236        let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap();
237
238        let nbtr = crate::can::fd::config::NominalBitTiming {
239            sync_jump_width: bit_timing.sync_jump_width,
240            prescaler: bit_timing.prescaler,
241            seg1: bit_timing.seg1,
242            seg2: bit_timing.seg2,
243        };
244        self.config = self.config.set_nominal_bit_timing(nbtr);
245    }
246
247    /// Configures the bit timings for VBR data calculated from supplied bitrate. This also sets confit to allow can FD and VBR
248    pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) {
249        let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap();
250        // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M
251        let nbtr = crate::can::fd::config::DataBitTiming {
252            transceiver_delay_compensation,
253            sync_jump_width: bit_timing.sync_jump_width,
254            prescaler: bit_timing.prescaler,
255            seg1: bit_timing.seg1,
256            seg2: bit_timing.seg2,
257        };
258        self.config.frame_transmit = FrameTransmissionConfig::AllowFdCanAndBRS;
259        self.config = self.config.set_data_bit_timing(nbtr);
260    }
261
262    /// Start in mode.
263    pub fn start(self, mode: OperatingMode) -> Can<'d> {
264        let ns_per_timer_tick = calc_ns_per_timer_tick(&self.info, self.periph_clock, self.config.frame_transmit);
265        self.info.state.lock(|s| {
266            s.borrow_mut().ns_per_timer_tick = ns_per_timer_tick;
267        });
268        self.info.regs.into_mode(self.config, mode);
269        Can {
270            _phantom: PhantomData,
271            config: self.config,
272            _mode: mode,
273            properties: Properties::new(&self.info),
274            info: InfoRef::new(&self.info),
275        }
276    }
277
278    /// Start, entering mode. Does same as start(mode)
279    pub fn into_normal_mode(self) -> Can<'d> {
280        self.start(OperatingMode::NormalOperationMode)
281    }
282
283    /// Start, entering mode. Does same as start(mode)
284    pub fn into_internal_loopback_mode(self) -> Can<'d> {
285        self.start(OperatingMode::InternalLoopbackMode)
286    }
287
288    /// Start, entering mode. Does same as start(mode)
289    pub fn into_external_loopback_mode(self) -> Can<'d> {
290        self.start(OperatingMode::ExternalLoopbackMode)
291    }
292}
293
294/// FDCAN Instance
295pub struct Can<'d> {
296    _phantom: PhantomData<&'d ()>,
297    config: crate::can::fd::config::FdCanConfig,
298    _mode: OperatingMode,
299    properties: Properties,
300    info: InfoRef,
301}
302
303impl<'d> Can<'d> {
304    /// Get driver properties
305    pub fn properties(&self) -> &Properties {
306        &self.properties
307    }
308
309    /// Flush one of the TX mailboxes.
310    pub async fn flush(&self, idx: usize) {
311        poll_fn(|cx| {
312            self.info.state.lock(|s| {
313                s.borrow_mut().tx_mode.register(cx.waker());
314            });
315
316            if idx > 3 {
317                panic!("Bad mailbox");
318            }
319            let idx = 1 << idx;
320            if !self.info.regs.regs.txbrp().read().trp(idx) {
321                return Poll::Ready(());
322            }
323
324            Poll::Pending
325        })
326        .await;
327    }
328
329    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
330    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
331    /// can be replaced, this call asynchronously waits for a frame to be successfully
332    /// transmitted, then tries again.
333    pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
334        TxMode::write(&self.info, frame).await
335    }
336
337    /// Returns the next received message frame
338    pub async fn read(&mut self) -> Result<Envelope, BusError> {
339        RxMode::read_classic(&self.info).await
340    }
341
342    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
343    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
344    /// can be replaced, this call asynchronously waits for a frame to be successfully
345    /// transmitted, then tries again.
346    pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
347        TxMode::write_fd(&self.info, frame).await
348    }
349
350    /// Returns the next received message frame
351    pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
352        RxMode::read_fd(&self.info).await
353    }
354
355    /// Split instance into separate portions: Tx(write), Rx(read), common properties
356    pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) {
357        (
358            CanTx {
359                _phantom: PhantomData,
360                config: self.config,
361                _mode: self._mode,
362                info: TxInfoRef::new(&self.info),
363            },
364            CanRx {
365                _phantom: PhantomData,
366                _mode: self._mode,
367                info: RxInfoRef::new(&self.info),
368            },
369            Properties {
370                info: self.properties.info,
371            },
372        )
373    }
374    /// Join split rx and tx portions back together
375    pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self {
376        Can {
377            _phantom: PhantomData,
378            config: tx.config,
379            _mode: rx._mode,
380            properties: Properties::new(&tx.info),
381            info: InfoRef::new(&tx.info),
382        }
383    }
384
385    /// Return a buffered instance of driver without CAN FD support. User must supply Buffers
386    pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
387        self,
388        tx_buf: &'static mut TxBuf<TX_BUF_SIZE>,
389        rxb: &'static mut RxBuf<RX_BUF_SIZE>,
390    ) -> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
391        BufferedCan::new(&self.info, self._mode, tx_buf, rxb)
392    }
393
394    /// Return a buffered instance of driver with CAN FD support. User must supply Buffers
395    pub fn buffered_fd<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
396        self,
397        tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>,
398        rxb: &'static mut RxFdBuf<RX_BUF_SIZE>,
399    ) -> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
400        BufferedCanFd::new(&self.info, self._mode, tx_buf, rxb)
401    }
402}
403
404/// User supplied buffer for RX Buffering
405pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>;
406
407/// User supplied buffer for TX buffering
408pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>;
409
410/// Buffered FDCAN Instance
411pub struct BufferedCan<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
412    _phantom: PhantomData<&'d ()>,
413    _mode: OperatingMode,
414    tx_buf: &'static TxBuf<TX_BUF_SIZE>,
415    rx_buf: &'static RxBuf<RX_BUF_SIZE>,
416    properties: Properties,
417    info: InfoRef,
418}
419
420impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
421    fn new(
422        info: &'static Info,
423        _mode: OperatingMode,
424        tx_buf: &'static TxBuf<TX_BUF_SIZE>,
425        rx_buf: &'static RxBuf<RX_BUF_SIZE>,
426    ) -> Self {
427        BufferedCan {
428            _phantom: PhantomData,
429            _mode,
430            tx_buf,
431            rx_buf,
432            properties: Properties::new(info),
433            info: InfoRef::new(info),
434        }
435        .setup()
436    }
437
438    /// Get driver properties
439    pub fn properties(&self) -> &Properties {
440        &self.properties
441    }
442
443    fn setup(self) -> Self {
444        // We don't want interrupts being processed while we change modes.
445        self.info.state.lock(|s| {
446            let rx_inner = super::common::ClassicBufferedRxInner {
447                rx_sender: self.rx_buf.sender().into(),
448            };
449            let tx_inner = super::common::ClassicBufferedTxInner {
450                tx_receiver: self.tx_buf.receiver().into(),
451            };
452            s.borrow_mut().rx_mode = RxMode::ClassicBuffered(rx_inner);
453            s.borrow_mut().tx_mode = TxMode::ClassicBuffered(tx_inner);
454        });
455        self
456    }
457
458    /// Async write frame to TX buffer.
459    pub async fn write(&mut self, frame: Frame) {
460        self.tx_buf.send(frame).await;
461        self.info.interrupt0.pend(); // Wake for Tx
462                                     //T::IT0Interrupt::pend(); // Wake for Tx
463    }
464
465    /// Async read frame from RX buffer.
466    pub async fn read(&mut self) -> Result<Envelope, BusError> {
467        self.rx_buf.receive().await
468    }
469
470    /// Returns a sender that can be used for sending CAN frames.
471    pub fn writer(&self) -> BufferedCanSender {
472        BufferedCanSender {
473            tx_buf: self.tx_buf.sender().into(),
474            info: TxInfoRef::new(&self.info),
475        }
476    }
477
478    /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
479    pub fn reader(&self) -> BufferedCanReceiver {
480        BufferedCanReceiver {
481            rx_buf: self.rx_buf.receiver().into(),
482            info: RxInfoRef::new(&self.info),
483        }
484    }
485}
486
487/// User supplied buffer for RX Buffering
488pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>;
489
490/// User supplied buffer for TX buffering
491pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
492
493/// Sender that can be used for sending Classic CAN frames.
494pub type BufferedFdCanSender = super::common::BufferedSender<'static, FdFrame>;
495
496/// Receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
497pub type BufferedFdCanReceiver = super::common::BufferedReceiver<'static, FdEnvelope>;
498
499/// Buffered FDCAN Instance
500pub struct BufferedCanFd<'d, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
501    _phantom: PhantomData<&'d ()>,
502    _mode: OperatingMode,
503    tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
504    rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
505    properties: Properties,
506    info: InfoRef,
507}
508
509impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<'d, TX_BUF_SIZE, RX_BUF_SIZE> {
510    fn new(
511        info: &'static Info,
512        _mode: OperatingMode,
513        tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
514        rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
515    ) -> Self {
516        BufferedCanFd {
517            _phantom: PhantomData,
518            _mode,
519            tx_buf,
520            rx_buf,
521            properties: Properties::new(info),
522            info: InfoRef::new(info),
523        }
524        .setup()
525    }
526
527    /// Get driver properties
528    pub fn properties(&self) -> &Properties {
529        &self.properties
530    }
531
532    fn setup(self) -> Self {
533        // We don't want interrupts being processed while we change modes.
534        self.info.state.lock(|s| {
535            let rx_inner = super::common::FdBufferedRxInner {
536                rx_sender: self.rx_buf.sender().into(),
537            };
538            let tx_inner = super::common::FdBufferedTxInner {
539                tx_receiver: self.tx_buf.receiver().into(),
540            };
541            s.borrow_mut().rx_mode = RxMode::FdBuffered(rx_inner);
542            s.borrow_mut().tx_mode = TxMode::FdBuffered(tx_inner);
543        });
544        self
545    }
546
547    /// Async write frame to TX buffer.
548    pub async fn write(&mut self, frame: FdFrame) {
549        self.tx_buf.send(frame).await;
550        self.info.interrupt0.pend(); // Wake for Tx
551                                     //T::IT0Interrupt::pend(); // Wake for Tx
552    }
553
554    /// Async read frame from RX buffer.
555    pub async fn read(&mut self) -> Result<FdEnvelope, BusError> {
556        self.rx_buf.receive().await
557    }
558
559    /// Returns a sender that can be used for sending CAN frames.
560    pub fn writer(&self) -> BufferedFdCanSender {
561        BufferedFdCanSender {
562            tx_buf: self.tx_buf.sender().into(),
563            info: TxInfoRef::new(&self.info),
564        }
565    }
566
567    /// Returns a receiver that can be used for receiving CAN frames. Note, each CAN frame will only be received by one receiver.
568    pub fn reader(&self) -> BufferedFdCanReceiver {
569        BufferedFdCanReceiver {
570            rx_buf: self.rx_buf.receiver().into(),
571            info: RxInfoRef::new(&self.info),
572        }
573    }
574}
575
576/// FDCAN Rx only Instance
577pub struct CanRx<'d> {
578    _phantom: PhantomData<&'d ()>,
579    _mode: OperatingMode,
580    info: RxInfoRef,
581}
582
583impl<'d> CanRx<'d> {
584    /// Returns the next received message frame
585    pub async fn read(&mut self) -> Result<Envelope, BusError> {
586        RxMode::read_classic(&self.info).await
587    }
588
589    /// Returns the next received message frame
590    pub async fn read_fd(&mut self) -> Result<FdEnvelope, BusError> {
591        RxMode::read_fd(&self.info).await
592    }
593}
594
595/// FDCAN Tx only Instance
596pub struct CanTx<'d> {
597    _phantom: PhantomData<&'d ()>,
598    config: crate::can::fd::config::FdCanConfig,
599    _mode: OperatingMode,
600    info: TxInfoRef,
601}
602
603impl<'c, 'd> CanTx<'d> {
604    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
605    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
606    /// can be replaced, this call asynchronously waits for a frame to be successfully
607    /// transmitted, then tries again.
608    pub async fn write(&mut self, frame: &Frame) -> Option<Frame> {
609        TxMode::write(&self.info, frame).await
610    }
611
612    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
613    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
614    /// can be replaced, this call asynchronously waits for a frame to be successfully
615    /// transmitted, then tries again.
616    pub async fn write_fd(&mut self, frame: &FdFrame) -> Option<FdFrame> {
617        TxMode::write_fd(&self.info, frame).await
618    }
619}
620
621enum RxMode {
622    NonBuffered(AtomicWaker),
623    ClassicBuffered(super::common::ClassicBufferedRxInner),
624    FdBuffered(super::common::FdBufferedRxInner),
625}
626
627impl RxMode {
628    fn register(&self, arg: &core::task::Waker) {
629        match self {
630            RxMode::NonBuffered(waker) => waker.register(arg),
631            _ => {
632                panic!("Bad Mode")
633            }
634        }
635    }
636
637    fn on_interrupt<T: Instance>(&self, fifonr: usize, ns_per_timer_tick: u64) {
638        T::registers().regs.ir().write(|w| w.set_rfn(fifonr, true));
639        match self {
640            RxMode::NonBuffered(waker) => {
641                waker.wake();
642            }
643            RxMode::ClassicBuffered(buf) => {
644                if let Some(result) = self.try_read::<T>(ns_per_timer_tick) {
645                    let _ = buf.rx_sender.try_send(result);
646                }
647            }
648            RxMode::FdBuffered(buf) => {
649                if let Some(result) = self.try_read_fd::<T>(ns_per_timer_tick) {
650                    let _ = buf.rx_sender.try_send(result);
651                }
652            }
653        }
654    }
655
656    //async fn read_classic<T: Instance>(&self) -> Result<Envelope, BusError> {
657    fn try_read<T: Instance>(&self, ns_per_timer_tick: u64) -> Option<Result<Envelope, BusError>> {
658        if let Some((frame, ts)) = T::registers().read(0) {
659            let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
660            Some(Ok(Envelope { ts, frame }))
661        } else if let Some((frame, ts)) = T::registers().read(1) {
662            let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
663            Some(Ok(Envelope { ts, frame }))
664        } else if let Some(err) = T::registers().curr_error() {
665            // TODO: this is probably wrong
666            Some(Err(err))
667        } else {
668            None
669        }
670    }
671
672    fn try_read_fd<T: Instance>(&self, ns_per_timer_tick: u64) -> Option<Result<FdEnvelope, BusError>> {
673        if let Some((frame, ts)) = T::registers().read(0) {
674            let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
675            Some(Ok(FdEnvelope { ts, frame }))
676        } else if let Some((frame, ts)) = T::registers().read(1) {
677            let ts = T::registers().calc_timestamp(ns_per_timer_tick, ts);
678            Some(Ok(FdEnvelope { ts, frame }))
679        } else if let Some(err) = T::registers().curr_error() {
680            // TODO: this is probably wrong
681            Some(Err(err))
682        } else {
683            None
684        }
685    }
686
687    fn read<F: CanHeader>(info: &'static Info, ns_per_timer_tick: u64) -> Option<Result<(F, Timestamp), BusError>> {
688        if let Some((msg, ts)) = info.regs.read(0) {
689            let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts);
690            Some(Ok((msg, ts)))
691        } else if let Some((msg, ts)) = info.regs.read(1) {
692            let ts = info.regs.calc_timestamp(ns_per_timer_tick, ts);
693            Some(Ok((msg, ts)))
694        } else if let Some(err) = info.regs.curr_error() {
695            // TODO: this is probably wrong
696            Some(Err(err))
697        } else {
698            None
699        }
700    }
701
702    async fn read_async<F: CanHeader>(info: &'static Info) -> Result<(F, Timestamp), BusError> {
703        poll_fn(move |cx| {
704            let ns_per_timer_tick = info.state.lock(|s| {
705                let state = s.borrow_mut();
706                state.err_waker.register(cx.waker());
707                state.rx_mode.register(cx.waker());
708                state.ns_per_timer_tick
709            });
710            match RxMode::read::<_>(info, ns_per_timer_tick) {
711                Some(result) => Poll::Ready(result),
712                None => Poll::Pending,
713            }
714        })
715        .await
716    }
717
718    async fn read_classic(info: &'static Info) -> Result<Envelope, BusError> {
719        match RxMode::read_async::<_>(info).await {
720            Ok((frame, ts)) => Ok(Envelope { ts, frame }),
721            Err(e) => Err(e),
722        }
723    }
724
725    async fn read_fd(info: &'static Info) -> Result<FdEnvelope, BusError> {
726        match RxMode::read_async::<_>(info).await {
727            Ok((frame, ts)) => Ok(FdEnvelope { ts, frame }),
728            Err(e) => Err(e),
729        }
730    }
731}
732
733enum TxMode {
734    NonBuffered(AtomicWaker),
735    ClassicBuffered(super::common::ClassicBufferedTxInner),
736    FdBuffered(super::common::FdBufferedTxInner),
737}
738
739impl TxMode {
740    fn register(&self, arg: &core::task::Waker) {
741        match self {
742            TxMode::NonBuffered(waker) => {
743                waker.register(arg);
744            }
745            _ => {
746                panic!("Bad mode");
747            }
748        }
749    }
750
751    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
752    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
753    /// can be replaced, this call asynchronously waits for a frame to be successfully
754    /// transmitted, then tries again.
755    async fn write_generic<F: embedded_can::Frame + CanHeader>(info: &'static Info, frame: &F) -> Option<F> {
756        poll_fn(|cx| {
757            info.state.lock(|s| {
758                s.borrow_mut().tx_mode.register(cx.waker());
759            });
760
761            if let Ok(dropped) = info.regs.write(frame) {
762                return Poll::Ready(dropped);
763            }
764
765            // Couldn't replace any lower priority frames.  Need to wait for some mailboxes
766            // to clear.
767            Poll::Pending
768        })
769        .await
770    }
771
772    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
773    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
774    /// can be replaced, this call asynchronously waits for a frame to be successfully
775    /// transmitted, then tries again.
776    async fn write(info: &'static Info, frame: &Frame) -> Option<Frame> {
777        TxMode::write_generic::<_>(info, frame).await
778    }
779
780    /// Queues the message to be sent but exerts backpressure.  If a lower-priority
781    /// frame is dropped from the mailbox, it is returned.  If no lower-priority frames
782    /// can be replaced, this call asynchronously waits for a frame to be successfully
783    /// transmitted, then tries again.
784    async fn write_fd(info: &'static Info, frame: &FdFrame) -> Option<FdFrame> {
785        TxMode::write_generic::<_>(info, frame).await
786    }
787}
788
789/// Common driver properties, including filters and error counters
790pub struct Properties {
791    info: &'static Info,
792    // phantom pointer to ensure !Sync
793    //instance: PhantomData<*const T>,
794}
795
796impl Properties {
797    fn new(info: &'static Info) -> Self {
798        Self {
799            info,
800            //instance: Default::default(),
801        }
802    }
803
804    /// Set a standard address CAN filter in the specified slot in FDCAN memory.
805    #[inline]
806    pub fn set_standard_filter(&self, slot: StandardFilterSlot, filter: StandardFilter) {
807        self.info.regs.msg_ram_mut().filters.flssa[slot as usize].activate(filter);
808    }
809
810    /// Set the full array of standard address CAN filters in FDCAN memory.
811    /// Overwrites all standard address filters in memory.
812    pub fn set_standard_filters(&self, filters: &[StandardFilter; STANDARD_FILTER_MAX as usize]) {
813        for (i, f) in filters.iter().enumerate() {
814            self.info.regs.msg_ram_mut().filters.flssa[i].activate(*f);
815        }
816    }
817
818    /// Set an extended address CAN filter in the specified slot in FDCAN memory.
819    #[inline]
820    pub fn set_extended_filter(&self, slot: ExtendedFilterSlot, filter: ExtendedFilter) {
821        self.info.regs.msg_ram_mut().filters.flesa[slot as usize].activate(filter);
822    }
823
824    /// Set the full array of extended address CAN filters in FDCAN memory.
825    /// Overwrites all extended address filters in memory.
826    pub fn set_extended_filters(&self, filters: &[ExtendedFilter; EXTENDED_FILTER_MAX as usize]) {
827        for (i, f) in filters.iter().enumerate() {
828            self.info.regs.msg_ram_mut().filters.flesa[i].activate(*f);
829        }
830    }
831
832    /// Get the CAN RX error counter
833    pub fn rx_error_count(&self) -> u8 {
834        self.info.regs.regs.ecr().read().rec()
835    }
836
837    /// Get the CAN TX error counter
838    pub fn tx_error_count(&self) -> u8 {
839        self.info.regs.regs.ecr().read().tec()
840    }
841
842    /// Get the current bus error mode
843    pub fn bus_error_mode(&self) -> BusErrorMode {
844        // This read will clear LEC and DLEC. This is not ideal, but protocol
845        // error reporting in this driver should have a big ol' FIXME on it
846        // anyway!
847        let psr = self.info.regs.regs.psr().read();
848        match (psr.bo(), psr.ep()) {
849            (false, false) => BusErrorMode::ErrorActive,
850            (false, true) => BusErrorMode::ErrorPassive,
851            (true, _) => BusErrorMode::BusOff,
852        }
853    }
854}
855
856struct State {
857    pub rx_mode: RxMode,
858    pub tx_mode: TxMode,
859    pub ns_per_timer_tick: u64,
860    receiver_instance_count: usize,
861    sender_instance_count: usize,
862    tx_pin_port: Option<u8>,
863    rx_pin_port: Option<u8>,
864
865    pub err_waker: AtomicWaker,
866}
867
868impl State {
869    const fn new() -> Self {
870        Self {
871            rx_mode: RxMode::NonBuffered(AtomicWaker::new()),
872            tx_mode: TxMode::NonBuffered(AtomicWaker::new()),
873            ns_per_timer_tick: 0,
874            err_waker: AtomicWaker::new(),
875            receiver_instance_count: 0,
876            sender_instance_count: 0,
877            tx_pin_port: None,
878            rx_pin_port: None,
879        }
880    }
881}
882
883type SharedState = embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, core::cell::RefCell<State>>;
884pub(crate) struct Info {
885    regs: Registers,
886    interrupt0: crate::interrupt::Interrupt,
887    _interrupt1: crate::interrupt::Interrupt,
888    pub(crate) tx_waker: fn(),
889    state: SharedState,
890}
891
892impl Info {
893    pub(crate) fn adjust_reference_counter(&self, val: RefCountOp) {
894        self.state.lock(|s| {
895            let mut mut_state = s.borrow_mut();
896            match val {
897                RefCountOp::NotifySenderCreated => {
898                    mut_state.sender_instance_count += 1;
899                }
900                RefCountOp::NotifySenderDestroyed => {
901                    mut_state.sender_instance_count -= 1;
902                    if 0 == mut_state.sender_instance_count {
903                        (*mut_state).tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
904                    }
905                }
906                RefCountOp::NotifyReceiverCreated => {
907                    mut_state.receiver_instance_count += 1;
908                }
909                RefCountOp::NotifyReceiverDestroyed => {
910                    mut_state.receiver_instance_count -= 1;
911                    if 0 == mut_state.receiver_instance_count {
912                        (*mut_state).rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new());
913                    }
914                }
915            }
916            if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 {
917                unsafe {
918                    let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap());
919                    tx_pin.set_as_disconnected();
920                    let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap());
921                    rx_pin.set_as_disconnected();
922                    self.interrupt0.disable();
923                }
924            }
925        });
926    }
927}
928
929trait SealedInstance {
930    const MSG_RAM_OFFSET: usize;
931
932    fn info() -> &'static Info;
933    fn registers() -> crate::can::fd::peripheral::Registers;
934}
935
936/// Instance trait
937#[allow(private_bounds)]
938pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + 'static {
939    /// Interrupt 0
940    type IT0Interrupt: crate::interrupt::typelevel::Interrupt;
941    /// Interrupt 1
942    type IT1Interrupt: crate::interrupt::typelevel::Interrupt;
943}
944
945/// Fdcan Instance struct
946pub struct FdcanInstance<'a, T: Instance>(Peri<'a, T>);
947
948macro_rules! impl_fdcan {
949    ($inst:ident,
950        //$irq0:ident, $irq1:ident,
951        $msg_ram_inst:ident, $msg_ram_offset:literal) => {
952        impl SealedInstance for peripherals::$inst {
953            const MSG_RAM_OFFSET: usize = $msg_ram_offset;
954
955            fn info() -> &'static Info {
956
957                static INFO: Info = Info {
958                    regs: Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: $msg_ram_offset},
959                    interrupt0: crate::_generated::peripheral_interrupts::$inst::IT0::IRQ,
960                    _interrupt1: crate::_generated::peripheral_interrupts::$inst::IT1::IRQ,
961                    tx_waker: crate::_generated::peripheral_interrupts::$inst::IT0::pend,
962                    state: embassy_sync::blocking_mutex::Mutex::new(core::cell::RefCell::new(State::new())),
963                };
964                &INFO
965            }
966            fn registers() -> Registers {
967                Registers{regs: crate::pac::$inst, msgram: crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET}
968            }
969
970        }
971
972        #[allow(non_snake_case)]
973        pub(crate) mod $inst {
974
975            foreach_interrupt!(
976                ($inst,can,FDCAN,IT0,$irq:ident) => {
977                    pub type Interrupt0 = crate::interrupt::typelevel::$irq;
978                };
979                ($inst,can,FDCAN,IT1,$irq:ident) => {
980                    pub type Interrupt1 = crate::interrupt::typelevel::$irq;
981                };
982            );
983        }
984        impl Instance for peripherals::$inst {
985            type IT0Interrupt = $inst::Interrupt0;
986            type IT1Interrupt = $inst::Interrupt1;
987        }
988    };
989
990    ($inst:ident, $msg_ram_inst:ident) => {
991        impl_fdcan!($inst, $msg_ram_inst, 0);
992    };
993}
994
995#[cfg(not(can_fdcan_h7))]
996foreach_peripheral!(
997    (can, FDCAN) => { impl_fdcan!(FDCAN, FDCANRAM); };
998    (can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM1); };
999    (can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM2); };
1000    (can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM3); };
1001);
1002
1003#[cfg(can_fdcan_h7)]
1004foreach_peripheral!(
1005    (can, FDCAN1) => { impl_fdcan!(FDCAN1, FDCANRAM, 0x0000); };
1006    (can, FDCAN2) => { impl_fdcan!(FDCAN2, FDCANRAM, 0x0C00); };
1007    (can, FDCAN3) => { impl_fdcan!(FDCAN3, FDCANRAM, 0x1800); };
1008);
1009
1010pin_trait!(RxPin, Instance);
1011pin_trait!(TxPin, Instance);