diff options
| -rw-r--r-- | embassy-stm32/src/can/fdcan.rs | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index 5467a40f1..a7815f79b 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs | |||
| @@ -10,7 +10,7 @@ use embassy_sync::channel::Channel; | |||
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | 11 | ||
| 12 | use crate::can::fd::peripheral::Registers; | 12 | use crate::can::fd::peripheral::Registers; |
| 13 | use crate::gpio::{AfType, OutputType, Pull, Speed}; | 13 | use crate::gpio::{AfType, OutputType, Pull, SealedPin as _, Speed}; |
| 14 | use crate::interrupt::typelevel::Interrupt; | 14 | use crate::interrupt::typelevel::Interrupt; |
| 15 | use crate::rcc::{self, RccPeripheral}; | 15 | use crate::rcc::{self, RccPeripheral}; |
| 16 | use crate::{interrupt, peripherals, Peri}; | 16 | use crate::{interrupt, peripherals, Peri}; |
| @@ -187,13 +187,17 @@ impl<'d> CanConfigurator<'d> { | |||
| 187 | 187 | ||
| 188 | rcc::enable_and_reset::<T>(); | 188 | rcc::enable_and_reset::<T>(); |
| 189 | 189 | ||
| 190 | let info = T::info(); | ||
| 191 | let state = unsafe { T::mut_state() }; | ||
| 192 | state.tx_pin_port = Some(tx.pin_port()); | ||
| 193 | state.rx_pin_port = Some(rx.pin_port()); | ||
| 194 | (info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 195 | (info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 196 | |||
| 190 | let mut config = crate::can::fd::config::FdCanConfig::default(); | 197 | let mut config = crate::can::fd::config::FdCanConfig::default(); |
| 191 | config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1); | 198 | config.timestamp_source = TimestampSource::Prescaler(TimestampPrescaler::_1); |
| 192 | T::registers().into_config_mode(config); | 199 | T::registers().into_config_mode(config); |
| 193 | 200 | ||
| 194 | rx.set_as_af(rx.af_num(), AfType::input(Pull::None)); | ||
| 195 | tx.set_as_af(tx.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh)); | ||
| 196 | |||
| 197 | unsafe { | 201 | unsafe { |
| 198 | T::IT0Interrupt::unpend(); // Not unsafe | 202 | T::IT0Interrupt::unpend(); // Not unsafe |
| 199 | T::IT0Interrupt::enable(); | 203 | T::IT0Interrupt::enable(); |
| @@ -204,8 +208,8 @@ impl<'d> CanConfigurator<'d> { | |||
| 204 | Self { | 208 | Self { |
| 205 | _phantom: PhantomData, | 209 | _phantom: PhantomData, |
| 206 | config, | 210 | config, |
| 207 | info: T::info(), | 211 | info, |
| 208 | state: T::state(), | 212 | state, |
| 209 | properties: Properties::new(T::info()), | 213 | properties: Properties::new(T::info()), |
| 210 | periph_clock: T::frequency(), | 214 | periph_clock: T::frequency(), |
| 211 | } | 215 | } |
| @@ -265,6 +269,8 @@ impl<'d> CanConfigurator<'d> { | |||
| 265 | } | 269 | } |
| 266 | }); | 270 | }); |
| 267 | self.info.regs.into_mode(self.config, mode); | 271 | self.info.regs.into_mode(self.config, mode); |
| 272 | (self.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 273 | (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 268 | Can { | 274 | Can { |
| 269 | _phantom: PhantomData, | 275 | _phantom: PhantomData, |
| 270 | config: self.config, | 276 | config: self.config, |
| @@ -291,6 +297,13 @@ impl<'d> CanConfigurator<'d> { | |||
| 291 | } | 297 | } |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 300 | impl<'d> Drop for CanConfigurator<'d> { | ||
| 301 | fn drop(&mut self) { | ||
| 302 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); | ||
| 303 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 294 | /// FDCAN Instance | 307 | /// FDCAN Instance |
| 295 | pub struct Can<'d> { | 308 | pub struct Can<'d> { |
| 296 | _phantom: PhantomData<&'d ()>, | 309 | _phantom: PhantomData<&'d ()>, |
| @@ -353,6 +366,8 @@ impl<'d> Can<'d> { | |||
| 353 | 366 | ||
| 354 | /// Split instance into separate portions: Tx(write), Rx(read), common properties | 367 | /// Split instance into separate portions: Tx(write), Rx(read), common properties |
| 355 | pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { | 368 | pub fn split(self) -> (CanTx<'d>, CanRx<'d>, Properties) { |
| 369 | (self.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 370 | (self.info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 356 | ( | 371 | ( |
| 357 | CanTx { | 372 | CanTx { |
| 358 | _phantom: PhantomData, | 373 | _phantom: PhantomData, |
| @@ -367,11 +382,15 @@ impl<'d> Can<'d> { | |||
| 367 | state: self.state, | 382 | state: self.state, |
| 368 | _mode: self._mode, | 383 | _mode: self._mode, |
| 369 | }, | 384 | }, |
| 370 | self.properties, | 385 | Properties { |
| 386 | info: self.properties.info, | ||
| 387 | }, | ||
| 371 | ) | 388 | ) |
| 372 | } | 389 | } |
| 373 | /// Join split rx and tx portions back together | 390 | /// Join split rx and tx portions back together |
| 374 | pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { | 391 | pub fn join(tx: CanTx<'d>, rx: CanRx<'d>) -> Self { |
| 392 | (tx.info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 393 | (tx.info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 375 | Can { | 394 | Can { |
| 376 | _phantom: PhantomData, | 395 | _phantom: PhantomData, |
| 377 | config: tx.config, | 396 | config: tx.config, |
| @@ -401,6 +420,13 @@ impl<'d> Can<'d> { | |||
| 401 | } | 420 | } |
| 402 | } | 421 | } |
| 403 | 422 | ||
| 423 | impl<'d> Drop for Can<'d> { | ||
| 424 | fn drop(&mut self) { | ||
| 425 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); | ||
| 426 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 404 | /// User supplied buffer for RX Buffering | 430 | /// User supplied buffer for RX Buffering |
| 405 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; | 431 | pub type RxBuf<const BUF_SIZE: usize> = Channel<CriticalSectionRawMutex, Result<Envelope, BusError>, BUF_SIZE>; |
| 406 | 432 | ||
| @@ -426,6 +452,8 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCan<'d, | |||
| 426 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, | 452 | tx_buf: &'static TxBuf<TX_BUF_SIZE>, |
| 427 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, | 453 | rx_buf: &'static RxBuf<RX_BUF_SIZE>, |
| 428 | ) -> Self { | 454 | ) -> Self { |
| 455 | (info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 456 | (info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 429 | BufferedCan { | 457 | BufferedCan { |
| 430 | _phantom: PhantomData, | 458 | _phantom: PhantomData, |
| 431 | info, | 459 | info, |
| @@ -532,6 +560,8 @@ impl<'c, 'd, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> BufferedCanFd<' | |||
| 532 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, | 560 | tx_buf: &'static TxFdBuf<TX_BUF_SIZE>, |
| 533 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, | 561 | rx_buf: &'static RxFdBuf<RX_BUF_SIZE>, |
| 534 | ) -> Self { | 562 | ) -> Self { |
| 563 | (info.internal_operation)(InternalOperation::NotifySenderCreated); | ||
| 564 | (info.internal_operation)(InternalOperation::NotifyReceiverCreated); | ||
| 535 | BufferedCanFd { | 565 | BufferedCanFd { |
| 536 | _phantom: PhantomData, | 566 | _phantom: PhantomData, |
| 537 | info, | 567 | info, |
| @@ -627,6 +657,12 @@ impl<'d> CanRx<'d> { | |||
| 627 | } | 657 | } |
| 628 | } | 658 | } |
| 629 | 659 | ||
| 660 | impl<'d> Drop for CanRx<'d> { | ||
| 661 | fn drop(&mut self) { | ||
| 662 | (self.info.internal_operation)(InternalOperation::NotifyReceiverDestroyed); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 630 | /// FDCAN Tx only Instance | 666 | /// FDCAN Tx only Instance |
| 631 | pub struct CanTx<'d> { | 667 | pub struct CanTx<'d> { |
| 632 | _phantom: PhantomData<&'d ()>, | 668 | _phantom: PhantomData<&'d ()>, |
| @@ -654,6 +690,12 @@ impl<'c, 'd> CanTx<'d> { | |||
| 654 | } | 690 | } |
| 655 | } | 691 | } |
| 656 | 692 | ||
| 693 | impl<'d> Drop for CanTx<'d> { | ||
| 694 | fn drop(&mut self) { | ||
| 695 | (self.info.internal_operation)(InternalOperation::NotifySenderDestroyed); | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 657 | enum RxMode { | 699 | enum RxMode { |
| 658 | NonBuffered(AtomicWaker), | 700 | NonBuffered(AtomicWaker), |
| 659 | ClassicBuffered(super::common::ClassicBufferedRxInner), | 701 | ClassicBuffered(super::common::ClassicBufferedRxInner), |
| @@ -898,6 +940,8 @@ struct State { | |||
| 898 | pub ns_per_timer_tick: u64, | 940 | pub ns_per_timer_tick: u64, |
| 899 | receiver_instance_count: usize, | 941 | receiver_instance_count: usize, |
| 900 | sender_instance_count: usize, | 942 | sender_instance_count: usize, |
| 943 | tx_pin_port: Option<u8>, | ||
| 944 | rx_pin_port: Option<u8>, | ||
| 901 | 945 | ||
| 902 | pub err_waker: AtomicWaker, | 946 | pub err_waker: AtomicWaker, |
| 903 | } | 947 | } |
| @@ -909,8 +953,10 @@ impl State { | |||
| 909 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), | 953 | tx_mode: TxMode::NonBuffered(AtomicWaker::new()), |
| 910 | ns_per_timer_tick: 0, | 954 | ns_per_timer_tick: 0, |
| 911 | err_waker: AtomicWaker::new(), | 955 | err_waker: AtomicWaker::new(), |
| 912 | receiver_instance_count: 1, | 956 | receiver_instance_count: 0, |
| 913 | sender_instance_count: 1, | 957 | sender_instance_count: 0, |
| 958 | tx_pin_port: None, | ||
| 959 | rx_pin_port: None, | ||
| 914 | } | 960 | } |
| 915 | } | 961 | } |
| 916 | } | 962 | } |
| @@ -998,6 +1044,13 @@ macro_rules! impl_fdcan { | |||
| 998 | } | 1044 | } |
| 999 | } | 1045 | } |
| 1000 | } | 1046 | } |
| 1047 | if mut_state.sender_instance_count == 0 && mut_state.receiver_instance_count == 0 { | ||
| 1048 | let tx_pin = crate::gpio::AnyPin::steal(mut_state.tx_pin_port.unwrap()); | ||
| 1049 | tx_pin.set_as_disconnected(); | ||
| 1050 | let rx_pin = crate::gpio::AnyPin::steal(mut_state.rx_pin_port.unwrap()); | ||
| 1051 | rx_pin.set_as_disconnected(); | ||
| 1052 | rcc::disable::<peripherals::$inst>(); | ||
| 1053 | } | ||
| 1001 | } | 1054 | } |
| 1002 | }); | 1055 | }); |
| 1003 | } | 1056 | } |
