mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 08:12:30 +00:00
Merge pull request #3032 from cschuhen/feature/bxcan_no_generics2
Remove more BXCAN generics.
This commit is contained in:
commit
5f8f867eae
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use core::marker::PhantomData;
|
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_RTR: u32 = 0b010; // set the RTR bit to match remote frames
|
||||||
const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers
|
const F32_IDE: u32 = 0b100; // set the IDE bit to match extended identifiers
|
||||||
@ -210,24 +210,24 @@ impl From<Mask32> for BankConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Interface to the filter banks of a CAN peripheral.
|
/// Interface to the filter banks of a CAN peripheral.
|
||||||
pub struct MasterFilters<'a, I: FilterOwner> {
|
pub struct MasterFilters<'a> {
|
||||||
/// Number of assigned filter banks.
|
/// Number of assigned filter banks.
|
||||||
///
|
///
|
||||||
/// On chips with splittable filter banks, this value can be dynamic.
|
/// On chips with splittable filter banks, this value can be dynamic.
|
||||||
bank_count: u8,
|
bank_count: u8,
|
||||||
_can: PhantomData<&'a mut I>,
|
_phantom: PhantomData<&'a ()>,
|
||||||
canregs: crate::pac::can::Can,
|
info: &'static crate::can::Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This type mutably borrows the CAN instance and has unique access to the registers while it
|
// NOTE: This type mutably borrows the CAN instance and has unique access to the registers while it
|
||||||
// exists.
|
// exists.
|
||||||
impl<I: FilterOwner> MasterFilters<'_, I> {
|
impl MasterFilters<'_> {
|
||||||
pub(crate) unsafe fn new(canregs: crate::pac::can::Can) -> Self {
|
pub(crate) unsafe fn new(info: &'static crate::can::Info) -> Self {
|
||||||
// Enable initialization mode.
|
// 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.
|
// 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
|
// (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
|
// of them to the master peripheral, and in devices with 28, assigns them 50/50 to
|
||||||
@ -235,8 +235,8 @@ impl<I: FilterOwner> MasterFilters<'_, I> {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
bank_count,
|
bank_count,
|
||||||
_can: PhantomData,
|
_phantom: PhantomData,
|
||||||
canregs,
|
info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ impl<I: FilterOwner> MasterFilters<'_, I> {
|
|||||||
FilterBanks {
|
FilterBanks {
|
||||||
start_idx: 0,
|
start_idx: 0,
|
||||||
bank_count: self.bank_count,
|
bank_count: self.bank_count,
|
||||||
canregs: self.canregs,
|
info: self.info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,49 +291,49 @@ impl<I: FilterOwner> MasterFilters<'_, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: MasterInstance> MasterFilters<'_, I> {
|
impl MasterFilters<'_> {
|
||||||
/// Sets the index at which the filter banks owned by the slave peripheral start.
|
/// 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 {
|
pub fn set_split(&mut self, split_index: u8) -> &mut Self {
|
||||||
assert!(split_index <= I::NUM_FILTER_BANKS);
|
assert!(split_index <= self.info.num_filter_banks);
|
||||||
self.canregs.fmr().modify(|reg| reg.set_can2sb(split_index));
|
self.info.regs.0.fmr().modify(|reg| reg.set_can2sb(split_index));
|
||||||
self.bank_count = split_index;
|
self.bank_count = split_index;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accesses the filters assigned to the slave peripheral.
|
/// 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.
|
// NB: This mutably borrows `self`, so it has full access to the filter bank registers.
|
||||||
SlaveFilters {
|
SlaveFilters {
|
||||||
start_idx: self.bank_count,
|
start_idx: self.bank_count,
|
||||||
bank_count: I::NUM_FILTER_BANKS - self.bank_count,
|
bank_count: self.info.num_filter_banks - self.bank_count,
|
||||||
_can: PhantomData,
|
_phantom: PhantomData,
|
||||||
canregs: self.canregs,
|
info: self.info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: FilterOwner> Drop for MasterFilters<'_, I> {
|
impl Drop for MasterFilters<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Leave initialization mode.
|
// 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.
|
/// Interface to the filter banks assigned to a slave peripheral.
|
||||||
pub struct SlaveFilters<'a, I: Instance> {
|
pub struct SlaveFilters<'a> {
|
||||||
start_idx: u8,
|
start_idx: u8,
|
||||||
bank_count: u8,
|
bank_count: u8,
|
||||||
_can: PhantomData<&'a mut I>,
|
_phantom: PhantomData<&'a ()>,
|
||||||
canregs: crate::pac::can::Can,
|
info: &'static crate::can::Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Instance> SlaveFilters<'_, I> {
|
impl SlaveFilters<'_> {
|
||||||
fn banks_imm(&self) -> FilterBanks {
|
fn banks_imm(&self) -> FilterBanks {
|
||||||
FilterBanks {
|
FilterBanks {
|
||||||
start_idx: self.start_idx,
|
start_idx: self.start_idx,
|
||||||
bank_count: self.bank_count,
|
bank_count: self.bank_count,
|
||||||
canregs: self.canregs,
|
info: self.info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,14 +377,14 @@ impl<I: Instance> SlaveFilters<'_, I> {
|
|||||||
struct FilterBanks {
|
struct FilterBanks {
|
||||||
start_idx: u8,
|
start_idx: u8,
|
||||||
bank_count: u8,
|
bank_count: u8,
|
||||||
canregs: crate::pac::can::Can,
|
info: &'static crate::can::Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterBanks {
|
impl FilterBanks {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
let mask = filter_bitmask(self.start_idx, self.bank_count);
|
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 {
|
for i in 0..28usize {
|
||||||
if (0x01u32 << i) & mask != 0 {
|
if (0x01u32 << i) & mask != 0 {
|
||||||
reg.set_fact(i, false);
|
reg.set_fact(i, false);
|
||||||
@ -399,7 +399,11 @@ impl FilterBanks {
|
|||||||
|
|
||||||
fn disable(&mut self, index: u8) {
|
fn disable(&mut self, index: u8) {
|
||||||
self.assert_bank_index(index);
|
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) {
|
fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) {
|
||||||
@ -407,11 +411,11 @@ impl FilterBanks {
|
|||||||
|
|
||||||
// Configure mode.
|
// Configure mode.
|
||||||
let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_));
|
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.
|
// Configure scale.
|
||||||
let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_));
|
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.
|
// Configure filter register.
|
||||||
let (fxr1, fxr2);
|
let (fxr1, fxr2);
|
||||||
@ -433,12 +437,12 @@ impl FilterBanks {
|
|||||||
fxr2 = a.mask;
|
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.fr1().write(|w| w.0 = fxr1);
|
||||||
bank.fr2().write(|w| w.0 = fxr2);
|
bank.fr2().write(|w| w.0 = fxr2);
|
||||||
|
|
||||||
// Assign to the right FIFO
|
// Assign to the right FIFO
|
||||||
self.canregs.ffa1r().modify(|reg| {
|
self.info.regs.0.ffa1r().modify(|reg| {
|
||||||
reg.set_ffa(
|
reg.set_ffa(
|
||||||
index as usize,
|
index as usize,
|
||||||
match fifo {
|
match fifo {
|
||||||
@ -449,7 +453,7 @@ impl FilterBanks {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set active.
|
// 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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use core::marker::PhantomData;
|
|||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_internal::interrupt::InterruptExt;
|
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::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::channel::Channel;
|
use embassy_sync::channel::Channel;
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
@ -91,11 +91,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::SCEInterrupt> for SceInterrup
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration proxy returned by [`Can::modify_config`].
|
/// Configuration proxy returned by [`Can::modify_config`].
|
||||||
pub struct CanConfig<'a, T: Instance> {
|
pub struct CanConfig<'a> {
|
||||||
can: PhantomData<&'a mut T>,
|
phantom: PhantomData<&'a ()>,
|
||||||
|
info: &'static Info,
|
||||||
|
periph_clock: crate::time::Hertz,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> CanConfig<'_, T> {
|
impl CanConfig<'_> {
|
||||||
/// Configures the bit timings.
|
/// Configures the bit timings.
|
||||||
///
|
///
|
||||||
/// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
|
/// You can use <http://www.bittiming.can-wiki.info/> to calculate the `btr` parameter. Enter
|
||||||
@ -109,7 +111,7 @@ impl<T: Instance> CanConfig<'_, T> {
|
|||||||
/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
|
/// Then copy the `CAN_BUS_TIME` register value from the table and pass it as the `btr`
|
||||||
/// parameter to this method.
|
/// parameter to this method.
|
||||||
pub fn set_bit_timing(self, bt: crate::can::util::NominalBitTiming) -> Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,20 +119,20 @@ impl<T: Instance> CanConfig<'_, T> {
|
|||||||
///
|
///
|
||||||
/// This is a helper that internally calls `set_bit_timing()`[Self::set_bit_timing].
|
/// This is a helper that internally calls `set_bit_timing()`[Self::set_bit_timing].
|
||||||
pub fn set_bitrate(self, bitrate: u32) -> Self {
|
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)
|
self.set_bit_timing(bit_timing)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables or disables loopback mode: Internally connects the TX and RX
|
/// Enables or disables loopback mode: Internally connects the TX and RX
|
||||||
/// signals together.
|
/// signals together.
|
||||||
pub fn set_loopback(self, enabled: bool) -> Self {
|
pub fn set_loopback(self, enabled: bool) -> Self {
|
||||||
Registers(T::regs()).set_loopback(enabled);
|
self.info.regs.set_loopback(enabled);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables or disables silent mode: Disconnects the TX signal from the pin.
|
/// Enables or disables silent mode: Disconnects the TX signal from the pin.
|
||||||
pub fn set_silent(self, enabled: bool) -> Self {
|
pub fn set_silent(self, enabled: bool) -> Self {
|
||||||
Registers(T::regs()).set_silent(enabled);
|
self.info.regs.set_silent(enabled);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,23 +143,24 @@ impl<T: Instance> CanConfig<'_, T> {
|
|||||||
///
|
///
|
||||||
/// Automatic retransmission is enabled by default.
|
/// Automatic retransmission is enabled by default.
|
||||||
pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
|
pub fn set_automatic_retransmit(self, enabled: bool) -> Self {
|
||||||
Registers(T::regs()).set_automatic_retransmit(enabled);
|
self.info.regs.set_automatic_retransmit(enabled);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Instance> Drop for CanConfig<'_, T> {
|
impl Drop for CanConfig<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
Registers(T::regs()).leave_init_mode();
|
self.info.regs.leave_init_mode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CAN driver
|
/// CAN driver
|
||||||
pub struct Can<'d, T: Instance> {
|
pub struct Can<'d> {
|
||||||
_peri: PeripheralRef<'d, T>,
|
phantom: PhantomData<&'d ()>,
|
||||||
info: &'static Info,
|
info: &'static Info,
|
||||||
state: &'static State,
|
state: &'static State,
|
||||||
|
periph_clock: crate::time::Hertz,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error returned by `try_write`
|
/// Error returned by `try_write`
|
||||||
@ -168,11 +171,11 @@ pub enum TryWriteError {
|
|||||||
Full,
|
Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Can<'d, T> {
|
impl<'d> Can<'d> {
|
||||||
/// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
|
/// Creates a new Bxcan instance, keeping the peripheral in sleep mode.
|
||||||
/// You must call [Can::enable_non_blocking] to use the peripheral.
|
/// You must call [Can::enable_non_blocking] to use the peripheral.
|
||||||
pub fn new(
|
pub fn new<T: Instance>(
|
||||||
peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
_irqs: impl interrupt::typelevel::Binding<T::TXInterrupt, TxInterruptHandler<T>>
|
_irqs: impl interrupt::typelevel::Binding<T::TXInterrupt, TxInterruptHandler<T>>
|
||||||
@ -181,7 +184,7 @@ impl<'d, T: Instance> Can<'d, T> {
|
|||||||
+ interrupt::typelevel::Binding<T::SCEInterrupt, SceInterruptHandler<T>>
|
+ interrupt::typelevel::Binding<T::SCEInterrupt, SceInterruptHandler<T>>
|
||||||
+ 'd,
|
+ 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(peri, rx, tx);
|
into_ref!(_peri, rx, tx);
|
||||||
let info = T::info();
|
let info = T::info();
|
||||||
let regs = &T::info().regs;
|
let regs = &T::info().regs;
|
||||||
|
|
||||||
@ -226,15 +229,16 @@ impl<'d, T: Instance> Can<'d, T> {
|
|||||||
Registers(T::regs()).leave_init_mode();
|
Registers(T::regs()).leave_init_mode();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
_peri: peri,
|
phantom: PhantomData,
|
||||||
info: T::info(),
|
info: T::info(),
|
||||||
state: T::state(),
|
state: T::state(),
|
||||||
|
periph_clock: T::frequency(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set CAN bit rate.
|
/// Set CAN bit rate.
|
||||||
pub fn set_bitrate(&mut self, bitrate: u32) {
|
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);
|
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
|
/// Calling this method will enter initialization mode. You must enable the peripheral
|
||||||
/// again afterwards with [`enable`](Self::enable).
|
/// again afterwards with [`enable`](Self::enable).
|
||||||
pub fn modify_config(&mut self) -> CanConfig<'_, T> {
|
pub fn modify_config(&mut self) -> CanConfig<'_> {
|
||||||
Registers(T::regs()).enter_init_mode();
|
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.
|
/// 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).
|
/// 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.
|
/// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
|
||||||
pub async fn enable(&mut self) {
|
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.
|
// SCE interrupt is only generated for entering sleep mode, but not leaving.
|
||||||
// Yield to allow other tasks to execute while can bus is initializing.
|
// Yield to allow other tasks to execute while can bus is initializing.
|
||||||
embassy_futures::yield_now().await;
|
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
|
/// Enables or disables the peripheral from automatically wakeup when a SOF is detected on the bus
|
||||||
/// while the peripheral is in sleep mode
|
/// while the peripheral is in sleep mode
|
||||||
pub fn set_automatic_wakeup(&mut self, enabled: bool) {
|
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.
|
/// Manually wake the peripheral from sleep mode.
|
||||||
@ -313,12 +321,12 @@ impl<'d, T: Instance> Can<'d, T> {
|
|||||||
///
|
///
|
||||||
/// FIFO scheduling is disabled by default.
|
/// FIFO scheduling is disabled by default.
|
||||||
pub fn set_tx_fifo_scheduling(&mut self, enabled: bool) {
|
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.
|
/// Checks if FIFO scheduling of outgoing frames is enabled.
|
||||||
pub fn tx_fifo_scheduling_enabled(&self) -> bool {
|
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.
|
/// 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.
|
/// 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
|
/// To modify filters of a slave peripheral, `modify_filters` has to be called on the master
|
||||||
/// peripheral instead.
|
/// peripheral instead.
|
||||||
pub fn modify_filters(&mut self) -> MasterFilters<'_, T> {
|
pub fn modify_filters(&mut self) -> MasterFilters<'_> {
|
||||||
unsafe { MasterFilters::new(self.info.regs.0) }
|
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) {
|
fn drop(&mut self) {
|
||||||
// Cannot call `free()` because it moves the instance.
|
// Cannot call `free()` because it moves the instance.
|
||||||
// Manually reset the peripheral.
|
// Manually reset the peripheral.
|
||||||
T::regs().mcr().write(|w| w.set_reset(true));
|
self.info.regs.0.mcr().write(|w| w.set_reset(true));
|
||||||
rcc::disable::<T>();
|
self.info.regs.enter_init_mode();
|
||||||
|
self.info.regs.leave_init_mode();
|
||||||
|
//rcc::disable::<T>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1041,11 @@ pub(crate) struct Info {
|
|||||||
rx1_interrupt: crate::interrupt::Interrupt,
|
rx1_interrupt: crate::interrupt::Interrupt,
|
||||||
sce_interrupt: crate::interrupt::Interrupt,
|
sce_interrupt: crate::interrupt::Interrupt,
|
||||||
tx_waker: fn(),
|
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 {
|
trait SealedInstance {
|
||||||
@ -1095,6 +1110,7 @@ foreach_peripheral!(
|
|||||||
rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
|
rx1_interrupt: crate::_generated::peripheral_interrupts::$inst::RX1::IRQ,
|
||||||
sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
|
sce_interrupt: crate::_generated::peripheral_interrupts::$inst::SCE::IRQ,
|
||||||
tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
|
tx_waker: crate::_generated::peripheral_interrupts::$inst::TX::pend,
|
||||||
|
num_filter_banks: peripherals::$inst::NUM_FILTER_BANKS,
|
||||||
};
|
};
|
||||||
&INFO
|
&INFO
|
||||||
}
|
}
|
||||||
@ -1148,6 +1164,11 @@ foreach_peripheral!(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
(can, CAN2) => {
|
||||||
|
unsafe impl FilterOwner for peripherals::CAN2 {
|
||||||
|
const NUM_FILTER_BANKS: u8 = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
(can, CAN3) => {
|
(can, CAN3) => {
|
||||||
unsafe impl FilterOwner for peripherals::CAN3 {
|
unsafe impl FilterOwner for peripherals::CAN3 {
|
||||||
const NUM_FILTER_BANKS: u8 = 14;
|
const NUM_FILTER_BANKS: u8 = 14;
|
||||||
|
@ -11,7 +11,7 @@ use crate::can::frame::{Envelope, Frame, Header};
|
|||||||
pub(crate) struct Registers(pub crate::pac::can::Can);
|
pub(crate) struct Registers(pub crate::pac::can::Can);
|
||||||
|
|
||||||
impl Registers {
|
impl Registers {
|
||||||
pub fn enter_init_mode(&mut self) {
|
pub fn enter_init_mode(&self) {
|
||||||
self.0.mcr().modify(|reg| {
|
self.0.mcr().modify(|reg| {
|
||||||
reg.set_sleep(false);
|
reg.set_sleep(false);
|
||||||
reg.set_inrq(true);
|
reg.set_inrq(true);
|
||||||
@ -25,7 +25,7 @@ impl Registers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Leaves initialization mode, enters sleep mode.
|
// Leaves initialization mode, enters sleep mode.
|
||||||
pub fn leave_init_mode(&mut self) {
|
pub fn leave_init_mode(&self) {
|
||||||
self.0.mcr().modify(|reg| {
|
self.0.mcr().modify(|reg| {
|
||||||
reg.set_sleep(true);
|
reg.set_sleep(true);
|
||||||
reg.set_inrq(false);
|
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 prescaler = u16::from(bt.prescaler) & 0x1FF;
|
||||||
let seg1 = u8::from(bt.seg1);
|
let seg1 = u8::from(bt.seg1);
|
||||||
let seg2 = u8::from(bt.seg2) & 0x7F;
|
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
|
/// receive the frame. If enabled, [`Interrupt::Wakeup`] will also be triggered by the incoming
|
||||||
/// frame.
|
/// frame.
|
||||||
#[allow(dead_code)]
|
#[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));
|
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
|
/// 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
|
/// in the background. The peripheral is enabled and ready to use when this method returns
|
||||||
/// successfully.
|
/// 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();
|
let msr = self.0.msr().read();
|
||||||
if msr.slak() {
|
if msr.slak() {
|
||||||
self.0.mcr().modify(|reg| {
|
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 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.
|
/// 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))
|
self.0.mcr().modify(|w| w.set_txfp(enabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ async fn main(spawner: Spawner) {
|
|||||||
let rx_pin = Input::new(&mut p.PA15, Pull::Up);
|
let rx_pin = Input::new(&mut p.PA15, Pull::Up);
|
||||||
core::mem::forget(rx_pin);
|
core::mem::forget(rx_pin);
|
||||||
|
|
||||||
static CAN: StaticCell<Can<'static, CAN3>> = StaticCell::new();
|
static CAN: StaticCell<Can<'static>> = StaticCell::new();
|
||||||
let can = CAN.init(Can::new(p.CAN3, p.PA8, p.PA15, Irqs));
|
let can = CAN.init(Can::new(p.CAN3, p.PA8, p.PA15, Irqs));
|
||||||
can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
|
can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all());
|
||||||
|
|
||||||
|
@ -18,10 +18,6 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
mod can_common;
|
mod can_common;
|
||||||
use 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 {
|
bind_interrupts!(struct Irqs {
|
||||||
CAN1_RX0 => Rx0InterruptHandler<CAN1>;
|
CAN1_RX0 => Rx0InterruptHandler<CAN1>;
|
||||||
CAN1_RX1 => Rx1InterruptHandler<CAN1>;
|
CAN1_RX1 => Rx1InterruptHandler<CAN1>;
|
||||||
@ -50,7 +46,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
let rx_pin = Input::new(&mut rx, Pull::Up);
|
let rx_pin = Input::new(&mut rx, Pull::Up);
|
||||||
core::mem::forget(rx_pin);
|
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...");
|
info!("Configuring can...");
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ pub struct TestOptions {
|
|||||||
pub max_buffered: u8,
|
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) {
|
//pub async fn run_can_tests<'d, T: can::Instance>(can: &mut can::Can<'d, T>, options: &TestOptions) {
|
||||||
let mut i: u8 = 0;
|
let mut i: u8 = 0;
|
||||||
loop {
|
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 {
|
for i in 0..options.max_buffered {
|
||||||
// Try filling up the RX FIFO0 buffers
|
// Try filling up the RX FIFO0 buffers
|
||||||
//let tx_frame = if 0 != (i & 0x01) {
|
//let tx_frame = if 0 != (i & 0x01) {
|
||||||
|
@ -15,10 +15,6 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
mod can_common;
|
mod can_common;
|
||||||
use 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 {
|
bind_interrupts!(struct Irqs2 {
|
||||||
FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>;
|
FDCAN2_IT0 => can::IT0InterruptHandler<FDCAN2>;
|
||||||
FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>;
|
FDCAN2_IT1 => can::IT1InterruptHandler<FDCAN2>;
|
||||||
|
Loading…
Reference in New Issue
Block a user