33
44use nrf52840_hal as hal;
55
6+ use core:: {
7+ cell:: RefCell ,
8+ sync:: atomic:: { AtomicBool , Ordering } ,
9+ } ;
10+ use cortex_m:: interrupt:: Mutex ;
11+ use hal:: pac:: interrupt;
612use hal:: rtc:: { Rtc , RtcCompareReg , RtcInterrupt } ;
713use rtt_target:: { rprintln, rtt_init_print} ;
814
@@ -13,35 +19,77 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
1319 }
1420}
1521
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+
1644#[ cortex_m_rt:: entry]
1745fn main ( ) -> ! {
1846 rtt_init_print ! ( ) ;
1947
48+ let mut cp = hal:: pac:: CorePeripherals :: take ( ) . unwrap ( ) ;
2049 let p = hal:: pac:: Peripherals :: take ( ) . unwrap ( ) ;
2150
22- // Enable LfClk which is required by the RTC.
51+ // Enable the low-power/low-frequency clock which is required by the RTC.
2352 let clocks = hal:: clocks:: Clocks :: new ( p. CLOCK ) ;
2453 let clocks = clocks. start_lfclk ( ) ;
2554
26- // Run RTC for 1 second
55+ // Run RTC for 1 second (1hz == LFCLK_FREQ)
2756 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 ( ) ;
2959 rtc. enable_event ( RtcInterrupt :: Compare0 ) ;
60+ rtc. enable_interrupt ( RtcInterrupt :: Compare0 , Some ( & mut cp. NVIC ) ) ;
3061
3162 rprintln ! ( "Starting RTC" ) ;
3263 rtc. enable_counter ( ) ;
3364
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+
3470 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+ }
3778
3879 rprintln ! ( "Compare match, stopping RTC" ) ;
39- rtc. disable_counter ( ) ;
4080
41- rprintln ! ( "Counter stopped at {} ticks" , rtc. get_counter( ) ) ;
81+ match cortex_m:: interrupt:: free ( |cs| RTC . borrow ( cs) . replace ( None ) ) {
82+ Some ( rtc) => {
83+ rtc. disable_counter ( ) ;
84+
85+ rprintln ! ( "Counter stopped at {} ticks" , rtc. get_counter( ) ) ;
86+
87+ rtc. release ( ) ;
88+ }
89+ None => ( ) ,
90+ }
4291
4392 // Stop LfClk when RTC is not used anymore.
44- rtc. release ( ) ;
4593 clocks. stop_lfclk ( ) ;
4694
4795 loop {
0 commit comments