Merge pull request #4044 from yodaldevoid/stm32-opm-timer
STM32: One pulse mode timer
This commit is contained in:
commit
5b632e3d03
@ -10,20 +10,12 @@ use super::{
|
|||||||
CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
|
CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin,
|
||||||
GeneralInstance4Channel,
|
GeneralInstance4Channel,
|
||||||
};
|
};
|
||||||
|
pub use super::{Ch1, Ch2, Ch3, Ch4};
|
||||||
use crate::gpio::{AfType, AnyPin, Pull};
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
use crate::interrupt::typelevel::{Binding, Interrupt};
|
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peri;
|
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 {}
|
|
||||||
|
|
||||||
/// Capture pin wrapper.
|
/// Capture pin wrapper.
|
||||||
///
|
///
|
||||||
/// This wraps a pin to make it usable with capture.
|
/// This wraps a pin to make it usable with capture.
|
||||||
|
|||||||
@ -423,6 +423,36 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> {
|
|||||||
TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(),
|
TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the max compare value.
|
||||||
|
///
|
||||||
|
/// An update event is generated to load the new value. The update event is
|
||||||
|
/// generated such that it will not cause an interrupt or DMA request.
|
||||||
|
pub fn set_max_compare_value(&self, ticks: u32) {
|
||||||
|
match T::BITS {
|
||||||
|
TimerBits::Bits16 => {
|
||||||
|
let arr = unwrap!(u16::try_from(ticks));
|
||||||
|
|
||||||
|
let regs = self.regs_1ch();
|
||||||
|
regs.arr().write(|r| r.set_arr(arr));
|
||||||
|
|
||||||
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
|
||||||
|
regs.egr().write(|r| r.set_ug(true));
|
||||||
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
|
||||||
|
}
|
||||||
|
#[cfg(not(stm32l0))]
|
||||||
|
TimerBits::Bits32 => {
|
||||||
|
let arr = ticks;
|
||||||
|
|
||||||
|
let regs = self.regs_gp32_unchecked();
|
||||||
|
regs.arr().write_value(arr);
|
||||||
|
|
||||||
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY));
|
||||||
|
regs.egr().write(|r| r.set_ug(true));
|
||||||
|
regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: GeneralInstance2Channel> Timer<'d, T> {
|
impl<'d, T: GeneralInstance2Channel> Timer<'d, T> {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ use embassy_sync::waitqueue::AtomicWaker;
|
|||||||
pub mod complementary_pwm;
|
pub mod complementary_pwm;
|
||||||
pub mod input_capture;
|
pub mod input_capture;
|
||||||
pub mod low_level;
|
pub mod low_level;
|
||||||
|
pub mod one_pulse;
|
||||||
pub mod pwm_input;
|
pub mod pwm_input;
|
||||||
pub mod qei;
|
pub mod qei;
|
||||||
pub mod simple_pwm;
|
pub mod simple_pwm;
|
||||||
@ -41,6 +42,15 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 {}
|
||||||
|
|
||||||
/// Amount of bits of a timer.
|
/// Amount of bits of a timer.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
|||||||
384
embassy-stm32/src/timer/one_pulse.rs
Normal file
384
embassy-stm32/src/timer/one_pulse.rs
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
//! One pulse mode driver.
|
||||||
|
|
||||||
|
use core::future::Future;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
pub use super::{Ch1, Ch2};
|
||||||
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
|
use crate::interrupt::typelevel::{Binding, Interrupt};
|
||||||
|
use crate::pac::timer::vals::Etp;
|
||||||
|
use crate::time::Hertz;
|
||||||
|
use crate::{into_ref, Peripheral, PeripheralRef};
|
||||||
|
|
||||||
|
/// External input marker type.
|
||||||
|
pub enum Ext {}
|
||||||
|
|
||||||
|
/// External trigger pin trigger polarity.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum ExternalTriggerPolarity {
|
||||||
|
/// Rising edge only.
|
||||||
|
Rising,
|
||||||
|
/// Falling edge only.
|
||||||
|
Falling,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ExternalTriggerPolarity> for Etp {
|
||||||
|
fn from(mode: ExternalTriggerPolarity) -> Self {
|
||||||
|
match mode {
|
||||||
|
ExternalTriggerPolarity::Rising => 0.into(),
|
||||||
|
ExternalTriggerPolarity::Falling => 1.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trigger pin wrapper.
|
||||||
|
///
|
||||||
|
/// This wraps a pin to make it usable as a timer trigger.
|
||||||
|
pub struct TriggerPin<'d, T, C> {
|
||||||
|
_pin: PeripheralRef<'d, AnyPin>,
|
||||||
|
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: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull: Pull) -> Self {
|
||||||
|
into_ref!(pin);
|
||||||
|
pin.set_as_af(pin.af_num(), AfType::input(pull));
|
||||||
|
TriggerPin {
|
||||||
|
_pin: pin.map_into(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_impl!(new_ch1, Ch1, Channel1Pin);
|
||||||
|
channel_impl!(new_ch2, Ch2, Channel2Pin);
|
||||||
|
channel_impl!(new_ext, Ext, ExternalTriggerPin);
|
||||||
|
|
||||||
|
/// One pulse driver.
|
||||||
|
///
|
||||||
|
/// Generates a pulse after a trigger and some configurable delay.
|
||||||
|
pub struct OnePulse<'d, T: GeneralInstance4Channel> {
|
||||||
|
inner: Timer<'d, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
|
||||||
|
/// Create a new one pulse driver.
|
||||||
|
///
|
||||||
|
/// The pulse is triggered by a channel 1 input pin on both rising and
|
||||||
|
/// falling edges. Channel 1 will unusable as an output.
|
||||||
|
pub fn new_ch1_edge_detect(
|
||||||
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
|
_pin: TriggerPin<'d, T, Ch1>,
|
||||||
|
_irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
|
||||||
|
freq: Hertz,
|
||||||
|
pulse_end: u32,
|
||||||
|
counting_mode: CountingMode,
|
||||||
|
) -> Self {
|
||||||
|
let mut this = Self { inner: Timer::new(tim) };
|
||||||
|
|
||||||
|
this.inner.set_trigger_source(TriggerSource::TI1F_ED);
|
||||||
|
this.inner
|
||||||
|
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||||
|
this.inner
|
||||||
|
.set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
|
||||||
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new one pulse driver.
|
||||||
|
///
|
||||||
|
/// The pulse is triggered by a channel 1 input pin. Channel 1 will unusable
|
||||||
|
/// as an output.
|
||||||
|
pub fn new_ch1(
|
||||||
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
|
_pin: TriggerPin<'d, T, Ch1>,
|
||||||
|
_irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
|
||||||
|
freq: Hertz,
|
||||||
|
pulse_end: u32,
|
||||||
|
counting_mode: CountingMode,
|
||||||
|
capture_mode: InputCaptureMode,
|
||||||
|
) -> Self {
|
||||||
|
let mut this = Self { inner: Timer::new(tim) };
|
||||||
|
|
||||||
|
this.inner.set_trigger_source(TriggerSource::TI1FP1);
|
||||||
|
this.inner
|
||||||
|
.set_input_ti_selection(Channel::Ch1, InputTISelection::Normal);
|
||||||
|
this.inner
|
||||||
|
.set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER);
|
||||||
|
this.inner.set_input_capture_mode(Channel::Ch1, capture_mode);
|
||||||
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new one pulse driver.
|
||||||
|
///
|
||||||
|
/// The pulse is triggered by a channel 2 input pin. Channel 2 will unusable
|
||||||
|
/// as an output.
|
||||||
|
pub fn new_ch2(
|
||||||
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
|
_pin: TriggerPin<'d, T, Ch1>,
|
||||||
|
_irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
|
||||||
|
freq: Hertz,
|
||||||
|
pulse_end: u32,
|
||||||
|
counting_mode: CountingMode,
|
||||||
|
capture_mode: InputCaptureMode,
|
||||||
|
) -> Self {
|
||||||
|
let mut this = Self { inner: Timer::new(tim) };
|
||||||
|
|
||||||
|
this.inner.set_trigger_source(TriggerSource::TI2FP2);
|
||||||
|
this.inner
|
||||||
|
.set_input_ti_selection(Channel::Ch2, InputTISelection::Normal);
|
||||||
|
this.inner
|
||||||
|
.set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER);
|
||||||
|
this.inner.set_input_capture_mode(Channel::Ch2, capture_mode);
|
||||||
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new one pulse driver.
|
||||||
|
///
|
||||||
|
/// The pulse is triggered by a external trigger input pin.
|
||||||
|
pub fn new_ext(
|
||||||
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
|
_pin: TriggerPin<'d, T, Ext>,
|
||||||
|
_irq: impl Binding<T::CaptureCompareInterrupt, CaptureCompareInterruptHandler<T>> + 'd,
|
||||||
|
freq: Hertz,
|
||||||
|
pulse_end: u32,
|
||||||
|
counting_mode: CountingMode,
|
||||||
|
polarity: ExternalTriggerPolarity,
|
||||||
|
) -> Self {
|
||||||
|
let mut this = Self { inner: Timer::new(tim) };
|
||||||
|
|
||||||
|
this.inner.regs_gp16().smcr().modify(|r| {
|
||||||
|
r.set_etp(polarity.into());
|
||||||
|
// No pre-scaling
|
||||||
|
r.set_etps(0.into());
|
||||||
|
// No filtering
|
||||||
|
r.set_etf(FilterValue::NO_FILTER);
|
||||||
|
});
|
||||||
|
this.inner.set_trigger_source(TriggerSource::ETRF);
|
||||||
|
this.new_inner(freq, pulse_end, counting_mode);
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) {
|
||||||
|
self.inner.set_counting_mode(counting_mode);
|
||||||
|
self.inner.set_tick_freq(freq);
|
||||||
|
self.inner.set_max_compare_value(pulse_end);
|
||||||
|
self.inner.regs_core().cr1().modify(|r| r.set_opm(true));
|
||||||
|
// Required for advanced timers, see GeneralInstance4Channel for details
|
||||||
|
self.inner.enable_outputs();
|
||||||
|
self.inner.set_slave_mode(SlaveMode::TRIGGER_MODE);
|
||||||
|
|
||||||
|
T::CaptureCompareInterrupt::unpend();
|
||||||
|
unsafe { T::CaptureCompareInterrupt::enable() };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the end of the pulse in ticks from the trigger.
|
||||||
|
pub fn pulse_end(&self) -> u32 {
|
||||||
|
let max = self.inner.get_max_compare_value();
|
||||||
|
assert!(max < u32::MAX);
|
||||||
|
max + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the end of the pulse in ticks from the trigger.
|
||||||
|
pub fn set_pulse_end(&mut self, ticks: u32) {
|
||||||
|
self.inner.set_max_compare_value(ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset the timer on each trigger
|
||||||
|
#[cfg(not(stm32l0))]
|
||||||
|
pub fn set_reset_on_trigger(&mut self, reset: bool) {
|
||||||
|
let slave_mode = if reset {
|
||||||
|
SlaveMode::COMBINED_RESET_TRIGGER
|
||||||
|
} else {
|
||||||
|
SlaveMode::TRIGGER_MODE
|
||||||
|
};
|
||||||
|
self.inner.set_slave_mode(slave_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a single channel
|
||||||
|
///
|
||||||
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
|
pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> {
|
||||||
|
OnePulseChannel {
|
||||||
|
inner: unsafe { self.inner.clone_unchecked() },
|
||||||
|
channel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channel 1
|
||||||
|
///
|
||||||
|
/// This is just a convenience wrapper around [`Self::channel`].
|
||||||
|
///
|
||||||
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
|
pub fn ch1(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
|
self.channel(Channel::Ch1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channel 2
|
||||||
|
///
|
||||||
|
/// This is just a convenience wrapper around [`Self::channel`].
|
||||||
|
///
|
||||||
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
|
pub fn ch2(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
|
self.channel(Channel::Ch2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channel 3
|
||||||
|
///
|
||||||
|
/// This is just a convenience wrapper around [`Self::channel`].
|
||||||
|
///
|
||||||
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
|
pub fn ch3(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
|
self.channel(Channel::Ch3)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Channel 4
|
||||||
|
///
|
||||||
|
/// This is just a convenience wrapper around [`Self::channel`].
|
||||||
|
///
|
||||||
|
/// If you need to use multiple channels, use [`Self::split`].
|
||||||
|
pub fn ch4(&mut self) -> OnePulseChannel<'_, T> {
|
||||||
|
self.channel(Channel::Ch4)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Splits a [`OnePulse`] into four output channels.
|
||||||
|
// TODO: I hate the name "split"
|
||||||
|
pub fn split(self) -> OnePulseChannels<'static, T>
|
||||||
|
where
|
||||||
|
// must be static because the timer will never be dropped/disabled
|
||||||
|
'd: 'static,
|
||||||
|
{
|
||||||
|
// without this, the timer would be disabled at the end of this function
|
||||||
|
let timer = ManuallyDrop::new(self.inner);
|
||||||
|
|
||||||
|
let ch = |channel| OnePulseChannel {
|
||||||
|
inner: unsafe { timer.clone_unchecked() },
|
||||||
|
channel,
|
||||||
|
};
|
||||||
|
|
||||||
|
OnePulseChannels {
|
||||||
|
ch1: ch(Channel::Ch1),
|
||||||
|
ch2: ch(Channel::Ch2),
|
||||||
|
ch3: ch(Channel::Ch3),
|
||||||
|
ch4: ch(Channel::Ch4),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A group of four [`OnePulseChannel`]s, obtained from [`OnePulse::split`].
|
||||||
|
pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> {
|
||||||
|
/// Channel 1
|
||||||
|
pub ch1: OnePulseChannel<'d, T>,
|
||||||
|
/// Channel 2
|
||||||
|
pub ch2: OnePulseChannel<'d, T>,
|
||||||
|
/// Channel 3
|
||||||
|
pub ch3: OnePulseChannel<'d, T>,
|
||||||
|
/// Channel 4
|
||||||
|
pub ch4: OnePulseChannel<'d, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single channel of a one pulse-configured timer, obtained from
|
||||||
|
/// [`OnePulse::split`],[`OnePulse::channel`], [`OnePulse::ch1`], etc.
|
||||||
|
///
|
||||||
|
/// It is not possible to change the pulse end tick because the end tick
|
||||||
|
/// configuration is shared with all four channels.
|
||||||
|
pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> {
|
||||||
|
inner: ManuallyDrop<Timer<'d, T>>,
|
||||||
|
channel: Channel,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> {
|
||||||
|
/// Get the end of the pulse in ticks from the trigger.
|
||||||
|
pub fn pulse_end(&self) -> u32 {
|
||||||
|
let max = self.inner.get_max_compare_value();
|
||||||
|
assert!(max < u32::MAX);
|
||||||
|
max + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the width of the pulse in ticks.
|
||||||
|
pub fn pulse_width(&mut self) -> u32 {
|
||||||
|
self.pulse_end().saturating_sub(self.pulse_delay())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the start of the pulse in ticks from the trigger.
|
||||||
|
pub fn pulse_delay(&mut self) -> u32 {
|
||||||
|
self.inner.get_compare_value(self.channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the start of the pulse in ticks from the trigger.
|
||||||
|
pub fn set_pulse_delay(&mut self, delay: u32) {
|
||||||
|
assert!(delay <= self.pulse_end());
|
||||||
|
self.inner.set_compare_value(self.channel, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the pulse width in ticks.
|
||||||
|
pub fn set_pulse_width(&mut self, width: u32) {
|
||||||
|
assert!(width <= self.pulse_end());
|
||||||
|
self.set_pulse_delay(self.pulse_end() - width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Waits until the trigger and following delay has passed.
|
||||||
|
pub async fn wait_for_pulse_start(&mut self) {
|
||||||
|
self.inner.enable_input_interrupt(self.channel, true);
|
||||||
|
|
||||||
|
OnePulseFuture::<T> {
|
||||||
|
channel: self.channel,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
|
struct OnePulseFuture<T: GeneralInstance4Channel> {
|
||||||
|
channel: Channel,
|
||||||
|
phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GeneralInstance4Channel> Drop for OnePulseFuture<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
|
||||||
|
|
||||||
|
// disable interrupt enable
|
||||||
|
regs.dier().modify(|w| w.set_ccie(self.channel.index(), false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GeneralInstance4Channel> Future for OnePulseFuture<T> {
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
T::state().cc_waker[self.channel.index()].register(cx.waker());
|
||||||
|
|
||||||
|
let regs = unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) };
|
||||||
|
|
||||||
|
let dier = regs.dier().read();
|
||||||
|
if !dier.ccie(self.channel.index()) {
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ use core::marker::PhantomData;
|
|||||||
use stm32_metapac::timer::vals;
|
use stm32_metapac::timer::vals;
|
||||||
|
|
||||||
use super::low_level::Timer;
|
use super::low_level::Timer;
|
||||||
|
pub use super::{Ch1, Ch2};
|
||||||
use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
|
use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel};
|
||||||
use crate::gpio::{AfType, AnyPin, Pull};
|
use crate::gpio::{AfType, AnyPin, Pull};
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
@ -17,11 +18,6 @@ pub enum Direction {
|
|||||||
Downcounting,
|
Downcounting,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel 1 marker type.
|
|
||||||
pub enum Ch1 {}
|
|
||||||
/// Channel 2 marker type.
|
|
||||||
pub enum Ch2 {}
|
|
||||||
|
|
||||||
/// Wrapper for using a pin with QEI.
|
/// Wrapper for using a pin with QEI.
|
||||||
pub struct QeiPin<'d, T, Channel> {
|
pub struct QeiPin<'d, T, Channel> {
|
||||||
_pin: Peri<'d, AnyPin>,
|
_pin: Peri<'d, AnyPin>,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user