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