stm32/time_driver: use trait impls from the main timer mod.
This commit is contained in:
parent
e8ca5f9b04
commit
2a246be06e
@ -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,25 +29,35 @@ type T = peripherals::TIM4;
|
|||||||
#[cfg(time_driver_tim5)]
|
#[cfg(time_driver_tim5)]
|
||||||
type T = peripherals::TIM5;
|
type T = peripherals::TIM5;
|
||||||
|
|
||||||
#[cfg(time_driver_tim2)]
|
crate::pac::interrupts! {
|
||||||
#[interrupt]
|
(TIM2, timer, $block:ident, UP, $irq:ident) => {
|
||||||
fn TIM2() {
|
#[cfg(time_driver_tim2)]
|
||||||
|
#[interrupt]
|
||||||
|
fn $irq() {
|
||||||
DRIVER.on_interrupt()
|
DRIVER.on_interrupt()
|
||||||
}
|
}
|
||||||
#[cfg(time_driver_tim3)]
|
};
|
||||||
#[interrupt]
|
(TIM3, timer, $block:ident, UP, $irq:ident) => {
|
||||||
fn TIM3() {
|
#[cfg(time_driver_tim3)]
|
||||||
|
#[interrupt]
|
||||||
|
fn $irq() {
|
||||||
DRIVER.on_interrupt()
|
DRIVER.on_interrupt()
|
||||||
}
|
}
|
||||||
#[cfg(time_driver_tim4)]
|
};
|
||||||
#[interrupt]
|
(TIM4, timer, $block:ident, UP, $irq:ident) => {
|
||||||
fn TIM4() {
|
#[cfg(time_driver_tim4)]
|
||||||
|
#[interrupt]
|
||||||
|
fn $irq() {
|
||||||
DRIVER.on_interrupt()
|
DRIVER.on_interrupt()
|
||||||
}
|
}
|
||||||
#[cfg(time_driver_tim5)]
|
};
|
||||||
#[interrupt]
|
(TIM5, timer, $block:ident, UP, $irq:ident) => {
|
||||||
fn TIM5() {
|
#[cfg(time_driver_tim5)]
|
||||||
|
#[interrupt]
|
||||||
|
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
|
||||||
@ -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); };
|
|
||||||
);
|
|
||||||
|
Loading…
Reference in New Issue
Block a user