1 | #[allow (unused_variables)] |
2 | use core::future::poll_fn; |
3 | use core::marker::PhantomData; |
4 | use core::task::Poll; |
5 | |
6 | use embassy_hal_internal::interrupt::InterruptExt; |
7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
9 | use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; |
10 | use embassy_sync::waitqueue::AtomicWaker; |
11 | |
12 | use crate::can::fd::peripheral::Registers; |
13 | use crate::gpio::{AfType, OutputType, Pull, Speed}; |
14 | use crate::interrupt::typelevel::Interrupt; |
15 | use crate::rcc::{self, RccPeripheral}; |
16 | use crate::{interrupt, peripherals, Peripheral}; |
17 | |
18 | pub(crate) mod fd; |
19 | |
20 | use self::fd::config::*; |
21 | use self::fd::filter::*; |
22 | pub use self::fd::{config, filter}; |
23 | pub use super::common::{BufferedCanReceiver, BufferedCanSender}; |
24 | use super::enums::*; |
25 | use super::frame::*; |
26 | use super::util; |
27 | |
28 | /// Timestamp for incoming packets. Use Embassy time when enabled. |
29 | #[cfg (feature = "time" )] |
30 | pub type Timestamp = embassy_time::Instant; |
31 | |
32 | /// Timestamp for incoming packets. |
33 | #[cfg (not(feature = "time" ))] |
34 | pub type Timestamp = u16; |
35 | |
36 | /// Interrupt handler channel 0. |
37 | pub struct IT0InterruptHandler<T: Instance> { |
38 | _phantom: PhantomData<T>, |
39 | } |
40 | |
41 | // We use IT0 for everything currently |
42 | impl<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. |
97 | pub struct IT1InterruptHandler<T: Instance> { |
98 | _phantom: PhantomData<T>, |
99 | } |
100 | |
101 | impl<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 |
108 | pub 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 | |
144 | fn 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 |
164 | pub 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 | |
174 | impl<'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 |
297 | pub 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 | |
306 | impl<'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 |
407 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; |
408 | |
409 | /// User supplied buffer for TX buffering |
410 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Frame, BUF_SIZE>; |
411 | |
412 | /// Buffered FDCAN Instance |
413 | pub 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 | |
423 | impl<'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 | |
493 | impl<'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 |
507 | pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<FdEnvelope, BusError>, BUF_SIZE>; |
508 | |
509 | /// User supplied buffer for TX buffering |
510 | pub 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)] |
514 | pub struct BufferedFdCanSender { |
515 | tx_buf: DynamicSender<'static, FdFrame>, |
516 | waker: fn(), |
517 | } |
518 | |
519 | impl 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. |
540 | pub type BufferedFdCanReceiver = DynamicReceiver<'static, Result<FdEnvelope, BusError>>; |
541 | |
542 | /// Buffered FDCAN Instance |
543 | pub 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 | |
553 | impl<'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 | |
623 | impl<'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 |
637 | pub struct CanRx<'d> { |
638 | _phantom: PhantomData<&'d ()>, |
639 | info: &'static Info, |
640 | state: &'static State, |
641 | _mode: OperatingMode, |
642 | } |
643 | |
644 | impl<'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 |
657 | pub 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 | |
665 | impl<'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 | |
683 | enum RxMode { |
684 | NonBuffered(AtomicWaker), |
685 | ClassicBuffered(super::common::ClassicBufferedRxInner), |
686 | FdBuffered(super::common::FdBufferedRxInner), |
687 | } |
688 | |
689 | impl 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 | |
800 | enum TxMode { |
801 | NonBuffered(AtomicWaker), |
802 | ClassicBuffered(super::common::ClassicBufferedTxInner), |
803 | FdBuffered(super::common::FdBufferedTxInner), |
804 | } |
805 | |
806 | impl 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 |
855 | pub struct Properties { |
856 | info: &'static Info, |
857 | // phantom pointer to ensure !Sync |
858 | //instance: PhantomData<*const T>, |
859 | } |
860 | |
861 | impl 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 | |
921 | struct 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 | |
929 | impl 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 | |
940 | struct Info { |
941 | regs: Registers, |
942 | interrupt0: crate::interrupt::Interrupt, |
943 | _interrupt1: crate::interrupt::Interrupt, |
944 | tx_waker: fn(), |
945 | } |
946 | |
947 | impl 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 | |
966 | trait 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)] |
978 | pub 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 |
986 | pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); |
987 | |
988 | macro_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))] |
1058 | foreach_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)] |
1066 | foreach_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 | |
1072 | pin_trait!(RxPin, Instance); |
1073 | pin_trait!(TxPin, Instance); |
1074 | |