3
3
4
4
use nrf52840_hal as hal;
5
5
6
+ use core:: {
7
+ cell:: RefCell ,
8
+ sync:: atomic:: { AtomicBool , Ordering } ,
9
+ } ;
10
+ use cortex_m:: interrupt:: Mutex ;
11
+ use hal:: pac:: interrupt;
6
12
use hal:: rtc:: { Rtc , RtcCompareReg , RtcInterrupt } ;
7
13
use rtt_target:: { rprintln, rtt_init_print} ;
8
14
@@ -13,35 +19,74 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
13
19
}
14
20
}
15
21
22
+ // We need to share the RTC between the main execution thread and an interrupt, hence the mutex.
23
+ // They'll never be any contention though as interrupts cannot fire while there's a critical
24
+ // section. Also note that the Mutex here is from cortex_m and is designed to work
25
+ // only with single core processors.
26
+ static RTC : Mutex < RefCell < Option < Rtc < hal:: pac:: RTC0 > > > > = Mutex :: new ( RefCell :: new ( None ) ) ;
27
+
28
+ // Keep a flag to indicate that our timer has expired.
29
+ static TIMER_EXPIRED : AtomicBool = AtomicBool :: new ( false ) ;
30
+
31
+ #[ interrupt]
32
+ fn RTC0 ( ) {
33
+ cortex_m:: interrupt:: free ( |cs| {
34
+ let rtc = RTC . borrow ( cs) . borrow ( ) ;
35
+ if let Some ( rtc) = rtc. as_ref ( ) {
36
+ rtc. reset_event ( RtcInterrupt :: Compare0 ) ;
37
+ rtc. clear_counter ( ) ;
38
+ }
39
+ } ) ;
40
+
41
+ TIMER_EXPIRED . store ( true , Ordering :: Relaxed ) ;
42
+ }
43
+
16
44
#[ cortex_m_rt:: entry]
17
45
fn main ( ) -> ! {
18
46
rtt_init_print ! ( ) ;
19
47
48
+ let mut cp = hal:: pac:: CorePeripherals :: take ( ) . unwrap ( ) ;
20
49
let p = hal:: pac:: Peripherals :: take ( ) . unwrap ( ) ;
21
50
22
- // Enable LfClk which is required by the RTC.
51
+ // Enable the low-power/low-frequency clock which is required by the RTC.
23
52
let clocks = hal:: clocks:: Clocks :: new ( p. CLOCK ) ;
24
53
let clocks = clocks. start_lfclk ( ) ;
25
54
26
- // Run RTC for 1 second
55
+ // Run RTC for 1 second (1hz == LFCLK_FREQ)
27
56
let mut rtc = Rtc :: new ( p. RTC0 , 0 ) . unwrap ( ) ;
28
- rtc. set_compare ( RtcCompareReg :: Compare0 , 32_768 ) . unwrap ( ) ;
57
+ rtc. set_compare ( RtcCompareReg :: Compare0 , hal:: clocks:: LFCLK_FREQ )
58
+ . unwrap ( ) ;
29
59
rtc. enable_event ( RtcInterrupt :: Compare0 ) ;
60
+ rtc. enable_interrupt ( RtcInterrupt :: Compare0 , Some ( & mut cp. NVIC ) ) ;
30
61
31
62
rprintln ! ( "Starting RTC" ) ;
32
63
rtc. enable_counter ( ) ;
33
64
65
+ // Permit the interrupt to gain access to the RTC for the purpsoes of resetting etc
66
+ cortex_m:: interrupt:: free ( |cs| {
67
+ RTC . borrow ( cs) . replace ( Some ( rtc) ) ;
68
+ } ) ;
69
+
34
70
rprintln ! ( "Waiting for compare match" ) ;
35
- while !rtc. is_event_triggered ( RtcInterrupt :: Compare0 ) { }
36
- rtc. reset_event ( RtcInterrupt :: Compare0 ) ;
71
+
72
+ while TIMER_EXPIRED . compare_exchange ( true , false , Ordering :: Relaxed , Ordering :: Relaxed )
73
+ != Ok ( true )
74
+ {
75
+ // Go to sleep until we get an event (typically our RTC interrupt)
76
+ cortex_m:: asm:: wfe ( ) ;
77
+ }
37
78
38
79
rprintln ! ( "Compare match, stopping RTC" ) ;
39
- rtc. disable_counter ( ) ;
40
80
41
- rprintln ! ( "Counter stopped at {} ticks" , rtc. get_counter( ) ) ;
81
+ if let Some ( rtc) = cortex_m:: interrupt:: free ( |cs| RTC . borrow ( cs) . replace ( None ) ) {
82
+ rtc. disable_counter ( ) ;
83
+
84
+ rprintln ! ( "Counter stopped at {} ticks" , rtc. get_counter( ) ) ;
85
+
86
+ rtc. release ( ) ;
87
+ }
42
88
43
89
// Stop LfClk when RTC is not used anymore.
44
- rtc. release ( ) ;
45
90
clocks. stop_lfclk ( ) ;
46
91
47
92
loop {
0 commit comments