diff --git a/embassy-stm32/src/can/bxcan/filter.rs b/embassy-stm32/src/can/bxcan/filter.rs index 9940c7f50..167c6c572 100644 --- a/embassy-stm32/src/can/bxcan/filter.rs +++ b/embassy-stm32/src/can/bxcan/filter.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; -use super::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId}; +use super::{ExtendedId, Fifo, Id, StandardId}; const F32_RTR: u32 = 0b010; // set the RTR bit to match remote frames const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers @@ -210,24 +210,24 @@ impl From for BankConfig { } /// Interface to the filter banks of a CAN peripheral. -pub struct MasterFilters<'a, I: FilterOwner> { +pub struct MasterFilters<'a> { /// Number of assigned filter banks. /// /// On chips with splittable filter banks, this value can be dynamic. bank_count: u8, - _can: PhantomData<&'a mut I>, - canregs: crate::pac::can::Can, + _phantom: PhantomData<&'a ()>, + info: &'static crate::can::Info, } // NOTE: This type mutably borrows the CAN instance and has unique access to the registers while it // exists. -impl MasterFilters<'_, I> { - pub(crate) unsafe fn new(canregs: crate::pac::can::Can) -> Self { +impl MasterFilters<'_> { + pub(crate) unsafe fn new(info: &'static crate::can::Info) -> Self { // Enable initialization mode. - canregs.fmr().modify(|reg| reg.set_finit(true)); + info.regs.0.fmr().modify(|reg| reg.set_finit(true)); // Read the filter split value. - let bank_count = canregs.fmr().read().can2sb(); + let bank_count = info.regs.0.fmr().read().can2sb(); // (Reset value of CAN2SB is 0x0E, 14, which, in devices with 14 filter banks, assigns all // of them to the master peripheral, and in devices with 28, assigns them 50/50 to @@ -235,8 +235,8 @@ impl MasterFilters<'_, I> { Self { bank_count, - _can: PhantomData, - canregs, + _phantom: PhantomData, + info, } } @@ -244,7 +244,7 @@ impl MasterFilters<'_, I> { FilterBanks { start_idx: 0, bank_count: self.bank_count, - canregs: self.canregs, + info: self.info, } } @@ -291,49 +291,49 @@ impl MasterFilters<'_, I> { } } -impl MasterFilters<'_, I> { +impl MasterFilters<'_> { /// Sets the index at which the filter banks owned by the slave peripheral start. pub fn set_split(&mut self, split_index: u8) -> &mut Self { - assert!(split_index <= I::NUM_FILTER_BANKS); - self.canregs.fmr().modify(|reg| reg.set_can2sb(split_index)); + assert!(split_index <= self.info.num_filter_banks); + self.info.regs.0.fmr().modify(|reg| reg.set_can2sb(split_index)); self.bank_count = split_index; self } /// Accesses the filters assigned to the slave peripheral. - pub fn slave_filters(&mut self) -> SlaveFilters<'_, I> { + pub fn slave_filters(&mut self) -> SlaveFilters<'_> { // NB: This mutably borrows `self`, so it has full access to the filter bank registers. SlaveFilters { start_idx: self.bank_count, - bank_count: I::NUM_FILTER_BANKS - self.bank_count, - _can: PhantomData, - canregs: self.canregs, + bank_count: self.info.num_filter_banks - self.bank_count, + _phantom: PhantomData, + info: self.info, } } } -impl Drop for MasterFilters<'_, I> { +impl Drop for MasterFilters<'_> { #[inline] fn drop(&mut self) { // Leave initialization mode. - self.canregs.fmr().modify(|regs| regs.set_finit(false)); + self.info.regs.0.fmr().modify(|regs| regs.set_finit(false)); } } /// Interface to the filter banks assigned to a slave peripheral. -pub struct SlaveFilters<'a, I: Instance> { +pub struct SlaveFilters<'a> { start_idx: u8, bank_count: u8, - _can: PhantomData<&'a mut I>, - canregs: crate::pac::can::Can, + _phantom: PhantomData<&'a ()>, + info: &'static crate::can::Info, } -impl SlaveFilters<'_, I> { +impl SlaveFilters<'_> { fn banks_imm(&self) -> FilterBanks { FilterBanks { start_idx: self.start_idx, bank_count: self.bank_count, - canregs: self.canregs, + info: self.info, } } @@ -377,14 +377,14 @@ impl SlaveFilters<'_, I> { struct FilterBanks { start_idx: u8, bank_count: u8, - canregs: crate::pac::can::Can, + info: &'static crate::can::Info, } impl FilterBanks { fn clear(&mut self) { let mask = filter_bitmask(self.start_idx, self.bank_count); - self.canregs.fa1r().modify(|reg| { + self.info.regs.0.fa1r().modify(|reg| { for i in 0..28usize { if (0x01u32 << i) & mask != 0 { reg.set_fact(i, false); @@ -399,7 +399,11 @@ impl FilterBanks { fn disable(&mut self, index: u8) { self.assert_bank_index(index); - self.canregs.fa1r().modify(|reg| reg.set_fact(index as usize, false)) + self.info + .regs + .0 + .fa1r() + .modify(|reg| reg.set_fact(index as usize, false)) } fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) { @@ -407,11 +411,11 @@ impl FilterBanks { // Configure mode. let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_)); - self.canregs.fm1r().modify(|reg| reg.set_fbm(index as usize, mode)); + self.info.regs.0.fm1r().modify(|reg| reg.set_fbm(index as usize, mode)); // Configure scale. let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_)); - self.canregs.fs1r().modify(|reg| reg.set_fsc(index as usize, scale)); + self.info.regs.0.fs1r().modify(|reg| reg.set_fsc(index as usize, scale)); // Configure filter register. let (fxr1, fxr2); @@ -433,12 +437,12 @@ impl FilterBanks { fxr2 = a.mask; } }; - let bank = self.canregs.fb(index as usize); + let bank = self.info.regs.0.fb(index as usize); bank.fr1().write(|w| w.0 = fxr1); bank.fr2().write(|w| w.0 = fxr2); // Assign to the right FIFO - self.canregs.ffa1r().modify(|reg| { + self.info.regs.0.ffa1r().modify(|reg| { reg.set_ffa( index as usize, match fifo { @@ -449,7 +453,7 @@ impl FilterBanks { }); // Set active. - self.canregs.fa1r().modify(|reg| reg.set_fact(index as usize, true)) + self.info.regs.0.fa1r().modify(|reg| reg.set_fact(index as usize, true)) } } diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index 9f7df1e71..53b94b9e2 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use core::task::Poll; use embassy_hal_internal::interrupt::InterruptExt; -use embassy_hal_internal::{into_ref, PeripheralRef}; +use embassy_hal_internal::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::waitqueue::AtomicWaker; @@ -91,11 +91,13 @@ impl interrupt::typelevel::Handler for SceInterrup } /// Configuration proxy returned by [`Can::modify_config`]. -pub struct CanConfig<'a, T: Instance> { - can: PhantomData<&'a mut T>, +pub struct CanConfig<'a> { + phantom: PhantomData<&'a ()>, + info: &'static Info, + periph_clock: crate::time::Hertz, } -impl CanConfig<'_, T> { +impl CanConfig<'_> { /// Configures the bit timings. /// /// You can use to calculate the `btr` parameter. Enter @@ -109,7 +111,7 @@ impl CanConfig<'_, T> { /// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr` /// parameter to this method. pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self { - Registers(T::regs()).set_bit_timing(bt); + self.info.regs.set_bit_timing(bt); self } @@ -117,20 +119,20 @@ impl CanConfig<'_, T> { /// /// This is a helper that internally calls `set_bit_timing()`[Self::set_bit_timing]. pub fn set_bitrate(self, bitrate: u32) -> Self { - let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); + let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap(); self.set_bit_timing(bit_timing) } /// Enables or disables loopback mode: Internally connects the TX and RX /// signals together. pub fn set_loopback(self, enabled: bool) -> Self { - Registers(T::regs()).set_loopback(enabled); + self.info.regs.set_loopback(enabled); self } /// Enables or disables silent mode: Disconnects the TX signal from the pin. pub fn set_silent(self, enabled: bool) -> Self { - Registers(T::regs()).set_silent(enabled); + self.info.regs.set_silent(enabled); self } @@ -141,23 +143,24 @@ impl CanConfig<'_, T> { /// /// Automatic retransmission is enabled by default. pub fn set_automatic_retransmit(self, enabled: bool) -> Self { - Registers(T::regs()).set_automatic_retransmit(enabled); + self.info.regs.set_automatic_retransmit(enabled); self } } -impl Drop for CanConfig<'_, T> { +impl Drop for CanConfig<'_> { #[inline] fn drop(&mut self) { - Registers(T::regs()).leave_init_mode(); + self.info.regs.leave_init_mode(); } } /// CAN driver -pub struct Can<'d, T: Instance> { - _peri: PeripheralRef<'d, T>, +pub struct Can<'d> { + phantom: PhantomData<&'d ()>, info: &'static Info, state: &'static State, + periph_clock: crate::time::Hertz, } /// Error returned by `try_write` @@ -168,11 +171,11 @@ pub enum TryWriteError { Full, } -impl<'d, T: Instance> Can<'d, T> { +impl<'d> Can<'d> { /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. /// You must call [Can::enable_non_blocking] to use the peripheral. - pub fn new( - peri: impl Peripheral

