1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! Periodic timer

use core::u16;

use cast::{u16, u32};
use stm32f30x::{Rcc, Tim7};

use frequency;

/// Specialized `Result` type
pub type Result<T> = ::core::result::Result<T, Error>;

/// An error
pub struct Error {
    _0: (),
}

/// Periodic timer
///
/// # Interrupts
///
/// - `Tim7` - update event
#[derive(Clone, Copy)]
pub struct Timer<'a>(pub &'a Tim7);

impl<'a> Timer<'a> {
    /// Initializes the timer with a periodic timeout of `frequency` Hz
    ///
    /// NOTE After initialization, the timer will be in the paused state.
    pub fn init(&self, rcc: &Rcc, frequency: u32) {
        let tim7 = self.0;

        // Power up peripherals
        rcc.apb1enr.modify(|_, w| w.tim7en().enabled());

        let ratio = frequency::APB1 / frequency;
        let psc = u16((ratio - 1) / u32(u16::MAX)).unwrap();
        tim7.psc.write(|w| w.psc().bits(psc));
        let arr = u16(ratio / u32(psc + 1)).unwrap();
        tim7.arr.write(|w| w.arr().bits(arr));

        tim7.dier.write(|w| unsafe { w.uie().bits(1) });
        tim7.cr1.write(|w| w.opm().continuous());
    }

    /// Clears the update event flag
    ///
    /// Returns `Err` if no update event has occurred
    pub fn clear_update_flag(&self) -> Result<()> {
        let tim7 = self.0;

        if tim7.sr.read().uif().is_no_update() {
            Err(Error { _0: () })
        } else {
            self.0.sr.modify(|_, w| w.uif().clear());
            Ok(())
        }
    }

    /// Resumes the timer count
    pub fn resume(&self) {
        self.0.cr1.modify(|_, w| w.cen().enabled());
    }

    /// Pauses the timer
    pub fn pause(&self) {
        self.0.cr1.modify(|_, w| w.cen().disabled());
    }
}