use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::rcc::{Clocks, Rcc};
use crate::time::Hertz;
use embedded_hal::timer::{CountDown, Periodic};
use void::Void;
pub struct Timer<TIM> {
clocks: Clocks,
tim: TIM,
}
pub enum Event {
TimeOut,
}
impl Timer<SYST> {
pub fn syst<T>(mut syst: SYST, timeout: T, rcc: &Rcc) -> Self
where
T: Into<Hertz>,
{
syst.set_clock_source(SystClkSource::Core);
let mut timer = Timer {
tim: syst,
clocks: rcc.clocks,
};
timer.start(timeout);
timer
}
pub fn listen(&mut self, event: &Event) {
match event {
Event::TimeOut => self.tim.enable_interrupt(),
}
}
pub fn unlisten(&mut self, event: &Event) {
match event {
Event::TimeOut => self.tim.disable_interrupt(),
}
}
}
impl CountDown for Timer<SYST> {
type Time = Hertz;
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1;
assert!(rvr < (1 << 24));
self.tim.set_reload(rvr);
self.tim.clear_current();
self.tim.enable_counter();
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.has_wrapped() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl Periodic for Timer<SYST> {}
macro_rules! timers {
($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
$(
use crate::pac::$TIM;
impl Timer<$TIM> {
// XXX(why not name this `new`?) bummer: constructors need to have different names
pub fn $tim<T>(tim: $TIM, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
rcc.regs.$apbenr.modify(|_, w| w.$timXen().set_bit());
rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
let mut timer = Timer {
clocks: rcc.clocks,
tim,
};
timer.start(timeout);
timer
}
pub fn listen(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().set_bit());
}
}
}
pub fn unlisten(&mut self, event: Event) {
match event {
Event::TimeOut => {
self.tim.dier.write(|w| w.uie().clear_bit());
}
}
}
pub fn release(self) -> $TIM {
let rcc = unsafe { &(*crate::pac::RCC::ptr()) };
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
rcc.$apbenr.modify(|_, w| w.$timXen().clear_bit());
self.tim
}
pub fn clear_irq(&mut self) {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
}
}
impl CountDown for Timer<$TIM> {
type Time = Hertz;
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim.cnt.reset();
let frequency = timeout.into().0;
let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 {
self.clocks.pclk().0
} else {
self.clocks.pclk().0 * 2
};
let ticks = tclk / frequency;
let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap();
self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) });
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<$TIM> {}
)+
}
}
timers! {
TIM1: (tim1, tim1en, tim1rst, apbenr2, apbrstr2),
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
timers! {
TIM16: (tim16, tim16en, tim16rst, apbenr2, apbrstr2),
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002b"))]
timers! {
TIM14: (tim14, tim14en, tim14rst, apbenr2, apbrstr2),
}
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
timers! {
TIM3: (tim3, tim3en, tim3rst, apbenr1, apbrstr1),
TIM17: (tim17, tim17en, tim17rst, apbenr2, apbrstr2),
}
use crate::gpio::AF2;
use crate::gpio::{gpioa::*, gpiob::*, Alternate};
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
use crate::gpio::{AF1, AF13, AF14};
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002b"))]
use crate::gpio::AF5;
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
use crate::gpio::{gpiof::*, AF0, AF4};
#[cfg(feature = "py32f002b")]
use crate::gpio::{gpioc::*, AF3};
pub trait PinC1<TIM> {}
pub trait PinC1N<TIM> {}
pub trait PinC2<TIM> {}
pub trait PinC2N<TIM> {}
pub trait PinC3<TIM> {}
pub trait PinC3N<TIM> {}
pub trait PinC4<TIM> {}
macro_rules! channel_impl {
( $( $TIM:ident, $PINC:ident, $PINX:ident, $MODE:ident<$AF:ident>; )+ ) => {
$(
impl $PINC<$TIM> for $PINX<$MODE<$AF>> {}
)+
};
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
channel_impl!(
TIM1, PinC3, PA0, Alternate<AF13>;
TIM1, PinC1N, PA0, Alternate<AF14>;
TIM1, PinC4, PA1, Alternate<AF13>;
TIM1, PinC2N, PA1, Alternate<AF14>;
TIM1, PinC1, PA3, Alternate<AF13>;
TIM1, PinC1N, PA7, Alternate<AF2>;
TIM1, PinC2, PA13, Alternate<AF13>;
TIM1, PinC2N, PB0, Alternate<AF2>;
TIM1, PinC3N, PB1, Alternate<AF2>;
TIM1, PinC3, PB6, Alternate<AF1>;
);
#[cfg(any(feature = "py32f030", feature = "py32f002a"))]
channel_impl!(
TIM1, PinC1, PA8, Alternate<AF2>;
TIM1, PinC2, PA9, Alternate<AF2>;
TIM1, PinC3, PA10, Alternate<AF2>;
TIM1, PinC4, PA11, Alternate<AF2>;
TIM1, PinC2, PB3, Alternate<AF1>;
);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
channel_impl!(
TIM3, PinC1, PA2, Alternate<AF13>;
TIM3, PinC3, PA4, Alternate<AF13>;
TIM3, PinC2, PA5, Alternate<AF13>;
TIM3, PinC1, PA6, Alternate<AF1>;
TIM3, PinC2, PA7, Alternate<AF1>;
TIM3, PinC3, PB0, Alternate<AF1>;
TIM3, PinC4, PB1, Alternate<AF1>;
TIM3, PinC2, PB5, Alternate<AF1>;
TIM14, PinC1, PA4, Alternate<AF4>;
TIM14, PinC1, PA7, Alternate<AF4>;
TIM14, PinC1, PB1, Alternate<AF0>;
TIM14, PinC1, PF0, Alternate<AF2>;
TIM14, PinC1, PF1, Alternate<AF13>;
TIM16, PinC1, PA6, Alternate<AF5>;
TIM16, PinC1N, PB6, Alternate<AF2>;
TIM17, PinC1, PA7, Alternate<AF5>;
TIM17, PinC1N, PB7, Alternate<AF2>;
);
#[cfg(feature = "py32f030")]
channel_impl!(
TIM3, PinC1, PB4, Alternate<AF1>;
TIM16, PinC1, PB8, Alternate<AF2>;
TIM17, PinC1, PB8, Alternate<AF13>;
);
#[cfg(feature = "py32f002b")]
channel_impl!(
TIM1, PinC1, PA0, Alternate<AF2>;
TIM1, PinC2, PA1, Alternate<AF2>;
TIM1, PinC4, PA2, Alternate<AF2>;
TIM1, PinC2, PA3, Alternate<AF2>;
TIM1, PinC3, PA4, Alternate<AF2>;
TIM1, PinC1, PA5, Alternate<AF2>;
TIM1, PinC4, PA7, Alternate<AF2>;
TIM1, PinC2, PB0, Alternate<AF2>;
TIM1, PinC3N, PB0, Alternate<AF3>;
TIM1, PinC2N, PB1, Alternate<AF2>;
TIM1, PinC4, PB1, Alternate<AF3>;
TIM1, PinC1N, PB2, Alternate<AF2>;
TIM1, PinC3, PB2, Alternate<AF3>;
TIM1, PinC3, PB5, Alternate<AF2>;
TIM1, PinC1N, PC0, Alternate<AF2>;
TIM14, PinC1, PA4, Alternate<AF5>;
TIM14, PinC1, PA5, Alternate<AF5>;
TIM14, PinC1, PB5, Alternate<AF5>;
TIM14, PinC1, PB7, Alternate<AF5>;
);