aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorey Schuhen <[email protected]>2024-02-18 13:09:37 +1000
committerCorey Schuhen <[email protected]>2024-02-18 13:09:37 +1000
commiteafa90cd0707298f354d5d1e496f8364117bd781 (patch)
tree0295b2a971bbe17b92465f3638e710544de987d2
parent5ad291b708528b5772d6ebcc9309fbd3f8a002c8 (diff)
Remove the OperatingMode typestates
Instead have two explcit types(without the mode generic arg)types: - One for config - One for all operating modes
-rw-r--r--embassy-stm32/src/can/fd/peripheral.rs13
-rw-r--r--embassy-stm32/src/can/fdcan.rs265
-rw-r--r--examples/stm32g4/src/bin/can.rs9
-rw-r--r--examples/stm32h5/src/bin/can.rs3
-rw-r--r--examples/stm32h7/src/bin/can.rs3
-rw-r--r--tests/stm32/src/bin/fdcan.rs2
6 files changed, 133 insertions, 162 deletions
diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs
index 487b8f413..0771d6fbb 100644
--- a/embassy-stm32/src/can/fd/peripheral.rs
+++ b/embassy-stm32/src/can/fd/peripheral.rs
@@ -481,6 +481,19 @@ impl Registers {
481 while self.regs.cccr().read().init() == true {} 481 while self.regs.cccr().read().init() == true {}
482 } 482 }
483 483
484 /// Moves out of ConfigMode and into specified mode
485 #[inline]
486 pub fn into_mode(mut self, config: FdCanConfig, mode: crate::can::_version::FdcanOperatingMode) {
487 match mode {
488 crate::can::FdcanOperatingMode::InternalLoopbackMode => self.set_loopback_mode(LoopbackMode::Internal),
489 crate::can::FdcanOperatingMode::ExternalLoopbackMode => self.set_loopback_mode(LoopbackMode::External),
490 crate::can::FdcanOperatingMode::NormalOperationMode => self.set_normal_operations(true),
491 crate::can::FdcanOperatingMode::RestrictedOperationMode => self.set_restricted_operations(true),
492 crate::can::FdcanOperatingMode::BusMonitoringMode => self.set_bus_monitoring_mode(true),
493 }
494 self.leave_init_mode(config);
495 }
496
484 /// Moves out of ConfigMode and into InternalLoopbackMode 497 /// Moves out of ConfigMode and into InternalLoopbackMode
485 #[inline] 498 #[inline]
486 pub fn into_internal_loopback(mut self, config: FdCanConfig) { 499 pub fn into_internal_loopback(mut self, config: FdCanConfig) {
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 3ae330e14..f1f6f935e 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -100,75 +100,50 @@ impl<T: Instance> interrupt::typelevel::Handler<T::IT1Interrupt> for IT1Interrup
100 unsafe fn on_interrupt() {} 100 unsafe fn on_interrupt() {}
101} 101}
102 102
103/// Allows for Transmit Operations 103#[derive(Debug, Copy, Clone, Eq, PartialEq)]
104pub trait Transmit {} 104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105/// Allows for Receive Operations 105/// Different operating modes
106pub trait Receive {} 106pub enum FdcanOperatingMode {
107 107 //PoweredDownMode,
108/// Allows for the FdCan Instance to be released or to enter ConfigMode 108 //ConfigMode,
109pub struct PoweredDownMode; 109 /// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without
110/// Allows for the configuration for the Instance 110 /// affecting a running CAN system connected to the FDCAN_TX and FDCAN_RX pins. In this
111pub struct ConfigMode; 111 /// mode, FDCAN_RX pin is disconnected from the FDCAN and FDCAN_TX pin is held
112/// This mode can be used for a “Hot Selftest”, meaning the FDCAN can be tested without 112 /// recessive.
113/// affecting a running CAN system connected to the FDCAN_TX and FDCAN_RX pins. In this 113 InternalLoopbackMode,
114/// mode, FDCAN_RX pin is disconnected from the FDCAN and FDCAN_TX pin is held 114 /// This mode is provided for hardware self-test. To be independent from external stimulation,
115/// recessive. 115 /// the FDCAN ignores acknowledge errors (recessive bit sampled in the acknowledge slot of a
116pub struct InternalLoopbackMode; 116 /// data / remote frame) in Loop Back mode. In this mode the FDCAN performs an internal
117impl Transmit for InternalLoopbackMode {} 117 /// feedback from its transmit output to its receive input. The actual value of the FDCAN_RX
118impl Receive for InternalLoopbackMode {} 118 /// input pin is disregarded by the FDCAN. The transmitted messages can be monitored at the
119/// This mode is provided for hardware self-test. To be independent from external stimulation, 119 /// FDCAN_TX transmit pin.
120/// the FDCAN ignores acknowledge errors (recessive bit sampled in the acknowledge slot of a 120 ExternalLoopbackMode,
121/// data / remote frame) in Loop Back mode. In this mode the FDCAN performs an internal 121 /// The normal use of the Fdcan instance after configurations
122/// feedback from its transmit output to its receive input. The actual value of the FDCAN_RX 122 NormalOperationMode,
123/// input pin is disregarded by the FDCAN. The transmitted messages can be monitored at the 123 /// In Restricted operation mode the node is able to receive data and remote frames and to give
124/// FDCAN_TX transmit pin. 124 /// acknowledge to valid frames, but it does not send data frames, remote frames, active error
125pub struct ExternalLoopbackMode; 125 /// frames, or overload frames. In case of an error condition or overload condition, it does not
126impl Transmit for ExternalLoopbackMode {} 126 /// send dominant bits, instead it waits for the occurrence of bus idle condition to resynchronize
127impl Receive for ExternalLoopbackMode {} 127 /// itself to the CAN communication. The error counters for transmit and receive are frozen while
128/// The normal use of the FdCan instance after configurations 128 /// error logging (can_errors) is active. TODO: automatically enter in this mode?
129pub struct NormalOperationMode; 129 RestrictedOperationMode,
130impl Transmit for NormalOperationMode {} 130 /// In Bus monitoring mode (for more details refer to ISO11898-1, 10.12 Bus monitoring),
131impl Receive for NormalOperationMode {} 131 /// the FDCAN is able to receive valid data frames and valid remote frames, but cannot start a
132/// In Restricted operation mode the node is able to receive data and remote frames and to give 132 /// transmission. In this mode, it sends only recessive bits on the CAN bus. If the FDCAN is
133/// acknowledge to valid frames, but it does not send data frames, remote frames, active error 133 /// required to send a dominant bit (ACK bit, overload flag, active error flag), the bit is
134/// frames, or overload frames. In case of an error condition or overload condition, it does not 134 /// rerouted internally so that the FDCAN can monitor it, even if the CAN bus remains in recessive
135/// send dominant bits, instead it waits for the occurrence of bus idle condition to resynchronize 135 /// state. In Bus monitoring mode the TXBRP register is held in reset state. The Bus monitoring
136/// itself to the CAN communication. The error counters for transmit and receive are frozen while 136 /// mode can be used to analyze the traffic on a CAN bus without affecting it by the transmission
137/// error logging (can_errors) is active. TODO: automatically enter in this mode? 137 /// of dominant bits.
138pub struct RestrictedOperationMode; 138 BusMonitoringMode,
139impl Receive for RestrictedOperationMode {} 139 //TestMode,
140/// In Bus monitoring mode (for more details refer to ISO11898-1, 10.12 Bus monitoring), 140}
141/// the FDCAN is able to receive valid data frames and valid remote frames, but cannot start a
142/// transmission. In this mode, it sends only recessive bits on the CAN bus. If the FDCAN is
143/// required to send a dominant bit (ACK bit, overload flag, active error flag), the bit is
144/// rerouted internally so that the FDCAN can monitor it, even if the CAN bus remains in recessive
145/// state. In Bus monitoring mode the TXBRP register is held in reset state. The Bus monitoring
146/// mode can be used to analyze the traffic on a CAN bus without affecting it by the transmission
147/// of dominant bits.
148pub struct BusMonitoringMode;
149impl Receive for BusMonitoringMode {}
150/// Test mode must be used for production tests or self test only. The software control for
151/// FDCAN_TX pin interferes with all CAN protocol functions. It is not recommended to use test
152/// modes for application.
153pub struct TestMode;
154
155/// Operating modes trait
156pub trait FdcanOperatingMode {}
157impl FdcanOperatingMode for PoweredDownMode {}
158impl FdcanOperatingMode for ConfigMode {}
159impl FdcanOperatingMode for InternalLoopbackMode {}
160impl FdcanOperatingMode for ExternalLoopbackMode {}
161impl FdcanOperatingMode for NormalOperationMode {}
162impl FdcanOperatingMode for RestrictedOperationMode {}
163impl FdcanOperatingMode for BusMonitoringMode {}
164impl FdcanOperatingMode for TestMode {}
165 141
166/// FDCAN Instance 142/// FDCAN Instance
167pub struct Fdcan<'d, T: Instance, M: FdcanOperatingMode> { 143pub struct FdcanConfigurator<'d, T: Instance> {
168 config: crate::can::fd::config::FdCanConfig, 144 config: crate::can::fd::config::FdCanConfig,
169 /// Reference to internals. 145 /// Reference to internals.
170 instance: FdcanInstance<'d, T>, 146 instance: FdcanInstance<'d, T>,
171 _mode: PhantomData<M>,
172} 147}
173 148
174fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 { 149fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 {
@@ -186,7 +161,7 @@ fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransm
186 } 161 }
187} 162}
188 163
189impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> { 164impl<'d, T: Instance> FdcanConfigurator<'d, T> {
190 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode. 165 /// Creates a new Fdcan instance, keeping the peripheral in sleep mode.
191 /// You must call [Fdcan::enable_non_blocking] to use the peripheral. 166 /// You must call [Fdcan::enable_non_blocking] to use the peripheral.
192 pub fn new( 167 pub fn new(
@@ -196,7 +171,7 @@ impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> {
196 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>> 171 _irqs: impl interrupt::typelevel::Binding<T::IT0Interrupt, IT0InterruptHandler<T>>
197 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>> 172 + interrupt::typelevel::Binding<T::IT1Interrupt, IT1InterruptHandler<T>>
198 + 'd, 173 + 'd,
199 ) -> Fdcan<'d, T, ConfigMode> { 174 ) -> FdcanConfigurator<'d, T> {
200 into_ref!(peri, rx, tx); 175 into_ref!(peri, rx, tx);
201 176
202 rx.set_as_af(rx.af_num(), AFType::Input); 177 rx.set_as_af(rx.af_num(), AFType::Input);
@@ -245,7 +220,6 @@ impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> {
245 Self { 220 Self {
246 config, 221 config,
247 instance: FdcanInstance(peri), 222 instance: FdcanInstance(peri),
248 _mode: PhantomData::<ConfigMode>,
249 } 223 }
250 } 224 }
251 225
@@ -272,7 +246,7 @@ impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> {
272 self.config = self.config.set_nominal_bit_timing(nbtr); 246 self.config = self.config.set_nominal_bit_timing(nbtr);
273 } 247 }
274 248
275 /// Configures the bit timings for VBR data calculated from supplied bitrate. 249 /// Configures the bit timings for VBR data calculated from supplied bitrate. This also sets confit to allow can FD and VBR
276 pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) { 250 pub fn set_fd_data_bitrate(&mut self, bitrate: u32, transceiver_delay_compensation: bool) {
277 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); 251 let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap();
278 // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M 252 // Note, used existing calcluation for normal(non-VBR) bitrate, appears to work for 250k/1M
@@ -312,51 +286,47 @@ impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> {
312 T::registers().msg_ram_mut().filters.flesa[i].activate(*f); 286 T::registers().msg_ram_mut().filters.flesa[i].activate(*f);
313 } 287 }
314 } 288 }
315}
316 289
317macro_rules! impl_transition { 290 /// Start in mode.
318 ($from_mode:ident, $to_mode:ident, $name:ident, $func: ident) => { 291 pub fn start(self, mode: FdcanOperatingMode) -> Fdcan<'d, T> {
319 impl<'d, T: Instance> Fdcan<'d, T, $from_mode> { 292 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit);
320 /// Transition from $from_mode:ident mode to $to_mode:ident mode 293 critical_section::with(|_| unsafe {
321 pub fn $name(self) -> Fdcan<'d, T, $to_mode> { 294 T::mut_state().ns_per_timer_tick = ns_per_timer_tick;
322 let ns_per_timer_tick = calc_ns_per_timer_tick::<T>(self.config.frame_transmit); 295 });
323 critical_section::with(|_| unsafe { 296 T::registers().into_mode(self.config, mode);
324 T::mut_state().ns_per_timer_tick = ns_per_timer_tick; 297 let ret = Fdcan {
325 }); 298 config: self.config,
326 T::registers().$func(self.config); 299 instance: self.instance,
327 let ret = Fdcan { 300 _mode: mode,
328 config: self.config, 301 };
329 instance: self.instance, 302 ret
330 _mode: PhantomData::<$to_mode>, 303 }
331 };
332 ret
333 }
334 }
335 };
336}
337 304
338impl_transition!(PoweredDownMode, ConfigMode, into_config_mode, into_config_mode); 305 /// Start, entering mode. Does same as start(mode)
339impl_transition!(InternalLoopbackMode, ConfigMode, into_config_mode, into_config_mode); 306 pub fn into_normal_mode(self) -> Fdcan<'d, T> {
307 self.start(FdcanOperatingMode::NormalOperationMode)
308 }
340 309
341impl_transition!(ConfigMode, NormalOperationMode, into_normal_mode, into_normal); 310 /// Start, entering mode. Does same as start(mode)
342impl_transition!( 311 pub fn into_internal_loopback_mode(self) -> Fdcan<'d, T> {
343 ConfigMode, 312 self.start(FdcanOperatingMode::InternalLoopbackMode)
344 ExternalLoopbackMode, 313 }
345 into_external_loopback_mode,
346 into_external_loopback
347);
348impl_transition!(
349 ConfigMode,
350 InternalLoopbackMode,
351 into_internal_loopback_mode,
352 into_internal_loopback
353);
354 314
355impl<'d, T: Instance, M: FdcanOperatingMode> Fdcan<'d, T, M> 315 /// Start, entering mode. Does same as start(mode)
356where 316 pub fn into_external_loopback_mode(self) -> Fdcan<'d, T> {
357 M: Transmit, 317 self.start(FdcanOperatingMode::ExternalLoopbackMode)
358 M: Receive, 318 }
359{ 319}
320
321/// FDCAN Instance
322pub struct Fdcan<'d, T: Instance> {
323 config: crate::can::fd::config::FdCanConfig,
324 /// Reference to internals.
325 instance: FdcanInstance<'d, T>,
326 _mode: FdcanOperatingMode,
327}
328
329impl<'d, T: Instance> Fdcan<'d, T> {
360 /// Flush one of the TX mailboxes. 330 /// Flush one of the TX mailboxes.
361 pub async fn flush(&self, idx: usize) { 331 pub async fn flush(&self, idx: usize) {
362 poll_fn(|cx| { 332 poll_fn(|cx| {
@@ -401,18 +371,8 @@ where
401 T::state().rx_mode.read_fd::<T>().await 371 T::state().rx_mode.read_fd::<T>().await
402 } 372 }
403 373
404 /// Join split rx and tx portions back together
405 pub fn join(tx: FdcanTx<'d, T, M>, rx: FdcanRx<'d, T, M>) -> Self {
406 Fdcan {
407 config: tx.config,
408 //_instance2: T::regs(),
409 instance: tx._instance,
410 _mode: rx._mode,
411 }
412 }
413
414 /// Split instance into separate Tx(write) and Rx(read) portions 374 /// Split instance into separate Tx(write) and Rx(read) portions
415 pub fn split(self) -> (FdcanTx<'d, T, M>, FdcanRx<'d, T, M>) { 375 pub fn split(self) -> (FdcanTx<'d, T>, FdcanRx<'d, T>) {
416 ( 376 (
417 FdcanTx { 377 FdcanTx {
418 config: self.config, 378 config: self.config,
@@ -427,12 +387,22 @@ where
427 ) 387 )
428 } 388 }
429 389
390 /// Join split rx and tx portions back together
391 pub fn join(tx: FdcanTx<'d, T>, rx: FdcanRx<'d, T>) -> Self {
392 Fdcan {
393 config: tx.config,
394 //_instance2: T::regs(),
395 instance: tx._instance,
396 _mode: rx._mode,
397 }
398 }
399
430 /// Return a buffered instance of driver without CAN FD support. User must supply Buffers 400 /// Return a buffered instance of driver without CAN FD support. User must supply Buffers
431 pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>( 401 pub fn buffered<const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>(
432 &self, 402 &self,
433 tx_buf: &'static mut TxBuf<TX_BUF_SIZE>, 403 tx_buf: &'static mut TxBuf<TX_BUF_SIZE>,
434 rxb: &'static mut RxBuf<RX_BUF_SIZE>, 404 rxb: &'static mut RxBuf<RX_BUF_SIZE>,
435 ) -> BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> { 405 ) -> BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
436 BufferedCan::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) 406 BufferedCan::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb)
437 } 407 }
438 408
@@ -441,7 +411,7 @@ where
441 &self, 411 &self,
442 tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>, 412 tx_buf: &'static mut TxFdBuf<TX_BUF_SIZE>,
443 rxb: &'static mut RxFdBuf<RX_BUF_SIZE>, 413 rxb: &'static mut RxFdBuf<RX_BUF_SIZE>,
444 ) -> BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> { 414 ) -> BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE> {
445 BufferedCanFd::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb) 415 BufferedCanFd::new(PhantomData::<T>, T::regs(), self._mode, tx_buf, rxb)
446 } 416 }
447} 417}
@@ -453,24 +423,21 @@ pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (Classi
453pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; 423pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>;
454 424
455/// Buffered FDCAN Instance 425/// Buffered FDCAN Instance
456#[allow(dead_code)] 426pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
457pub struct BufferedCan<'d, T: Instance, M: FdcanOperatingMode, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
458 _instance1: PhantomData<T>, 427 _instance1: PhantomData<T>,
459 _instance2: &'d crate::pac::can::Fdcan, 428 _instance2: &'d crate::pac::can::Fdcan,
460 _mode: PhantomData<M>, 429 _mode: FdcanOperatingMode,
461 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 430 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
462 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 431 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
463} 432}
464 433
465impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> 434impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
466 BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> 435 BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
467where
468 M: FdcanOperatingMode,
469{ 436{
470 fn new( 437 fn new(
471 _instance1: PhantomData<T>, 438 _instance1: PhantomData<T>,
472 _instance2: &'d crate::pac::can::Fdcan, 439 _instance2: &'d crate::pac::can::Fdcan,
473 _mode: PhantomData<M>, 440 _mode: FdcanOperatingMode,
474 tx_buf: &'static TxBuf<TX_BUF_SIZE>, 441 tx_buf: &'static TxBuf<TX_BUF_SIZE>,
475 rx_buf: &'static RxBuf<RX_BUF_SIZE>, 442 rx_buf: &'static RxBuf<RX_BUF_SIZE>,
476 ) -> Self { 443 ) -> Self {
@@ -511,10 +478,8 @@ where
511 } 478 }
512} 479}
513 480
514impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop 481impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop
515 for BufferedCan<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> 482 for BufferedCan<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
516where
517 M: FdcanOperatingMode,
518{ 483{
519 fn drop(&mut self) { 484 fn drop(&mut self) {
520 critical_section::with(|_| unsafe { 485 critical_section::with(|_| unsafe {
@@ -531,24 +496,21 @@ pub type RxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, (FdFr
531pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; 496pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>;
532 497
533/// Buffered FDCAN Instance 498/// Buffered FDCAN Instance
534#[allow(dead_code)] 499pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
535pub struct BufferedCanFd<'d, T: Instance, M: FdcanOperatingMode, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> {
536 _instance1: PhantomData<T>, 500 _instance1: PhantomData<T>,
537 _instance2: &'d crate::pac::can::Fdcan, 501 _instance2: &'d crate::pac::can::Fdcan,
538 _mode: PhantomData<M>, 502 _mode: FdcanOperatingMode,
539 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 503 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
540 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 504 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
541} 505}
542 506
543impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> 507impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize>
544 BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> 508 BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
545where
546 M: FdcanOperatingMode,
547{ 509{
548 fn new( 510 fn new(
549 _instance1: PhantomData<T>, 511 _instance1: PhantomData<T>,
550 _instance2: &'d crate::pac::can::Fdcan, 512 _instance2: &'d crate::pac::can::Fdcan,
551 _mode: PhantomData<M>, 513 _mode: FdcanOperatingMode,
552 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, 514 tx_buf: &'static TxFdBuf<TX_BUF_SIZE>,
553 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, 515 rx_buf: &'static RxFdBuf<RX_BUF_SIZE>,
554 ) -> Self { 516 ) -> Self {
@@ -589,10 +551,8 @@ where
589 } 551 }
590} 552}
591 553
592impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop 554impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop
593 for BufferedCanFd<'d, T, M, TX_BUF_SIZE, RX_BUF_SIZE> 555 for BufferedCanFd<'d, T, TX_BUF_SIZE, RX_BUF_SIZE>
594where
595 M: FdcanOperatingMode,
596{ 556{
597 fn drop(&mut self) { 557 fn drop(&mut self) {
598 critical_section::with(|_| unsafe { 558 critical_section::with(|_| unsafe {
@@ -603,21 +563,20 @@ where
603} 563}
604 564
605/// FDCAN Rx only Instance 565/// FDCAN Rx only Instance
606#[allow(dead_code)] 566pub struct FdcanRx<'d, T: Instance> {
607pub struct FdcanRx<'d, T: Instance, M: Receive> {
608 _instance1: PhantomData<T>, 567 _instance1: PhantomData<T>,
609 _instance2: &'d crate::pac::can::Fdcan, 568 _instance2: &'d crate::pac::can::Fdcan,
610 _mode: PhantomData<M>, 569 _mode: FdcanOperatingMode,
611} 570}
612 571
613/// FDCAN Tx only Instance 572/// FDCAN Tx only Instance
614pub struct FdcanTx<'d, T: Instance, M: Transmit> { 573pub struct FdcanTx<'d, T: Instance> {
615 config: crate::can::fd::config::FdCanConfig, 574 config: crate::can::fd::config::FdCanConfig,
616 _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>); 575 _instance: FdcanInstance<'d, T>, //(PeripheralRef<'a, T>);
617 _mode: PhantomData<M>, 576 _mode: FdcanOperatingMode,
618} 577}
619 578
620impl<'c, 'd, T: Instance, M: Transmit> FdcanTx<'d, T, M> { 579impl<'c, 'd, T: Instance> FdcanTx<'d, T> {
621 /// Queues the message to be sent but exerts backpressure. If a lower-priority 580 /// Queues the message to be sent but exerts backpressure. If a lower-priority
622 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames 581 /// frame is dropped from the mailbox, it is returned. If no lower-priority frames
623 /// can be replaced, this call asynchronously waits for a frame to be successfully 582 /// can be replaced, this call asynchronously waits for a frame to be successfully
@@ -635,7 +594,7 @@ impl<'c, 'd, T: Instance, M: Transmit> FdcanTx<'d, T, M> {
635 } 594 }
636} 595}
637 596
638impl<'c, 'd, T: Instance, M: Receive> FdcanRx<'d, T, M> { 597impl<'c, 'd, T: Instance> FdcanRx<'d, T> {
639 /// Returns the next received message frame 598 /// Returns the next received message frame
640 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> { 599 pub async fn read(&mut self) -> Result<(ClassicFrame, Timestamp), BusError> {
641 T::state().rx_mode.read::<T>().await 600 T::state().rx_mode.read::<T>().await
diff --git a/examples/stm32g4/src/bin/can.rs b/examples/stm32g4/src/bin/can.rs
index 043ca7144..affa97039 100644
--- a/examples/stm32g4/src/bin/can.rs
+++ b/examples/stm32g4/src/bin/can.rs
@@ -19,7 +19,7 @@ async fn main(_spawner: Spawner) {
19 19
20 let peripherals = embassy_stm32::init(config); 20 let peripherals = embassy_stm32::init(config);
21 21
22 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); 22 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
23 23
24 can.set_extended_filter( 24 can.set_extended_filter(
25 can::fd::filter::ExtendedFilterSlot::_0, 25 can::fd::filter::ExtendedFilterSlot::_0,
@@ -38,8 +38,10 @@ async fn main(_spawner: Spawner) {
38 38
39 info!("Configured"); 39 info!("Configured");
40 40
41 let mut can = can.into_normal_mode(); 41 let mut can = can.start(match use_fd {
42 //let mut can = can.into_internal_loopback_mode(); 42 true => can::FdcanOperatingMode::InternalLoopbackMode,
43 false => can::FdcanOperatingMode::NormalOperationMode,
44 });
43 45
44 let mut i = 0; 46 let mut i = 0;
45 let mut last_read_ts = embassy_time::Instant::now(); 47 let mut last_read_ts = embassy_time::Instant::now();
@@ -106,7 +108,6 @@ async fn main(_spawner: Spawner) {
106 break; 108 break;
107 } 109 }
108 } 110 }
109
110 i = 0; 111 i = 0;
111 let (mut tx, mut rx) = can.split(); 112 let (mut tx, mut rx) = can.split();
112 // With split 113 // With split
diff --git a/examples/stm32h5/src/bin/can.rs b/examples/stm32h5/src/bin/can.rs
index 4b29a0d21..e5ccfe4f7 100644
--- a/examples/stm32h5/src/bin/can.rs
+++ b/examples/stm32h5/src/bin/can.rs
@@ -24,8 +24,7 @@ async fn main(_spawner: Spawner) {
24 24
25 let peripherals = embassy_stm32::init(config); 25 let peripherals = embassy_stm32::init(config);
26 26
27 //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 27 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
28 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
29 28
30 // 250k bps 29 // 250k bps
31 can.set_bitrate(250_000); 30 can.set_bitrate(250_000);
diff --git a/examples/stm32h7/src/bin/can.rs b/examples/stm32h7/src/bin/can.rs
index 4b29a0d21..e5ccfe4f7 100644
--- a/examples/stm32h7/src/bin/can.rs
+++ b/examples/stm32h7/src/bin/can.rs
@@ -24,8 +24,7 @@ async fn main(_spawner: Spawner) {
24 24
25 let peripherals = embassy_stm32::init(config); 25 let peripherals = embassy_stm32::init(config);
26 26
27 //let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 27 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
28 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
29 28
30 // 250k bps 29 // 250k bps
31 can.set_bitrate(250_000); 30 can.set_bitrate(250_000);
diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs
index 76c27d091..398e31ffc 100644
--- a/tests/stm32/src/bin/fdcan.rs
+++ b/tests/stm32/src/bin/fdcan.rs
@@ -75,7 +75,7 @@ async fn main(_spawner: Spawner) {
75 let options = options(); 75 let options = options();
76 let peripherals = embassy_stm32::init(options.config); 76 let peripherals = embassy_stm32::init(options.config);
77 77
78 let mut can = can::Fdcan::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs); 78 let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PB8, peripherals.PB9, Irqs);
79 79
80 // 250k bps 80 // 250k bps
81 can.set_bitrate(250_000); 81 can.set_bitrate(250_000);