stm32/time_driver: use trait impls from the main timer mod.

This commit is contained in:
Dario Nieuwenhuis 2022-02-24 05:57:52 +01:00
parent e8ca5f9b04
commit 2a246be06e

View File

@ -11,12 +11,12 @@ use embassy::time::TICKS_PER_SECOND;
use stm32_metapac::timer::regs;
use crate::interrupt;
use crate::interrupt::{CriticalSection, Interrupt};
use crate::pac::timer::{vals, TimGp16};
use crate::interrupt::CriticalSection;
use crate::pac::timer::vals;
use crate::peripherals;
use crate::rcc::sealed::RccPeripheral;
use self::sealed::Instance as _;
use crate::timer::sealed::Basic16bitInstance as BasicInstance;
use crate::timer::sealed::GeneralPurpose16bitInstance as Instance;
const ALARM_COUNT: usize = 3;
@ -29,25 +29,35 @@ type T = peripherals::TIM4;
#[cfg(time_driver_tim5)]
type T = peripherals::TIM5;
#[cfg(time_driver_tim2)]
#[interrupt]
fn TIM2() {
crate::pac::interrupts! {
(TIM2, timer, $block:ident, UP, $irq:ident) => {
#[cfg(time_driver_tim2)]
#[interrupt]
fn $irq() {
DRIVER.on_interrupt()
}
#[cfg(time_driver_tim3)]
#[interrupt]
fn TIM3() {
}
};
(TIM3, timer, $block:ident, UP, $irq:ident) => {
#[cfg(time_driver_tim3)]
#[interrupt]
fn $irq() {
DRIVER.on_interrupt()
}
#[cfg(time_driver_tim4)]
#[interrupt]
fn TIM4() {
}
};
(TIM4, timer, $block:ident, UP, $irq:ident) => {
#[cfg(time_driver_tim4)]
#[interrupt]
fn $irq() {
DRIVER.on_interrupt()
}
#[cfg(time_driver_tim5)]
#[interrupt]
fn TIM5() {
}
};
(TIM5, timer, $block:ident, UP, $irq:ident) => {
#[cfg(time_driver_tim5)]
#[interrupt]
fn $irq() {
DRIVER.on_interrupt()
}
};
}
// Clock timekeeping works with something we call "periods", which are time intervals
@ -93,6 +103,7 @@ impl AlarmState {
}
struct RtcDriver {
timer: T,
/// Number of 2^15 periods elapsed since boot.
period: AtomicU32,
alarm_count: AtomicU8,
@ -103,6 +114,7 @@ struct RtcDriver {
const ALARM_STATE_NEW: AlarmState = AlarmState::new();
embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
timer: unsafe { core::mem::transmute(()) }, // steal is not const
period: AtomicU32::new(0),
alarm_count: AtomicU8::new(0),
alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]),
@ -110,10 +122,10 @@ embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
impl RtcDriver {
fn init(&'static self) {
let r = T::regs();
let r = self.timer.regs_gp16();
T::enable();
T::reset();
<T as RccPeripheral>::enable();
<T as RccPeripheral>::reset();
let timer_freq = T::frequency();
@ -142,7 +154,7 @@ impl RtcDriver {
// Enable CC0, disable others
r.dier().write(|w| w.set_ccie(0, true));
let irq: <T as sealed::Instance>::Interrupt = core::mem::transmute(());
let irq: <T as BasicInstance>::Interrupt = core::mem::transmute(());
irq.unpend();
irq.enable();
@ -151,7 +163,7 @@ impl RtcDriver {
}
fn on_interrupt(&self) {
let r = T::regs();
let r = self.timer.regs_gp16();
// NOTE(unsafe) Use critical section to access the methods
// XXX: reduce the size of this critical section ?
@ -182,7 +194,7 @@ impl RtcDriver {
}
fn next_period(&self) {
let r = T::regs();
let r = self.timer.regs_gp16();
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
let t = (period as u64) << 15;
@ -224,7 +236,7 @@ impl RtcDriver {
impl Driver for RtcDriver {
fn now(&self) -> u64 {
let r = T::regs();
let r = self.timer.regs_gp16();
let period = self.period.load(Ordering::Relaxed);
compiler_fence(Ordering::Acquire);
@ -261,7 +273,7 @@ impl Driver for RtcDriver {
fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) {
critical_section::with(|cs| {
let r = T::regs();
let r = self.timer.regs_gp16();
let n = alarm.id() as _;
let alarm = self.get_alarm(cs, alarm);
@ -291,37 +303,3 @@ impl Driver for RtcDriver {
pub(crate) fn init() {
DRIVER.init()
}
// ------------------------------------------------------
pub(crate) mod sealed {
use super::*;
pub trait Instance {
type Interrupt: Interrupt;
fn regs() -> TimGp16;
}
}
pub trait Instance: sealed::Instance + Sized + RccPeripheral + 'static {}
macro_rules! impl_timer {
($inst:ident) => {
impl sealed::Instance for peripherals::$inst {
type Interrupt = crate::interrupt::$inst;
fn regs() -> TimGp16 {
crate::pac::timer::TimGp16(crate::pac::$inst.0)
}
}
impl Instance for peripherals::$inst {}
};
}
crate::pac::peripherals!(
(timer, TIM2) => { impl_timer!(TIM2); };
(timer, TIM3) => { impl_timer!(TIM3); };
(timer, TIM4) => { impl_timer!(TIM4); };
(timer, TIM5) => { impl_timer!(TIM5); };
);