mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 06:40:32 +00:00
Merge pull request #4348 from melvdlin/stm32-ch-generic-timer-traits
[stm32]: Replace per-channel traits in `timer` module with generic versions
This commit is contained in:
commit
77fc1bac2a
@ -1090,21 +1090,21 @@ fn main() {
|
||||
(("fmc", "CLK"), quote!(crate::fmc::ClkPin)),
|
||||
(("fmc", "BA0"), quote!(crate::fmc::BA0Pin)),
|
||||
(("fmc", "BA1"), quote!(crate::fmc::BA1Pin)),
|
||||
(("timer", "CH1"), quote!(crate::timer::Channel1Pin)),
|
||||
(("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)),
|
||||
(("timer", "CH2"), quote!(crate::timer::Channel2Pin)),
|
||||
(("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)),
|
||||
(("timer", "CH3"), quote!(crate::timer::Channel3Pin)),
|
||||
(("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)),
|
||||
(("timer", "CH4"), quote!(crate::timer::Channel4Pin)),
|
||||
(("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)),
|
||||
(("timer", "CH1"), quote!(crate::timer::TimerPin<Ch1>)),
|
||||
(("timer", "CH1N"), quote!(crate::timer::TimerComplementaryPin<Ch1>)),
|
||||
(("timer", "CH2"), quote!(crate::timer::TimerPin<Ch2>)),
|
||||
(("timer", "CH2N"), quote!(crate::timer::TimerComplementaryPin<Ch2>)),
|
||||
(("timer", "CH3"), quote!(crate::timer::TimerPin<Ch3>)),
|
||||
(("timer", "CH3N"), quote!(crate::timer::TimerComplementaryPin<Ch3>)),
|
||||
(("timer", "CH4"), quote!(crate::timer::TimerPin<Ch4>)),
|
||||
(("timer", "CH4N"), quote!(crate::timer::TimerComplementaryPin<Ch4>)),
|
||||
(("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)),
|
||||
(("timer", "BKIN"), quote!(crate::timer::BreakInputPin)),
|
||||
(("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)),
|
||||
(("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)),
|
||||
(("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)),
|
||||
(("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)),
|
||||
(("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)),
|
||||
(("timer", "BKIN"), quote!(crate::timer::BreakInputPin<BkIn1>)),
|
||||
(("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin<BkIn1>)),
|
||||
(("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin<BkIn1>)),
|
||||
(("timer", "BKIN2"), quote!(crate::timer::BreakInputPin<BkIn2>)),
|
||||
(("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInputComparator1Pin<BkIn2>)),
|
||||
(("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInputComparator2Pin<BkIn2>)),
|
||||
(("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)),
|
||||
(("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)),
|
||||
(("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)),
|
||||
@ -1475,10 +1475,10 @@ fn main() {
|
||||
(("hash", "IN"), quote!(crate::hash::Dma)),
|
||||
(("cryp", "IN"), quote!(crate::cryp::DmaIn)),
|
||||
(("cryp", "OUT"), quote!(crate::cryp::DmaOut)),
|
||||
(("timer", "CH1"), quote!(crate::timer::Ch1Dma)),
|
||||
(("timer", "CH2"), quote!(crate::timer::Ch2Dma)),
|
||||
(("timer", "CH3"), quote!(crate::timer::Ch3Dma)),
|
||||
(("timer", "CH4"), quote!(crate::timer::Ch4Dma)),
|
||||
(("timer", "CH1"), quote!(crate::timer::Dma<Ch1>)),
|
||||
(("timer", "CH2"), quote!(crate::timer::Dma<Ch2>)),
|
||||
(("timer", "CH3"), quote!(crate::timer::Dma<Ch3>)),
|
||||
(("timer", "CH4"), quote!(crate::timer::Dma<Ch4>)),
|
||||
(("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver
|
||||
(("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver
|
||||
]
|
||||
|
@ -5,14 +5,12 @@ use core::marker::PhantomData;
|
||||
use stm32_metapac::timer::vals::Ckd;
|
||||
|
||||
use super::low_level::{CountingMode, OutputPolarity, Timer};
|
||||
use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin};
|
||||
use super::{
|
||||
AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin,
|
||||
Channel4ComplementaryPin,
|
||||
};
|
||||
use super::simple_pwm::PwmPin;
|
||||
use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin};
|
||||
use crate::gpio::{AnyPin, OutputType};
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::low_level::OutputCompareMode;
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// Complementary PWM pin wrapper.
|
||||
@ -23,32 +21,23 @@ pub struct ComplementaryPwmPin<'d, T, C> {
|
||||
phantom: PhantomData<(T, C)>,
|
||||
}
|
||||
|
||||
macro_rules! complementary_channel_impl {
|
||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(
|
||||
pin.af_num(),
|
||||
crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
|
||||
);
|
||||
});
|
||||
ComplementaryPwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> {
|
||||
/// Create a new complementary PWM pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerComplementaryPin<T, C>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(
|
||||
pin.af_num(),
|
||||
crate::gpio::AfType::output(output_type, crate::gpio::Speed::VeryHigh),
|
||||
);
|
||||
});
|
||||
ComplementaryPwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin);
|
||||
complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin);
|
||||
complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin);
|
||||
complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin);
|
||||
|
||||
/// PWM driver with support for standard and complementary outputs.
|
||||
pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> {
|
||||
inner: Timer<'d, T>,
|
||||
|
@ -6,14 +6,12 @@ use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer};
|
||||
use super::{
|
||||
CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
|
||||
GeneralInstance4Channel,
|
||||
};
|
||||
use super::{CaptureCompareInterruptHandler, Channel, GeneralInstance4Channel, TimerPin};
|
||||
pub use super::{Ch1, Ch2, Ch3, Ch4};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||
use crate::time::Hertz;
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// Capture pin wrapper.
|
||||
@ -23,27 +21,17 @@ pub struct CapturePin<'d, T, C> {
|
||||
_pin: Peri<'d, AnyPin>,
|
||||
phantom: PhantomData<(T, C)>,
|
||||
}
|
||||
|
||||
macro_rules! channel_impl {
|
||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> CapturePin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, pull: Pull) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
CapturePin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> {
|
||||
/// Create a new capture pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, pull: Pull) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
CapturePin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
||||
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
||||
channel_impl!(new_ch3, Ch3, Channel3Pin);
|
||||
channel_impl!(new_ch4, Ch4, Channel4Pin);
|
||||
|
||||
/// Input capture driver.
|
||||
pub struct InputCapture<'d, T: GeneralInstance4Channel> {
|
||||
inner: Timer<'d, T>,
|
||||
|
@ -51,6 +51,80 @@ pub enum Ch3 {}
|
||||
/// Channel 4 marker type.
|
||||
pub enum Ch4 {}
|
||||
|
||||
/// Timer channel trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait TimerChannel: SealedTimerChannel {
|
||||
/// The runtime channel.
|
||||
const CHANNEL: Channel;
|
||||
}
|
||||
|
||||
trait SealedTimerChannel {}
|
||||
|
||||
impl TimerChannel for Ch1 {
|
||||
const CHANNEL: Channel = Channel::Ch1;
|
||||
}
|
||||
|
||||
impl TimerChannel for Ch2 {
|
||||
const CHANNEL: Channel = Channel::Ch2;
|
||||
}
|
||||
|
||||
impl TimerChannel for Ch3 {
|
||||
const CHANNEL: Channel = Channel::Ch3;
|
||||
}
|
||||
|
||||
impl TimerChannel for Ch4 {
|
||||
const CHANNEL: Channel = Channel::Ch4;
|
||||
}
|
||||
|
||||
impl SealedTimerChannel for Ch1 {}
|
||||
impl SealedTimerChannel for Ch2 {}
|
||||
impl SealedTimerChannel for Ch3 {}
|
||||
impl SealedTimerChannel for Ch4 {}
|
||||
|
||||
/// Timer break input.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BkIn {
|
||||
/// Break input 1.
|
||||
BkIn1,
|
||||
/// Break input 2.
|
||||
BkIn2,
|
||||
}
|
||||
|
||||
impl BkIn {
|
||||
/// Get the channel index (0..3)
|
||||
pub fn index(&self) -> usize {
|
||||
match self {
|
||||
BkIn::BkIn1 => 0,
|
||||
BkIn::BkIn2 => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Break input 1 marker type.
|
||||
pub enum BkIn1 {}
|
||||
/// Break input 2 marker type.
|
||||
pub enum BkIn2 {}
|
||||
|
||||
/// Timer channel trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait BreakInput: SealedBreakInput {
|
||||
/// The runtim timer channel.
|
||||
const INPUT: BkIn;
|
||||
}
|
||||
|
||||
trait SealedBreakInput {}
|
||||
|
||||
impl BreakInput for BkIn1 {
|
||||
const INPUT: BkIn = BkIn::BkIn1;
|
||||
}
|
||||
|
||||
impl BreakInput for BkIn2 {
|
||||
const INPUT: BkIn = BkIn::BkIn2;
|
||||
}
|
||||
|
||||
impl SealedBreakInput for BkIn1 {}
|
||||
impl SealedBreakInput for BkIn2 {}
|
||||
|
||||
/// Amount of bits of a timer.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@ -149,33 +223,20 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad
|
||||
/// Advanced 16-bit timer with 4 channels instance.
|
||||
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
|
||||
|
||||
pin_trait!(Channel1Pin, GeneralInstance4Channel);
|
||||
pin_trait!(Channel2Pin, GeneralInstance4Channel);
|
||||
pin_trait!(Channel3Pin, GeneralInstance4Channel);
|
||||
pin_trait!(Channel4Pin, GeneralInstance4Channel);
|
||||
pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
|
||||
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
|
||||
|
||||
pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
|
||||
pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
|
||||
pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
|
||||
pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
|
||||
pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
|
||||
|
||||
pin_trait!(BreakInputPin, AdvancedInstance4Channel);
|
||||
pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
|
||||
pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
|
||||
|
||||
pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
|
||||
pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
|
||||
|
||||
pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
|
||||
pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel);
|
||||
pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput);
|
||||
pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
|
||||
|
||||
// Update Event trigger DMA for every timer
|
||||
dma_trait!(UpDma, BasicInstance);
|
||||
|
||||
dma_trait!(Ch1Dma, GeneralInstance4Channel);
|
||||
dma_trait!(Ch2Dma, GeneralInstance4Channel);
|
||||
dma_trait!(Ch3Dma, GeneralInstance4Channel);
|
||||
dma_trait!(Ch4Dma, GeneralInstance4Channel);
|
||||
dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_core_timer {
|
||||
|
@ -7,11 +7,9 @@ use core::pin::Pin;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use super::low_level::{
|
||||
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource,
|
||||
};
|
||||
use super::{
|
||||
CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, ExternalTriggerPin, GeneralInstance4Channel,
|
||||
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
|
||||
};
|
||||
use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin};
|
||||
pub use super::{Ch1, Ch2};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||
@ -48,24 +46,78 @@ pub struct TriggerPin<'d, T, C> {
|
||||
phantom: PhantomData<(T, C)>,
|
||||
}
|
||||
|
||||
macro_rules! channel_impl {
|
||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " trigger pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, pull: Pull) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
TriggerPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
trait SealedTriggerSource {}
|
||||
|
||||
/// Marker trait for a trigger source.
|
||||
#[expect(private_bounds)]
|
||||
pub trait TriggerSource: SealedTriggerSource {}
|
||||
|
||||
impl TriggerSource for Ch1 {}
|
||||
impl TriggerSource for Ch2 {}
|
||||
impl TriggerSource for Ext {}
|
||||
|
||||
impl SealedTriggerSource for Ch1 {}
|
||||
impl SealedTriggerSource for Ch2 {}
|
||||
impl SealedTriggerSource for Ext {}
|
||||
|
||||
trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
|
||||
|
||||
/// Marker trait for a trigger pin.
|
||||
#[expect(private_bounds)]
|
||||
// TODO: find better naming scheme than prefixing all pin traits with "Timer".
|
||||
// The trait name cannot conflict with the corresponding type's name.
|
||||
// Applies to other timer submodules as well.
|
||||
pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
|
||||
/// Get the AF number needed to use this pin as a trigger source.
|
||||
fn af_num(&self) -> u8;
|
||||
}
|
||||
|
||||
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
||||
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
||||
channel_impl!(new_ext, Ext, ExternalTriggerPin);
|
||||
impl<T, P, C> TimerTriggerPin<T, C> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
P: TimerPin<T, C>,
|
||||
C: super::TimerChannel + TriggerSource,
|
||||
{
|
||||
fn af_num(&self) -> u8 {
|
||||
TimerPin::af_num(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P> TimerTriggerPin<T, Ext> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
P: ExternalTriggerPin<T>,
|
||||
{
|
||||
fn af_num(&self) -> u8 {
|
||||
ExternalTriggerPin::af_num(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P, C> SealedTimerTriggerPin<T, C> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
P: TimerPin<T, C>,
|
||||
C: super::TimerChannel + TriggerSource,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, P> SealedTimerTriggerPin<T, Ext> for P
|
||||
where
|
||||
T: GeneralInstance4Channel,
|
||||
P: ExternalTriggerPin<T>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
|
||||
/// "Create a new Ch1 trigger pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
TriggerPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One pulse driver.
|
||||
///
|
||||
@ -89,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
) -> Self {
|
||||
let mut this = Self { inner: Timer::new(tim) };
|
||||
|
||||
this.inner.set_trigger_source(TriggerSource::TI1F_ED);
|
||||
this.inner.set_trigger_source(Ts::TI1F_ED);
|
||||
this.inner
|
||||
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||
this.inner
|
||||
@ -114,7 +166,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
) -> Self {
|
||||
let mut this = Self { inner: Timer::new(tim) };
|
||||
|
||||
this.inner.set_trigger_source(TriggerSource::TI1FP1);
|
||||
this.inner.set_trigger_source(Ts::TI1FP1);
|
||||
this.inner
|
||||
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||
this.inner
|
||||
@ -140,7 +192,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
) -> Self {
|
||||
let mut this = Self { inner: Timer::new(tim) };
|
||||
|
||||
this.inner.set_trigger_source(TriggerSource::TI2FP2);
|
||||
this.inner.set_trigger_source(Ts::TI2FP2);
|
||||
this.inner
|
||||
.set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
|
||||
this.inner
|
||||
@ -172,7 +224,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||
// No filtering
|
||||
r.set_etf(FilterValue::NO_FILTER);
|
||||
});
|
||||
this.inner.set_trigger_source(TriggerSource::ETRF);
|
||||
this.inner.set_trigger_source(Ts::ETRF);
|
||||
this.new_inner(freq, pulse_end, counting_mode);
|
||||
|
||||
this
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! PWM Input driver.
|
||||
|
||||
use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource};
|
||||
use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel};
|
||||
use super::{Ch1, Ch2, Channel, GeneralInstance4Channel, TimerPin};
|
||||
use crate::gpio::{AfType, Pull};
|
||||
use crate::time::Hertz;
|
||||
use crate::Peri;
|
||||
@ -14,14 +14,14 @@ pub struct PwmInput<'d, T: GeneralInstance4Channel> {
|
||||
|
||||
impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> {
|
||||
/// Create a new PWM input driver.
|
||||
pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl Channel1Pin<T>>, pull: Pull, freq: Hertz) -> Self {
|
||||
pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull, freq: Hertz) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
|
||||
Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2)
|
||||
}
|
||||
|
||||
/// Create a new PWM input driver.
|
||||
pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl Channel2Pin<T>>, pull: Pull, freq: Hertz) -> Self {
|
||||
pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull, freq: Hertz) -> Self {
|
||||
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||
|
||||
Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1)
|
||||
|
@ -6,8 +6,9 @@ use stm32_metapac::timer::vals;
|
||||
|
||||
use super::low_level::Timer;
|
||||
pub use super::{Ch1, Ch2};
|
||||
use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
|
||||
use super::{GeneralInstance4Channel, TimerPin};
|
||||
use crate::gpio::{AfType, AnyPin, Pull};
|
||||
use crate::timer::TimerChannel;
|
||||
use crate::Peri;
|
||||
|
||||
/// Counting direction
|
||||
@ -24,26 +25,31 @@ pub struct QeiPin<'d, T, Channel> {
|
||||
phantom: PhantomData<(T, Channel)>,
|
||||
}
|
||||
|
||||
macro_rules! channel_impl {
|
||||
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
|
||||
});
|
||||
QeiPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
|
||||
/// Create a new QEI pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
|
||||
});
|
||||
QeiPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
||||
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
||||
trait SealedQeiChannel: TimerChannel {}
|
||||
|
||||
/// Marker trait for a timer channel eligible for use with QEI.
|
||||
#[expect(private_bounds)]
|
||||
pub trait QeiChannel: SealedQeiChannel {}
|
||||
|
||||
impl QeiChannel for Ch1 {}
|
||||
impl QeiChannel for Ch2 {}
|
||||
|
||||
impl SealedQeiChannel for Ch1 {}
|
||||
impl SealedQeiChannel for Ch2 {}
|
||||
|
||||
/// Quadrature decoder driver.
|
||||
pub struct Qei<'d, T: GeneralInstance4Channel> {
|
||||
|
@ -4,22 +4,13 @@ use core::marker::PhantomData;
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer};
|
||||
use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel, TimerBits};
|
||||
use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin};
|
||||
#[cfg(gpio_v2)]
|
||||
use crate::gpio::Pull;
|
||||
use crate::gpio::{AfType, AnyPin, OutputType, Speed};
|
||||
use crate::time::Hertz;
|
||||
use crate::Peri;
|
||||
|
||||
/// Channel 1 marker type.
|
||||
pub enum Ch1 {}
|
||||
/// Channel 2 marker type.
|
||||
pub enum Ch2 {}
|
||||
/// Channel 3 marker type.
|
||||
pub enum Ch3 {}
|
||||
/// Channel 4 marker type.
|
||||
pub enum Ch4 {}
|
||||
|
||||
/// PWM pin wrapper.
|
||||
///
|
||||
/// This wraps a pin to make it usable with PWM.
|
||||
@ -43,46 +34,37 @@ pub struct PwmPinConfig {
|
||||
pub pull: Pull,
|
||||
}
|
||||
|
||||
macro_rules! channel_impl {
|
||||
($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> {
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
|
||||
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
||||
});
|
||||
PwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")]
|
||||
pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait<T>>, pin_config: PwmPinConfig) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(
|
||||
pin.af_num(),
|
||||
#[cfg(gpio_v1)]
|
||||
AfType::output(pin_config.output_type, pin_config.speed),
|
||||
#[cfg(gpio_v2)]
|
||||
AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
|
||||
);
|
||||
});
|
||||
PwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> {
|
||||
/// Create a new PWM pin instance.
|
||||
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>, output_type: OutputType) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh));
|
||||
});
|
||||
PwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
channel_impl!(new_ch1, new_ch1_with_config, Ch1, Channel1Pin);
|
||||
channel_impl!(new_ch2, new_ch2_with_config, Ch2, Channel2Pin);
|
||||
channel_impl!(new_ch3, new_ch3_with_config, Ch3, Channel3Pin);
|
||||
channel_impl!(new_ch4, new_ch4_with_config, Ch4, Channel4Pin);
|
||||
/// Create a new PWM pin instance with config.
|
||||
pub fn new_with_config(pin: Peri<'d, impl TimerPin<T, C>>, pin_config: PwmPinConfig) -> Self {
|
||||
critical_section::with(|_| {
|
||||
pin.set_low();
|
||||
pin.set_as_af(
|
||||
pin.af_num(),
|
||||
#[cfg(gpio_v1)]
|
||||
AfType::output(pin_config.output_type, pin_config.speed),
|
||||
#[cfg(gpio_v2)]
|
||||
AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull),
|
||||
);
|
||||
});
|
||||
PwmPin {
|
||||
_pin: pin.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single channel of a pwm, obtained from [`SimplePwm::split`],
|
||||
/// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc.
|
||||
@ -466,106 +448,97 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_waveform_chx {
|
||||
($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
|
||||
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
/// Generate a sequence of PWM waveform
|
||||
pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch<T>>, duty: &[u16]) {
|
||||
use crate::pac::timer::vals::Ccds;
|
||||
impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
|
||||
/// Generate a sequence of PWM waveform
|
||||
pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
|
||||
use crate::pac::timer::vals::Ccds;
|
||||
|
||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||
let req = dma.request();
|
||||
#[allow(clippy::let_unit_value)] // eg. stm32f334
|
||||
let req = dma.request();
|
||||
|
||||
let cc_channel = Channel::$cc_ch;
|
||||
let cc_channel = C::CHANNEL;
|
||||
|
||||
let original_duty_state = self.channel(cc_channel).current_duty_cycle();
|
||||
let original_enable_state = self.channel(cc_channel).is_enabled();
|
||||
let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
|
||||
let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
||||
let original_duty_state = self.channel(cc_channel).current_duty_cycle();
|
||||
let original_enable_state = self.channel(cc_channel).is_enabled();
|
||||
let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE;
|
||||
let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel);
|
||||
|
||||
// redirect CC DMA request onto Update Event
|
||||
if !original_cc_dma_on_update {
|
||||
self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
|
||||
}
|
||||
|
||||
if !original_cc_dma_enabled {
|
||||
self.inner.set_cc_dma_enable_state(cc_channel, true);
|
||||
}
|
||||
|
||||
if !original_enable_state {
|
||||
self.channel(cc_channel).enable();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
use crate::dma::{Burst, FifoThreshold};
|
||||
use crate::dma::{Transfer, TransferOptions};
|
||||
|
||||
let dma_transfer_option = TransferOptions {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
fifo_threshold: Some(FifoThreshold::Full),
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
mburst: Burst::Incr8,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match self.inner.bits() {
|
||||
TimerBits::Bits16 => {
|
||||
Transfer::new_write(
|
||||
dma,
|
||||
req,
|
||||
duty,
|
||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
|
||||
dma_transfer_option,
|
||||
)
|
||||
.await
|
||||
}
|
||||
#[cfg(not(any(stm32l0)))]
|
||||
TimerBits::Bits32 => {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
panic!("unsupported timer bits");
|
||||
|
||||
#[cfg(any(bdma, gpdma))]
|
||||
Transfer::new_write(
|
||||
dma,
|
||||
req,
|
||||
duty,
|
||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
|
||||
dma_transfer_option,
|
||||
)
|
||||
.await
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// restore output compare state
|
||||
if !original_enable_state {
|
||||
self.channel(cc_channel).disable();
|
||||
}
|
||||
|
||||
self.channel(cc_channel).set_duty_cycle(original_duty_state);
|
||||
|
||||
// Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
|
||||
// this can almost always trigger a DMA FIFO error.
|
||||
//
|
||||
// optional TODO:
|
||||
// clean FEIF after disable UDE
|
||||
if !original_cc_dma_enabled {
|
||||
self.inner.set_cc_dma_enable_state(cc_channel, false);
|
||||
}
|
||||
|
||||
if !original_cc_dma_on_update {
|
||||
self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
|
||||
}
|
||||
}
|
||||
// redirect CC DMA request onto Update Event
|
||||
if !original_cc_dma_on_update {
|
||||
self.inner.set_cc_dma_selection(Ccds::ON_UPDATE)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_waveform_chx!(waveform_ch1, Ch1Dma, Ch1);
|
||||
impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
|
||||
impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
|
||||
impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
|
||||
if !original_cc_dma_enabled {
|
||||
self.inner.set_cc_dma_enable_state(cc_channel, true);
|
||||
}
|
||||
|
||||
if !original_enable_state {
|
||||
self.channel(cc_channel).enable();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
use crate::dma::{Burst, FifoThreshold};
|
||||
use crate::dma::{Transfer, TransferOptions};
|
||||
|
||||
let dma_transfer_option = TransferOptions {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
fifo_threshold: Some(FifoThreshold::Full),
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
mburst: Burst::Incr8,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match self.inner.bits() {
|
||||
TimerBits::Bits16 => {
|
||||
Transfer::new_write(
|
||||
dma,
|
||||
req,
|
||||
duty,
|
||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16,
|
||||
dma_transfer_option,
|
||||
)
|
||||
.await
|
||||
}
|
||||
#[cfg(not(any(stm32l0)))]
|
||||
TimerBits::Bits32 => {
|
||||
#[cfg(not(any(bdma, gpdma)))]
|
||||
panic!("unsupported timer bits");
|
||||
|
||||
#[cfg(any(bdma, gpdma))]
|
||||
Transfer::new_write(
|
||||
dma,
|
||||
req,
|
||||
duty,
|
||||
self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32,
|
||||
dma_transfer_option,
|
||||
)
|
||||
.await
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// restore output compare state
|
||||
if !original_enable_state {
|
||||
self.channel(cc_channel).disable();
|
||||
}
|
||||
|
||||
self.channel(cc_channel).set_duty_cycle(original_duty_state);
|
||||
|
||||
// Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
|
||||
// this can almost always trigger a DMA FIFO error.
|
||||
//
|
||||
// optional TODO:
|
||||
// clean FEIF after disable UDE
|
||||
if !original_cc_dma_enabled {
|
||||
self.inner.set_cc_dma_enable_state(cc_channel, false);
|
||||
}
|
||||
|
||||
if !original_cc_dma_on_update {
|
||||
self.inner.set_cc_dma_selection(Ccds::ON_COMPARE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> {
|
||||
type Error = core::convert::Infallible;
|
||||
|
@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
|
||||
|
||||
unwrap!(spawner.spawn(blinky(p.PC13)));
|
||||
|
||||
let ch3 = CapturePin::new_ch3(p.PA2, Pull::None);
|
||||
let ch3 = CapturePin::new(p.PA2, Pull::None);
|
||||
let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
|
||||
|
||||
loop {
|
||||
|
@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
|
||||
|
||||
unwrap!(spawner.spawn(blinky(p.PB2)));
|
||||
|
||||
let ch3 = CapturePin::new_ch3(p.PB10, Pull::None);
|
||||
let ch3 = CapturePin::new(p.PB10, Pull::None);
|
||||
let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default());
|
||||
|
||||
loop {
|
||||
|
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let ch1_pin = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
|
||||
let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull);
|
||||
let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
|
||||
let mut ch1 = pwm.ch1();
|
||||
ch1.enable();
|
||||
|
@ -16,8 +16,8 @@ async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);
|
||||
let ch1 = PwmPin::new(p.PE9, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
|
||||
let mut pwm = ComplementaryPwm::new(
|
||||
p.TIM1,
|
||||
Some(ch1),
|
||||
|
@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
let mut ws2812_pwm = SimplePwm::new(
|
||||
dp.TIM3,
|
||||
Some(PwmPin::new_ch1(dp.PB4, OutputType::PushPull)),
|
||||
Some(PwmPin::new(dp.PB4, OutputType::PushPull)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
|
@ -37,8 +37,8 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);
|
||||
let ch1 = PwmPin::new(p.PA8, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
|
||||
|
||||
let mut pwm = ComplementaryPwm::new(
|
||||
p.TIM1,
|
||||
|
@ -47,12 +47,12 @@ async fn main(spawner: Spawner) {
|
||||
unwrap!(spawner.spawn(blinky(p.PB1)));
|
||||
|
||||
// Connect PB1 and PA8 with a 1k Ohm resistor
|
||||
let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
|
||||
let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull);
|
||||
let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
|
||||
pwm.ch1().enable();
|
||||
pwm.ch1().set_duty_cycle(50);
|
||||
|
||||
let ch1 = CapturePin::new_ch1(p.PA0, Pull::None);
|
||||
let ch1 = CapturePin::new(p.PA0, Pull::None);
|
||||
let mut ic = InputCapture::new(p.TIM2, Some(ch1), None, None, None, Irqs, khz(1000), Default::default());
|
||||
|
||||
let mut old_capture = 0;
|
||||
|
@ -26,10 +26,10 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);
|
||||
let ch2 = PwmPin::new_ch2(p.PB3, OutputType::PushPull);
|
||||
let ch2n = ComplementaryPwmPin::new_ch2(p.PB0, OutputType::PushPull);
|
||||
let ch1 = PwmPin::new(p.PA8, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new(p.PA7, OutputType::PushPull);
|
||||
let ch2 = PwmPin::new(p.PB3, OutputType::PushPull);
|
||||
let ch2n = ComplementaryPwmPin::new(p.PB0, OutputType::PushPull);
|
||||
|
||||
let mut pwm = ComplementaryPwm::new(
|
||||
p.TIM1,
|
||||
|
@ -42,7 +42,7 @@ async fn main(spawner: Spawner) {
|
||||
|
||||
unwrap!(spawner.spawn(blinky(p.PB1)));
|
||||
// Connect PA8 and PA6 with a 1k Ohm resistor
|
||||
let ch1_pin = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
|
||||
let ch1_pin = PwmPin::new(p.PA8, OutputType::PushPull);
|
||||
let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(1), Default::default());
|
||||
pwm.ch1().set_duty_cycle_fraction(1, 4);
|
||||
pwm.ch1().enable();
|
||||
|
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
info!("Hello World!");
|
||||
|
||||
let ch1_pin = PwmPin::new_ch1(p.PC0, OutputType::PushPull);
|
||||
let ch1_pin = PwmPin::new(p.PC0, OutputType::PushPull);
|
||||
let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), None, None, None, khz(10), Default::default());
|
||||
let mut ch1 = pwm.ch1();
|
||||
ch1.enable();
|
||||
|
@ -6,7 +6,7 @@ use embassy_executor::Spawner;
|
||||
use embassy_stm32::gpio::{AfType, Flex, OutputType, Speed};
|
||||
use embassy_stm32::time::{khz, Hertz};
|
||||
use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer};
|
||||
use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel};
|
||||
use embassy_stm32::timer::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance32bit4Channel, TimerPin};
|
||||
use embassy_stm32::{Config, Peri};
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -67,10 +67,10 @@ pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> {
|
||||
impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> {
|
||||
pub fn new(
|
||||
tim: Peri<'d, T>,
|
||||
ch1: Peri<'d, impl Channel1Pin<T>>,
|
||||
ch2: Peri<'d, impl Channel2Pin<T>>,
|
||||
ch3: Peri<'d, impl Channel3Pin<T>>,
|
||||
ch4: Peri<'d, impl Channel4Pin<T>>,
|
||||
ch1: Peri<'d, impl TimerPin<T, Ch1>>,
|
||||
ch2: Peri<'d, impl TimerPin<T, Ch2>>,
|
||||
ch3: Peri<'d, impl TimerPin<T, Ch3>>,
|
||||
ch4: Peri<'d, impl TimerPin<T, Ch4>>,
|
||||
freq: Hertz,
|
||||
) -> Self {
|
||||
let af1 = ch1.af_num();
|
||||
|
@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
let ch1_pin = PwmPin::new_ch1(p.PA6, OutputType::PushPull);
|
||||
let ch1_pin = PwmPin::new(p.PA6, OutputType::PushPull);
|
||||
let mut pwm = SimplePwm::new(p.TIM3, Some(ch1_pin), None, None, None, khz(10), Default::default());
|
||||
let mut ch1 = pwm.ch1();
|
||||
ch1.enable();
|
||||
|
@ -11,7 +11,7 @@ use embassy_stm32::rcc::*;
|
||||
use embassy_stm32::time::hz;
|
||||
use embassy_stm32::timer::low_level::{Timer as LLTimer, *};
|
||||
use embassy_stm32::timer::simple_pwm::PwmPin;
|
||||
use embassy_stm32::timer::Channel;
|
||||
use embassy_stm32::timer::{Ch3, Channel};
|
||||
use embassy_stm32::{interrupt, pac, Config};
|
||||
use panic_probe as _;
|
||||
|
||||
@ -70,7 +70,7 @@ async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
// setup PWM pin in AF mode
|
||||
let _ch3 = PwmPin::new_ch3(p.PA2, OutputType::PushPull);
|
||||
let _ch3 = PwmPin::<_, Ch3>::new(p.PA2, OutputType::PushPull);
|
||||
|
||||
// initialize timer
|
||||
// we cannot use SimplePWM here because the Time is privately encapsulated
|
||||
|
Loading…
x
Reference in New Issue
Block a user