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