|
15 | 15 |
|
16 | 16 | //! Interface to SYSTICK timer.
|
17 | 17 |
|
18 |
| -#[path="../../lib/ioreg.rs"] mod ioreg; |
| 18 | +use core::option::{Option,None,Some}; |
19 | 19 |
|
20 |
| -/// A constant that requests to use hardware calibration value. |
21 |
| -/// Note that not all core implementations support this. |
22 |
| -pub static CALIBRATED: u32 = 0xffffffff; |
| 20 | +#[path="../../lib/ioreg.rs"] mod ioreg; |
23 | 21 |
|
24 |
| -/// Initializes systick timer. |
| 22 | +/// Initialize systick timer. |
| 23 | +/// |
| 24 | +/// After this call system timer will be disabled, and needs to be enabled manual. SysTick irq will |
| 25 | +/// be disabled and needs to be enabled manually, too. |
25 | 26 | ///
|
26 | 27 | /// Arguments:
|
27 | 28 | ///
|
28 |
| -/// * calibration: Timer reload value, or `CALIBRATED` to use the device 10ms |
29 |
| -/// calibrated value. |
30 |
| -/// * enable_irq: true, if IRQ should be initially enabled. |
31 |
| -pub fn setup(calibration: u32, enable_irq: bool) { |
32 |
| - reg::SYSTICK.set_CONTROL(0b100); // disabled, no interrupt |
33 |
| - let reload_val: u32 = match calibration { |
34 |
| - CALIBRATED => reg::SYSTICK.CALIBRATION() & 0xffffff, |
35 |
| - val => val, |
36 |
| - }; |
37 |
| - reg::SYSTICK.set_RELOAD(reload_val); |
38 |
| - reg::SYSTICK.set_CURRENT(0); |
39 |
| - if enable_irq { |
40 |
| - reg::SYSTICK.set_CONTROL(0b110); |
| 29 | +/// * reload: Reload value for the timer |
| 30 | +pub fn setup(reload: u32) { |
| 31 | + reg::SYSTICK.csr.set_enable(false).set_tickint(false).set_clksource(reg::CPU); |
| 32 | + |
| 33 | + reg::SYSTICK.rvr.set_reload(reload); |
| 34 | + reg::SYSTICK.cvr.set_current(0); |
| 35 | +} |
| 36 | + |
| 37 | +/// Read ten millisecond calibration value from hardware |
| 38 | +pub fn ten_ms() -> Option<u32> { |
| 39 | + let calib = reg::SYSTICK.calib.tenms(); |
| 40 | + match calib { |
| 41 | + 0 => None, |
| 42 | + val => Some(val) |
41 | 43 | }
|
42 | 44 | }
|
43 | 45 |
|
44 | 46 | /// Enables the timer.
|
45 | 47 | pub fn enable() {
|
46 |
| - reg::SYSTICK.set_CONTROL(reg::SYSTICK.CONTROL() | 1); |
| 48 | + reg::SYSTICK.csr.set_enable(true); |
| 49 | +} |
| 50 | + |
| 51 | +/// Disable the timer. |
| 52 | +pub fn disable() { |
| 53 | + reg::SYSTICK.csr.set_enable(false); |
47 | 54 | }
|
48 | 55 |
|
49 | 56 | /// Enables interrupts generation for timer.
|
50 | 57 | pub fn enable_irq() {
|
51 |
| - reg::SYSTICK.set_CONTROL(reg::SYSTICK.CONTROL() | 0b010); |
| 58 | + reg::SYSTICK.csr.set_tickint(true); |
52 | 59 | }
|
53 | 60 |
|
54 | 61 | /// Disables interrupts generation for timer, which is still ticking.
|
55 | 62 | pub fn disable_irq() {
|
56 |
| - reg::SYSTICK.set_CONTROL(reg::SYSTICK.CONTROL() & !0b010); |
| 63 | + reg::SYSTICK.csr.set_tickint(false); |
57 | 64 | }
|
58 | 65 |
|
59 | 66 | /// Gets the current 24bit systick value.
|
60 | 67 | pub fn get_current() -> u32 {
|
61 |
| - reg::SYSTICK.CURRENT() & 0xFFFFFF |
| 68 | + reg::SYSTICK.cvr.current() |
62 | 69 | }
|
63 | 70 |
|
64 | 71 | /// Checks if the timer has been triggered since last call.
|
65 | 72 | /// The flag is cleared when this is called.
|
66 | 73 | pub fn tick() -> bool {
|
67 |
| - ((reg::SYSTICK.CONTROL() >> 16) & 0x1) == 1 |
| 74 | + reg::SYSTICK.csr.countflag() |
68 | 75 | }
|
69 | 76 |
|
| 77 | +#[allow(dead_code)] |
70 | 78 | mod reg {
|
71 | 79 | use lib::volatile_cell::VolatileCell;
|
| 80 | + use core::ops::Drop; |
| 81 | + |
| 82 | + ioregs!(SYSTICK = { |
| 83 | + /// SysTick Control and Status Register |
| 84 | + 0x0 => reg32 csr |
| 85 | + { |
| 86 | + 16 => countflag : ro, //= Returns 1 if timer counted to 0 |
| 87 | + //= since last time this was read. |
| 88 | + 2 => clksource : rw { |
| 89 | + 0 => External, //= External clock |
| 90 | + 1 => CPU, //= CPU clock |
| 91 | + }, |
| 92 | + 1 => tickint : rw, //= Enable SysTick exception |
| 93 | + 0 => enable : rw |
| 94 | + }, |
| 95 | + |
| 96 | + /// Reload Value Register |
| 97 | + 0x4 => reg32 rvr { |
| 98 | + 23..0 => reload : rw //= Reload value |
| 99 | + } |
| 100 | + |
| 101 | + /// Current Value Register |
| 102 | + 0x8 => reg32 cvr { |
| 103 | + 31..0 => current : rw //= Current timer value |
| 104 | + }, |
72 | 105 |
|
73 |
| - ioreg_old!(SYSTICKReg: u32, CONTROL, RELOAD, CURRENT, CALIBRATION) |
74 |
| - reg_rw!(SYSTICKReg, u32, CONTROL, set_CONTROL, CONTROL) |
75 |
| - reg_rw!(SYSTICKReg, u32, RELOAD, set_RELOAD, RELOAD) |
76 |
| - reg_rw!(SYSTICKReg, u32, CURRENT, set_CURRENT, CURRENT) |
77 |
| - reg_r!( SYSTICKReg, u32, CALIBRATION, CALIBRATION) |
| 106 | + 0xc => reg32 calib { |
| 107 | + 31 => noref : ro, //= If 1, the reference clock is not provided |
| 108 | + 30 => skew : ro, //= If 1, the calibration value is inexact |
| 109 | + 23..0 => tenms : ro, //= An optional Reload value for 10ms (100Hz) timing |
| 110 | + //= If zero calibration value not known |
| 111 | + }, |
| 112 | + }) |
78 | 113 |
|
79 | 114 | extern {
|
80 |
| - #[link_name="armmem_SYSTICK"] pub static SYSTICK: SYSTICKReg; |
| 115 | + #[link_name="armmem_SYSTICK"] pub static SYSTICK: SYSTICK; |
81 | 116 | }
|
82 | 117 | }
|
0 commit comments