diff --git a/src/lib.rs b/src/lib.rs index 28148346fa72a1d25655f67407d4814ad0745573..aa7242ff359adc862746440e08e5f86fdf2e07d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,6 @@ pub mod rcc; pub mod serial; // pub mod spi; pub mod time; -// pub mod timer; +pub mod timer; pub mod led; diff --git a/src/timer.rs b/src/timer.rs index b1aff91fc39f3b75e677bd4319f3b8017af11d8c..4e644aa2b7957adf28064b11aeac3134407c039c 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,9 +1,11 @@ //! Timers +use cortex_m::peripheral::SYST; +use cortex_m::peripheral::syst::SystClkSource; use cast::{u16, u32}; use hal::timer::{CountDown, Periodic}; use nb; -use stm32f30x::{TIM2, TIM3, TIM4, TIM6, TIM7}; +use stm32f4x::{TIM2, TIM3, TIM4, TIM6, TIM7}; use rcc::{APB1, Clocks}; use time::Hertz; @@ -21,6 +23,64 @@ pub enum Event { TimeOut, } +impl Timer<SYST> { + /// start systic timer + pub fn syst<T>(mut syst: SYST, timeout: T, clocks: Clocks) -> Self + where + T: Into<Hertz>, + { + syst.set_clock_source(SystClkSource::Core); + let mut timer = Timer { + tim: syst, + clocks: clocks, + timeout: Hertz(0), + }; + timer.start(timeout); + timer + } + + /// Starts listening for an `event` + pub fn listen(&mut self, event: Event) { + match event { + Event::TimeOut => self.tim.enable_interrupt(), + } + } + + /// Stops listening for an `event` + 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<(), !> { + if self.tim.has_wrapped() { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } +} + +impl Periodic for Timer<SYST> {} + macro_rules! hal { ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident),)+) => { $(