diff options
| author | Corey Schuhen <[email protected]> | 2024-02-18 13:09:37 +1000 |
|---|---|---|
| committer | Corey Schuhen <[email protected]> | 2024-02-18 13:09:37 +1000 |
| commit | eafa90cd0707298f354d5d1e496f8364117bd781 (patch) | |
| tree | 0295b2a971bbe17b92465f3638e710544de987d2 | |
| parent | 5ad291b708528b5772d6ebcc9309fbd3f8a002c8 (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.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 265 | ||||
| -rw-r--r-- | examples/stm32g4/src/bin/can.rs | 9 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/can.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/can.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/fdcan.rs | 2 |
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)] |
| 104 | pub trait Transmit {} | 104 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 105 | /// Allows for Receive Operations | 105 | /// Different operating modes |
| 106 | pub trait Receive {} | 106 | pub enum FdcanOperatingMode { |
| 107 | 107 | //PoweredDownMode, | |
| 108 | /// Allows for the FdCan Instance to be released or to enter ConfigMode | 108 | //ConfigMode, |
| 109 | pub 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 |
| 111 | pub 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 |
| 116 | pub struct InternalLoopbackMode; | 116 | /// data / remote frame) in Loop Back mode. In this mode the FDCAN performs an internal |
| 117 | impl Transmit for InternalLoopbackMode {} | 117 | /// feedback from its transmit output to its receive input. The actual value of the FDCAN_RX |
| 118 | impl 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 |
| 125 | pub struct ExternalLoopbackMode; | 125 | /// frames, or overload frames. In case of an error condition or overload condition, it does not |
| 126 | impl Transmit for ExternalLoopbackMode {} | 126 | /// send dominant bits, instead it waits for the occurrence of bus idle condition to resynchronize |
| 127 | impl 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? |
| 129 | pub struct NormalOperationMode; | 129 | RestrictedOperationMode, |
| 130 | impl Transmit for NormalOperationMode {} | 130 | /// In Bus monitoring mode (for more details refer to ISO11898-1, 10.12 Bus monitoring), |
| 131 | impl 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. |
| 138 | pub struct RestrictedOperationMode; | 138 | BusMonitoringMode, |
| 139 | impl 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. | ||
| 148 | pub struct BusMonitoringMode; | ||
| 149 | impl 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. | ||
| 153 | pub struct TestMode; | ||
| 154 | |||
| 155 | /// Operating modes trait | ||
| 156 | pub trait FdcanOperatingMode {} | ||
| 157 | impl FdcanOperatingMode for PoweredDownMode {} | ||
| 158 | impl FdcanOperatingMode for ConfigMode {} | ||
| 159 | impl FdcanOperatingMode for InternalLoopbackMode {} | ||
| 160 | impl FdcanOperatingMode for ExternalLoopbackMode {} | ||
| 161 | impl FdcanOperatingMode for NormalOperationMode {} | ||
| 162 | impl FdcanOperatingMode for RestrictedOperationMode {} | ||
| 163 | impl FdcanOperatingMode for BusMonitoringMode {} | ||
| 164 | impl FdcanOperatingMode for TestMode {} | ||
| 165 | 141 | ||
| 166 | /// FDCAN Instance | 142 | /// FDCAN Instance |
| 167 | pub struct Fdcan<'d, T: Instance, M: FdcanOperatingMode> { | 143 | pub 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 | ||
| 174 | fn calc_ns_per_timer_tick<T: Instance>(mode: crate::can::fd::config::FrameTransmissionConfig) -> u64 { | 149 | fn 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 | ||
| 189 | impl<'d, T: Instance> Fdcan<'d, T, ConfigMode> { | 164 | impl<'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 | ||
| 317 | macro_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 | ||
| 338 | impl_transition!(PoweredDownMode, ConfigMode, into_config_mode, into_config_mode); | 305 | /// Start, entering mode. Does same as start(mode) |
| 339 | impl_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 | ||
| 341 | impl_transition!(ConfigMode, NormalOperationMode, into_normal_mode, into_normal); | 310 | /// Start, entering mode. Does same as start(mode) |
| 342 | impl_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 | ); | ||
| 348 | impl_transition!( | ||
| 349 | ConfigMode, | ||
| 350 | InternalLoopbackMode, | ||
| 351 | into_internal_loopback_mode, | ||
| 352 | into_internal_loopback | ||
| 353 | ); | ||
| 354 | 314 | ||
| 355 | impl<'d, T: Instance, M: FdcanOperatingMode> Fdcan<'d, T, M> | 315 | /// Start, entering mode. Does same as start(mode) |
| 356 | where | 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 | ||
| 322 | pub 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 | |||
| 329 | impl<'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 | |||
| 453 | pub type TxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, ClassicFrame, BUF_SIZE>; | 423 | pub 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)] | 426 | pub struct BufferedCan<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 457 | pub 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 | ||
| 465 | impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 434 | impl<'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> |
| 467 | where | ||
| 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 | ||
| 514 | impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | 481 | impl<'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> |
| 516 | where | ||
| 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 | |||
| 531 | pub type TxFdBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, FdFrame, BUF_SIZE>; | 496 | pub 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)] | 499 | pub struct BufferedCanFd<'d, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> { |
| 535 | pub 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 | ||
| 543 | impl<'c, 'd, T: Instance, M: Transmit, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> | 507 | impl<'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> |
| 545 | where | ||
| 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 | ||
| 592 | impl<'c, 'd, T: Instance, M, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Drop | 554 | impl<'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> |
| 594 | where | ||
| 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)] | 566 | pub struct FdcanRx<'d, T: Instance> { |
| 607 | pub 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 |
| 614 | pub struct FdcanTx<'d, T: Instance, M: Transmit> { | 573 | pub 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 | ||
| 620 | impl<'c, 'd, T: Instance, M: Transmit> FdcanTx<'d, T, M> { | 579 | impl<'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 | ||
| 638 | impl<'c, 'd, T: Instance, M: Receive> FdcanRx<'d, T, M> { | 597 | impl<'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); |
