blob: dc4259fef13819d798d59181fa535489a7c762b3 (
plain)
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
70
71
72
73
74
75
76
|
use crate::hal::{clock::GenericClockController, pac::RTC};
use core::sync::atomic::{AtomicUsize, Ordering};
use log;
struct Clock(AtomicUsize);
impl Clock {
const fn new() -> Self {
Self(AtomicUsize::new(0))
}
fn set(&self, millis: usize) {
self.0.store(millis, Ordering::SeqCst)
}
// Slightly less than 1ms, due to using a 32,768Hz clock, we can't
// hit exactly 1ms, so we shoot for a bit under.
fn millis(&self) -> usize {
self.0.load(Ordering::SeqCst)
}
}
static CLOCK: Clock = Clock::new();
// Set to run every ~500µs. This has been loosely calibrated from a
// nrf52 clock running Arduino and a Linux host.
static COUNTER: u32 = 13;
pub fn setup(mut rtc: RTC, clocks: &mut GenericClockController) -> impl FnMut() {
let rtc_clock = &clocks.gclk1();
clocks.rtc(&rtc_clock);
rtc.mode0().ctrl.write(|w| w.swrst().set_bit());
while rtc.mode0().status.read().syncbusy().bit_is_set() {}
rtc.mode0().ctrl.write(|w| {
w.mode().count32();
// Neither the prescaler nor matchlr values seem to work. Not
// sure why.
//w.prescaler().div1024();
w.matchclr().set_bit() // Reset on match for periodic
});
rtc.mode0().comp[0].write(|w| unsafe { w.bits(COUNTER) });
rtc.mode0().intflag.write(|w| w.cmp0().set_bit());
rtc.mode0().intenset.write(|w| w.cmp0().set_bit());
// Enable the RTC and wait for sync.
rtc.mode0().ctrl.write(|w| w.enable().set_bit());
while rtc.mode0().status.read().syncbusy().bit_is_set() {}
move || handler(&mut rtc)
}
pub fn millis() -> usize {
CLOCK.millis()
}
fn handler(rtc: &mut RTC) {
// FIXME: matchclr doesn't seem to work to reset the counter?
rtc.mode0().count.write(|w| unsafe { w.bits(0) });
rtc.mode0().intflag.write(|w| w.cmp0().set_bit());
static mut TICKS: usize = 0;
static mut ADD: bool = false;
unsafe {
if ADD {
TICKS += 1;
CLOCK.set(TICKS);
}
ADD = !ADD;
log::logger().flush();
}
}
|