#![allow(non_upper_case_globals)]
use crate::pac::{self, DBG};
use crate::rcc::{BusTimerClock, Clocks, Enable, Reset};
use crate::time::Hertz;
use core::convert::TryFrom;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
#[cfg(feature = "rtic")]
pub mod monotonic;
#[cfg(feature = "rtic")]
pub use monotonic::*;
pub(crate) mod pins;
pub use pins::*;
pub mod delay;
pub use delay::*;
pub mod counter;
pub use counter::*;
mod hal_02;
mod hal_1;
pub struct Timer<TIM> {
clk: Hertz,
tim: TIM,
}
pub enum SysEvent {
Update,
}
bitflags::bitflags! {
pub struct Event: u32 {
const Update = 1 << 0;
const C1 = 1 << 1;
const C2 = 1 << 2;
const C3 = 1 << 3;
const C4 = 1 << 4;
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
Disabled,
WrongAutoReload,
}
pub trait TimerExt: Sized {
fn counter<const FREQ: u32>(self, clocks: &Clocks) -> Counter<Self, FREQ>;
fn counter_ms(self, clocks: &Clocks) -> CounterMs<Self> {
self.counter::<1_000>(clocks)
}
fn counter_us(self, clocks: &Clocks) -> CounterUs<Self> {
self.counter::<1_000_000>(clocks)
}
fn counter_hz(self, clocks: &Clocks) -> CounterHz<Self>;
fn delay<const FREQ: u32>(self, clocks: &Clocks) -> Delay<Self, FREQ>;
fn delay_ms(self, clocks: &Clocks) -> DelayMs<Self> {
self.delay::<1_000>(clocks)
}
fn delay_us(self, clocks: &Clocks) -> DelayUs<Self> {
self.delay::<1_000_000>(clocks)
}
}
impl<TIM: Instance> TimerExt for TIM {
fn counter<const FREQ: u32>(self, clocks: &Clocks) -> Counter<Self, FREQ> {
FTimer::new(self, clocks).counter()
}
fn counter_hz(self, clocks: &Clocks) -> CounterHz<Self> {
Timer::new(self, clocks).counter_hz()
}
fn delay<const FREQ: u32>(self, clocks: &Clocks) -> Delay<Self, FREQ> {
FTimer::new(self, clocks).delay()
}
}
pub trait SysTimerExt: Sized {
fn counter_hz(self, clocks: &Clocks) -> SysCounterHz;
fn counter<const FREQ: u32>(self, clocks: &Clocks) -> SysCounter<FREQ>;
fn counter_us(self, clocks: &Clocks) -> SysCounterUs {
self.counter::<1_000_000>(clocks)
}
fn delay(self, clocks: &Clocks) -> SysDelay;
}
impl SysTimerExt for SYST {
fn counter_hz(self, clocks: &Clocks) -> SysCounterHz {
Timer::syst(self, clocks).counter_hz()
}
fn counter<const FREQ: u32>(self, clocks: &Clocks) -> SysCounter<FREQ> {
Timer::syst(self, clocks).counter()
}
fn delay(self, clocks: &Clocks) -> SysDelay {
Timer::syst_external(self, clocks).delay()
}
}
impl Timer<SYST> {
pub fn syst(mut tim: SYST, clocks: &Clocks) -> Self {
tim.set_clock_source(SystClkSource::Core);
Self {
tim,
clk: clocks.sysclk(),
}
}
pub fn syst_external(mut tim: SYST, clocks: &Clocks) -> Self {
tim.set_clock_source(SystClkSource::External);
Self {
tim,
clk: clocks.hclk(),
}
}
pub fn configure(&mut self, clocks: &Clocks) {
self.tim.set_clock_source(SystClkSource::Core);
self.clk = clocks.sysclk();
}
pub fn configure_external(&mut self, clocks: &Clocks) {
self.tim.set_clock_source(SystClkSource::External);
self.clk = clocks.hclk();
}
pub fn release(self) -> SYST {
self.tim
}
pub fn listen(&mut self, event: SysEvent) {
match event {
SysEvent::Update => self.tim.enable_interrupt(),
}
}
pub fn unlisten(&mut self, event: SysEvent) {
match event {
SysEvent::Update => self.tim.disable_interrupt(),
}
}
pub fn reset(&mut self) {
self.tim.clear_current();
}
}
mod sealed {
use super::{Event, DBG};
pub trait General {
type Width: Into<u32> + From<u16>;
fn max_auto_reload() -> u32;
unsafe fn set_auto_reload_unchecked(&mut self, arr: u32);
fn set_auto_reload(&mut self, arr: u32) -> Result<(), super::Error>;
fn read_auto_reload() -> u32;
fn enable_preload(&mut self, b: bool);
fn enable_counter(&mut self);
fn disable_counter(&mut self);
fn is_counter_enabled(&self) -> bool;
fn reset_counter(&mut self);
fn set_prescaler(&mut self, psc: u16);
fn read_prescaler(&self) -> u16;
fn trigger_update(&mut self);
fn clear_interrupt_flag(&mut self, event: Event);
fn listen_interrupt(&mut self, event: Event, b: bool);
fn get_interrupt_flag(&self) -> Event;
fn read_count(&self) -> Self::Width;
fn cr1_reset(&mut self);
fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool);
}
pub trait MasterTimer: General {
type Mms;
fn master_mode(&mut self, mode: Self::Mms);
}
pub trait OnePulseMode: General {
fn start_one_pulse(&mut self);
}
}
pub(crate) use sealed::{General, MasterTimer, OnePulseMode};
pub trait Instance: crate::Sealed + Enable + Reset + BusTimerClock + General {}
macro_rules! hal {
($($TIM:ty: [
$Timer:ident,
$bits:ty,
$dbg_timX_reg:ident,
$dbg_timX_stop:ident,
$(m: $timbase:ident,)?
$(opm: $opm:ident,)?
],)+) => {
$(
impl Instance for $TIM { }
pub type $Timer = Timer<$TIM>;
impl General for $TIM {
type Width = $bits;
#[inline(always)]
fn max_auto_reload() -> u32 {
<$bits>::MAX as u32
}
#[inline(always)]
unsafe fn set_auto_reload_unchecked(&mut self, arr: u32) {
self.arr.write(|w| w.bits(arr))
}
#[inline(always)]
fn set_auto_reload(&mut self, arr: u32) -> Result<(), Error> {
if arr > 0 && arr <= Self::max_auto_reload() {
Ok(unsafe { self.set_auto_reload_unchecked(arr) })
} else {
Err(Error::WrongAutoReload)
}
}
#[inline(always)]
fn read_auto_reload() -> u32 {
let tim = unsafe { &*<$TIM>::ptr() };
tim.arr.read().bits()
}
#[inline(always)]
fn enable_preload(&mut self, b: bool) {
self.cr1.modify(|_, w| w.arpe().bit(b));
}
#[inline(always)]
fn enable_counter(&mut self) {
self.cr1.modify(|_, w| w.cen().set_bit());
}
#[inline(always)]
fn disable_counter(&mut self) {
self.cr1.modify(|_, w| w.cen().clear_bit());
}
#[inline(always)]
fn is_counter_enabled(&self) -> bool {
self.cr1.read().cen().is_enabled()
}
#[inline(always)]
fn reset_counter(&mut self) {
self.cnt.reset();
}
#[inline(always)]
fn set_prescaler(&mut self, psc: u16) {
self.psc.write(|w| unsafe { w.psc().bits(psc) } );
}
#[inline(always)]
fn read_prescaler(&self) -> u16 {
self.psc.read().psc().bits()
}
#[inline(always)]
fn trigger_update(&mut self) {
self.cr1.modify(|_, w| w.urs().set_bit());
self.egr.write(|w| w.ug().set_bit());
self.cr1.modify(|_, w| w.urs().clear_bit());
}
#[inline(always)]
fn clear_interrupt_flag(&mut self, event: Event) {
self.sr.write(|w| unsafe { w.bits(0xffff & !event.bits()) });
}
#[inline(always)]
fn listen_interrupt(&mut self, event: Event, b: bool) {
self.dier.modify(|r, w| unsafe { w.bits(
if b {
r.bits() | event.bits()
} else {
r.bits() & !event.bits()
}
) });
}
#[inline(always)]
fn get_interrupt_flag(&self) -> Event {
Event::from_bits_truncate(self.sr.read().bits())
}
#[inline(always)]
fn read_count(&self) -> Self::Width {
self.cnt.read().bits() as Self::Width
}
#[inline(always)]
fn cr1_reset(&mut self) {
self.cr1.reset();
}
#[inline(always)]
fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool) {
dbg.$dbg_timX_reg.modify(|_, w| w.$dbg_timX_stop().bit(state));
}
}
$(impl MasterTimer for $TIM {
type Mms = pac::$timbase::cr2::MMS_A;
fn master_mode(&mut self, mode: Self::Mms) {
self.cr2.modify(|_,w| w.mms().variant(mode));
}
})?
$(impl OnePulseMode for $TIM {
fn start_one_pulse(&mut self) {
self.cr1.modify(|_, w| w.$opm().set_bit().cen().set_bit());
}
})?
)+
}
}
impl<TIM: Instance> Timer<TIM> {
pub fn new(tim: TIM, clocks: &Clocks) -> Self {
unsafe {
let rcc = &(*pac::RCC::ptr());
TIM::enable(rcc);
TIM::reset(rcc);
}
Self {
clk: TIM::timer_clock(clocks),
tim,
}
}
pub fn configure(&mut self, clocks: &Clocks) {
self.clk = TIM::timer_clock(clocks);
}
pub fn counter_hz(self) -> CounterHz<TIM> {
CounterHz(self)
}
pub fn release(self) -> TIM {
self.tim
}
pub fn listen(&mut self, event: Event) {
self.tim.listen_interrupt(event, true);
}
pub fn clear_interrupt(&mut self, event: Event) {
self.tim.clear_interrupt_flag(event);
}
pub fn get_interrupt(&mut self) -> Event {
self.tim.get_interrupt_flag()
}
pub fn unlisten(&mut self, event: Event) {
self.tim.listen_interrupt(event, false);
}
pub fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool) {
self.tim.stop_in_debug(dbg, state);
}
}
impl<TIM: Instance + MasterTimer> Timer<TIM> {
pub fn set_master_mode(&mut self, mode: TIM::Mms) {
self.tim.master_mode(mode)
}
}
pub struct FTimer<TIM, const FREQ: u32> {
tim: TIM,
}
pub type FTimerUs<TIM> = FTimer<TIM, 1_000_000>;
pub type FTimerMs<TIM> = FTimer<TIM, 1_000>;
impl<TIM: Instance, const FREQ: u32> FTimer<TIM, FREQ> {
pub fn new(tim: TIM, clocks: &Clocks) -> Self {
unsafe {
let rcc = &(*pac::RCC::ptr());
TIM::enable(rcc);
TIM::reset(rcc);
}
let mut t = Self { tim };
t.configure(clocks);
t
}
pub fn configure(&mut self, clocks: &Clocks) {
let clk = TIM::timer_clock(clocks);
assert!(clk.raw() % FREQ == 0);
let psc = clk.raw() / FREQ;
self.tim.set_prescaler(u16::try_from(psc - 1).unwrap());
}
pub fn counter(self) -> Counter<TIM, FREQ> {
Counter(self)
}
pub fn delay(self) -> Delay<TIM, FREQ> {
Delay(self)
}
pub fn release(self) -> TIM {
self.tim
}
pub fn listen(&mut self, event: Event) {
self.tim.listen_interrupt(event, true);
}
pub fn clear_interrupt(&mut self, event: Event) {
self.tim.clear_interrupt_flag(event);
}
pub fn get_interrupt(&self) -> Event {
self.tim.get_interrupt_flag()
}
pub fn unlisten(&mut self, event: Event) {
self.tim.listen_interrupt(event, false);
}
pub fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool) {
self.tim.stop_in_debug(dbg, state);
}
}
impl<TIM: Instance + MasterTimer, const FREQ: u32> FTimer<TIM, FREQ> {
pub fn set_master_mode(&mut self, mode: TIM::Mms) {
self.tim.master_mode(mode)
}
}
impl<TIM: Instance + OnePulseMode, const FREQ: u32> FTimer<TIM, FREQ> {
pub fn onepulsemode_delay(self) -> OpmDelay<TIM, FREQ> {
OpmDelay(self)
}
}
#[inline(always)]
const fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u32) {
let ticks = clock / freq;
let psc = (ticks - 1) / (1 << 16);
let arr = ticks / (psc + 1) - 1;
(psc as u16, arr)
}
hal!(
pac::TIM1: [Timer1, u16, apb_fz2, dbg_timer1_stop, m: tim1, opm: opm,],
);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
hal!(
pac::TIM3: [Timer3, u16, apb_fz1, dbg_timer3_stop, m: tim3, opm: opm,],
pac::TIM17: [Timer17, u16, apb_fz2, dbg_timer17_stop, opm: opm,],
);
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
hal!(
pac::TIM16: [Timer16, u16, apb_fz2, dbg_timer16_stop, opm: opm,],
);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
hal!(
pac::TIM14: [Timer14, u16, apb_fz2, dbg_timer14_stop,],
);
#[cfg(feature = "py32f002b")]
hal!(
pac::TIM14: [Timer14, u16, apb_fz2, dbg_tim14_stop,],
);