+ 'd, + pub fn new( + _peri: impl Peripheral

+ 'd, rx: impl Peripheral

> + 'd, tx: impl Peripheral

> + 'd, _irqs: impl interrupt::typelevel::Binding> @@ -181,7 +184,7 @@ impl<'d, T: Instance> Can<'d, T> { + interrupt::typelevel::Binding> + 'd, ) -> Self { - into_ref!(peri, rx, tx); + into_ref!(_peri, rx, tx); let info = T::info(); let regs = &T::info().regs; @@ -226,15 +229,16 @@ impl<'d, T: Instance> Can<'d, T> { Registers(T::regs()).leave_init_mode(); Self { - _peri: peri, + phantom: PhantomData, info: T::info(), state: T::state(), + periph_clock: T::frequency(), } } /// Set CAN bit rate. pub fn set_bitrate(&mut self, bitrate: u32) { - let bit_timing = util::calc_can_timings(T::frequency(), bitrate).unwrap(); + let bit_timing = util::calc_can_timings(self.periph_clock, bitrate).unwrap(); self.modify_config().set_bit_timing(bit_timing); } @@ -242,10 +246,14 @@ impl<'d, T: Instance> Can<'d, T> { /// /// Calling this method will enter initialization mode. You must enable the peripheral /// again afterwards with [`enable`](Self::enable). - pub fn modify_config(&mut self) -> CanConfig<'_, T> { - Registers(T::regs()).enter_init_mode(); + pub fn modify_config(&mut self) -> CanConfig<'_> { + self.info.regs.enter_init_mode(); - CanConfig { can: PhantomData } + CanConfig { + phantom: self.phantom, + info: self.info, + periph_clock: self.periph_clock, + } } /// Enables the peripheral and synchronizes with the bus. @@ -253,7 +261,7 @@ impl<'d, T: Instance> Can<'d, T> { /// This will wait for 11 consecutive recessive bits (bus idle state). /// Contrary to enable method from bxcan library, this will not freeze the executor while waiting. pub async fn enable(&mut self) { - while Registers(T::regs()).enable_non_blocking().is_err() { + while self.info.regs.enable_non_blocking().is_err() { // SCE interrupt is only generated for entering sleep mode, but not leaving. // Yield to allow other tasks to execute while can bus is initializing. embassy_futures::yield_now().await; @@ -263,7 +271,7 @@ impl<'d, T: Instance> Can<'d, T> { /// Enables or disables the peripheral from automatically wakeup when a SOF is detected on the bus /// while the peripheral is in sleep mode pub fn set_automatic_wakeup(&mut self, enabled: bool) { - Registers(T::regs()).set_automatic_wakeup(enabled); + self.info.regs.set_automatic_wakeup(enabled); } /// Manually wake the peripheral from sleep mode. @@ -313,12 +321,12 @@ impl<'d, T: Instance> Can<'d, T> { /// /// FIFO scheduling is disabled by default. pub fn set_tx_fifo_scheduling(&mut self, enabled: bool) { - Registers(T::regs()).set_tx_fifo_scheduling(enabled) + self.info.regs.set_tx_fifo_scheduling(enabled) } /// Checks if FIFO scheduling of outgoing frames is enabled. pub fn tx_fifo_scheduling_enabled(&self) -> bool { - Registers(T::regs()).tx_fifo_scheduling_enabled() + self.info.regs.tx_fifo_scheduling_enabled() } /// Queues the message to be sent. @@ -448,13 +456,13 @@ impl<'d, T: Instance> Can<'d, T> { } } -impl<'d, T: FilterOwner> Can<'d, T> { +impl<'d> Can<'d> { /// Accesses the filter banks owned by this CAN peripheral. /// /// To modify filters of a slave peripheral, `modify_filters` has to be called on the master /// peripheral instead. - pub fn modify_filters(&mut self) -> MasterFilters<'_, T> { - unsafe { MasterFilters::new(self.info.regs.0) } + pub fn modify_filters(&mut self) -> MasterFilters<'_> { + unsafe { MasterFilters::new(self.info) } } } @@ -819,12 +827,14 @@ impl<'d, const RX_BUF_SIZE: usize> Drop for BufferedCanRx<'d, RX_BUF_SIZE> { } } -impl<'d, T: Instance> Drop for Can<'d, T> { +impl Drop for Can<'_> { fn drop(&mut self) { // Cannot call `free()` because it moves the instance. // Manually reset the peripheral. - T::regs().mcr().write(|w| w.set_reset(true)); - rcc::disable::(); + self.info.regs.0.mcr().write(|w| w.set_reset(true)); + self.info.regs.enter_init_mode(); + self.info.regs.leave_init_mode(); + //rcc::disable::(); } } @@ -1031,6 +1041,11 @@ pub(crate) struct Info { rx1_interrupt: crate::interrupt::Interrupt, sce_interrupt: crate::interrupt::Interrupt, tx_waker: fn(), + + /// The total number of filter banks available to the instance. + /// + /// This is usually either 14 or 28, and should be specified in the chip's reference manual or datasheet. + num_filter_banks: u8, } trait SealedInstance { @@ -1095,6 +1110,7 @@ foreach_peripheral!( rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ, sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ, tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend, + num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS, }; &INFO } @@ -1148,6 +1164,11 @@ foreach_peripheral!( } } }; + (can, CAN2) => { + unsafe impl FilterOwner for peripherals::CAN2 { + const NUM_FILTER_BANKS: u8 = 0; + } + }; (can, CAN3) => { unsafe impl FilterOwner for peripherals::CAN3 { const NUM_FILTER_BANKS: u8 = 14; diff --git a/embassy-stm32/src/can/bxcan/registers.rs b/embassy-stm32/src/can/bxcan/registers.rs index e7c7525d8..5f3d70e25 100644 --- a/embassy-stm32/src/can/bxcan/registers.rs +++ b/embassy-stm32/src/can/bxcan/registers.rs @@ -11,7 +11,7 @@ use crate::can::frame::{Envelope, Frame, Header}; pub(crate) struct Registers(pub crate::pac::can::Can); impl Registers { - pub fn enter_init_mode(&mut self) { + pub fn enter_init_mode(&self) { self.0.mcr().modify(|reg| { reg.set_sleep(false); reg.set_inrq(true); @@ -25,7 +25,7 @@ impl Registers { } // Leaves initialization mode, enters sleep mode. - pub fn leave_init_mode(&mut self) { + pub fn leave_init_mode(&self) { self.0.mcr().modify(|reg| { reg.set_sleep(true); reg.set_inrq(false); @@ -38,7 +38,7 @@ impl Registers { } } - pub fn set_bit_timing(&mut self, bt: crate::can::util::NominalBitTiming) { + pub fn set_bit_timing(&self, bt: crate::can::util::NominalBitTiming) { let prescaler = u16::from(bt.prescaler) & 0x1FF; let seg1 = u8::from(bt.seg1); let seg2 = u8::from(bt.seg2) & 0x7F; @@ -84,7 +84,7 @@ impl Registers { /// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming /// frame. #[allow(dead_code)] - pub fn set_automatic_wakeup(&mut self, enabled: bool) { + pub fn set_automatic_wakeup(&self, enabled: bool) { self.0.mcr().modify(|reg| reg.set_awum(enabled)); } @@ -96,7 +96,7 @@ impl Registers { /// If this returns [`WouldBlock`][nb::Error::WouldBlock], the peripheral will enable itself /// in the background. The peripheral is enabled and ready to use when this method returns /// successfully. - pub fn enable_non_blocking(&mut self) -> nb::Result<(), Infallible> { + pub fn enable_non_blocking(&self) -> nb::Result<(), Infallible> { let msr = self.0.msr().read(); if msr.slak() { self.0.mcr().modify(|reg| { @@ -186,7 +186,7 @@ impl Registers { /// If this is enabled, mailboxes are scheduled based on the time when the transmit request bit of the mailbox was set. /// /// If this is disabled, mailboxes are scheduled based on the priority of the frame in the mailbox. - pub fn set_tx_fifo_scheduling(&mut self, enabled: bool) { + pub fn set_tx_fifo_scheduling(&self, enabled: bool) { self.0.mcr().modify(|w| w.set_txfp(enabled)) } diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index f63076512..ba8a33e34 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs @@ -18,10 +18,6 @@ use {defmt_rtt as _, panic_probe as _}; mod can_common; use can_common::*; -type Can<'d> = embassy_stm32::can::Can<'d, embassy_stm32::peripherals::CAN1>; -type CanTx<'d> = embassy_stm32::can::CanTx<'d>; -type CanRx<'d> = embassy_stm32::can::CanRx<'d>; - bind_interrupts!(struct Irqs { CAN1_RX0 => Rx0InterruptHandler; CAN1_RX1 => Rx1InterruptHandler; @@ -50,7 +46,7 @@ async fn main(_spawner: Spawner) { let rx_pin = Input::new(&mut rx, Pull::Up); core::mem::forget(rx_pin); - let mut can = Can::new(can, rx, tx, Irqs); + let mut can = embassy_stm32::can::Can::new(can, rx, tx, Irqs); info!("Configuring can..."); diff --git a/tests/stm32/src/bin/can_common.rs b/tests/stm32/src/bin/can_common.rs index fbfbcdc21..4e1740ad5 100644 --- a/tests/stm32/src/bin/can_common.rs +++ b/tests/stm32/src/bin/can_common.rs @@ -8,7 +8,7 @@ pub struct TestOptions { pub max_buffered: u8, } -pub async fn run_can_tests<'d>(can: &mut crate::Can<'d>, options: &TestOptions) { +pub async fn run_can_tests<'d>(can: &mut can::Can<'d>, options: &TestOptions) { //pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) { let mut i: u8 = 0; loop { @@ -80,7 +80,7 @@ pub async fn run_can_tests<'d>(can: &mut crate::Can<'d>, options: &TestOptions) } } -pub async fn run_split_can_tests<'d>(tx: &mut crate::CanTx<'d>, rx: &mut crate::CanRx<'d>, options: &TestOptions) { +pub async fn run_split_can_tests<'d>(tx: &mut can::CanTx<'d>, rx: &mut can::CanRx<'d>, options: &TestOptions) { for i in 0..options.max_buffered { // Try filling up the RX FIFO0 buffers //let tx_frame = if 0 != (i & 0x01) { diff --git a/tests/stm32/src/bin/fdcan.rs b/tests/stm32/src/bin/fdcan.rs index 8a397f661..bc2b7edd4 100644 --- a/tests/stm32/src/bin/fdcan.rs +++ b/tests/stm32/src/bin/fdcan.rs @@ -15,10 +15,6 @@ use {defmt_rtt as _, panic_probe as _}; mod can_common; use can_common::*; -type Can<'d> = can::Can<'d>; -type CanTx<'d> = can::CanTx<'d>; -type CanRx<'d> = can::CanRx<'d>; - bind_interrupts!(struct Irqs2 { FDCAN2_IT0 => can::IT0InterruptHandler; FDCAN2_IT1 => can::IT1InterruptHandler;