Skip to content

Commit 9d0c754

Browse files
bors[bot]huntc
andauthored
Merge #324
324: Enhances the RTC example with an interrupt r=thejpster a=huntc I find it common to use an interrupt with RTC so I've enhanced this example to illustrate how an interrupt can be established and managed. Co-authored-by: huntc <[email protected]>
2 parents f7d5c6a + c220bab commit 9d0c754

File tree

1 file changed

+53
-8
lines changed

1 file changed

+53
-8
lines changed

examples/rtc-demo/src/main.rs

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
use 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;
612
use hal::rtc::{Rtc, RtcCompareReg, RtcInterrupt};
713
use rtt_target::{rprintln, rtt_init_print};
814

@@ -13,35 +19,74 @@ 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]
1745
fn 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+
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+
}
4288

4389
// Stop LfClk when RTC is not used anymore.
44-
rtc.release();
4590
clocks.stop_lfclk();
4691

4792
loop {

0 commit comments

Comments
 (0)