Skip to content

Commit 52e5f2b

Browse files
Merge pull request #243 from timokroeger/fix-rtc-event
Fix race condition in RTC event handling
2 parents 561511f + 5ea7149 commit 52e5f2b

File tree

6 files changed

+121
-31
lines changed

6 files changed

+121
-31
lines changed

examples/rtc-demo/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "rtc-demo"
3+
version = "0.1.0"
4+
authors = ["Timo Kröger"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
cortex-m = "0.6.2"
11+
cortex-m-rt = "0.6.12"
12+
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
13+
nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" }
14+
15+
[dependencies.embedded-hal]
16+
version = "0.2.3"
17+
features = ["unproven"]

examples/rtc-demo/Embed.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[default.rtt]
2+
enabled = true

examples/rtc-demo/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# RTC demo
2+
3+
This example shows how to use the compare functionality of the real-time counter peripheral.
4+
Runs on the nRF52840_DK but can easily be adapted for other hardware.
5+
6+
## Set up with `cargo-embed`
7+
8+
Install `cargo-embed` if you don't have it already:
9+
10+
```console
11+
$ cargo install cargo-embed
12+
```
13+
14+
Then just `cd` to the example folder and run
15+
16+
```console
17+
$ cargo embed --target thumbv7em-none-eabihf
18+
```

examples/rtc-demo/src/main.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use nrf52840_hal as hal;
5+
6+
use hal::rtc::{Rtc, RtcCompareReg, RtcInterrupt};
7+
use rtt_target::{rprintln, rtt_init_print};
8+
9+
#[panic_handler] // panicking behavior
10+
fn panic(_: &core::panic::PanicInfo) -> ! {
11+
loop {
12+
cortex_m::asm::bkpt();
13+
}
14+
}
15+
16+
#[cortex_m_rt::entry]
17+
fn main() -> ! {
18+
rtt_init_print!();
19+
20+
let p = hal::pac::Peripherals::take().unwrap();
21+
22+
// Enable LfClk which is required by the RTC.
23+
let clocks = hal::clocks::Clocks::new(p.CLOCK);
24+
let clocks = clocks.start_lfclk();
25+
26+
// Run RTC for 1 second
27+
let mut rtc = Rtc::new(p.RTC0);
28+
rtc.set_compare(RtcCompareReg::Compare0, 32_768).unwrap();
29+
rtc.enable_event(RtcInterrupt::Compare0);
30+
31+
rprintln!("Starting RTC");
32+
let rtc = rtc.enable_counter();
33+
34+
rprintln!("Waiting for compare match");
35+
while !rtc.is_event_triggered(RtcInterrupt::Compare0) {}
36+
rtc.reset_event(RtcInterrupt::Compare0);
37+
38+
rprintln!("Compare match, stopping RTC");
39+
let rtc = rtc.disable_counter();
40+
41+
rprintln!("Counter stopped at {} ticks", rtc.get_counter());
42+
43+
// Stop LfClk when RTC is not used anymore.
44+
rtc.release();
45+
clocks.stop_lfclk();
46+
47+
loop {
48+
cortex_m::asm::nop();
49+
}
50+
}

nrf-hal-common/src/rtc.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -142,41 +142,43 @@ where
142142
}
143143
}
144144

145-
/// Obtain the state of a given interrupt/event, and optionally clear the event
146-
/// if it is set.
147-
pub fn get_event_triggered(&mut self, evt: RtcInterrupt, clear_on_read: bool) -> bool {
148-
let mut orig = 0;
149-
let set_val = if clear_on_read { 0 } else { 1 };
150-
match evt {
151-
RtcInterrupt::Tick => self.periph.events_tick.modify(|r, w| {
152-
orig = r.bits();
153-
unsafe { w.bits(set_val) }
154-
}),
155-
RtcInterrupt::Overflow => self.periph.events_ovrflw.modify(|r, w| {
156-
orig = r.bits();
157-
unsafe { w.bits(set_val) }
158-
}),
159-
RtcInterrupt::Compare0 => self.periph.events_compare[0].modify(|r, w| {
160-
orig = r.bits();
161-
unsafe { w.bits(set_val) }
162-
}),
163-
RtcInterrupt::Compare1 => self.periph.events_compare[1].modify(|r, w| {
164-
orig = r.bits();
165-
unsafe { w.bits(set_val) }
166-
}),
167-
RtcInterrupt::Compare2 => self.periph.events_compare[2].modify(|r, w| {
168-
orig = r.bits();
169-
unsafe { w.bits(set_val) }
170-
}),
171-
RtcInterrupt::Compare3 => self.periph.events_compare[3].modify(|r, w| {
172-
orig = r.bits();
173-
unsafe { w.bits(set_val) }
174-
}),
145+
/// Checks if the given event has been triggered.
146+
pub fn is_event_triggered(&self, evt: RtcInterrupt) -> bool {
147+
let orig = match evt {
148+
RtcInterrupt::Tick => self.periph.events_tick.read().bits(),
149+
RtcInterrupt::Overflow => self.periph.events_ovrflw.read().bits(),
150+
RtcInterrupt::Compare0 => self.periph.events_compare[0].read().bits(),
151+
RtcInterrupt::Compare1 => self.periph.events_compare[1].read().bits(),
152+
RtcInterrupt::Compare2 => self.periph.events_compare[2].read().bits(),
153+
RtcInterrupt::Compare3 => self.periph.events_compare[3].read().bits(),
175154
};
176-
177155
orig == 1
178156
}
179157

158+
/// Resets the given event.
159+
pub fn reset_event(&self, evt: RtcInterrupt) {
160+
match evt {
161+
RtcInterrupt::Tick => {
162+
self.periph.events_tick.write(|w| unsafe { w.bits(0) });
163+
}
164+
RtcInterrupt::Overflow => {
165+
self.periph.events_ovrflw.write(|w| unsafe { w.bits(0) });
166+
}
167+
RtcInterrupt::Compare0 => {
168+
self.periph.events_compare[0].write(|w| unsafe { w.bits(0) });
169+
}
170+
RtcInterrupt::Compare1 => {
171+
self.periph.events_compare[1].write(|w| unsafe { w.bits(0) });
172+
}
173+
RtcInterrupt::Compare2 => {
174+
self.periph.events_compare[2].write(|w| unsafe { w.bits(0) });
175+
}
176+
RtcInterrupt::Compare3 => {
177+
self.periph.events_compare[3].write(|w| unsafe { w.bits(0) });
178+
}
179+
};
180+
}
181+
180182
/// Set the compare value of a given register. The compare registers have a width
181183
/// of 24 bits.
182184
pub fn set_compare(&mut self, reg: RtcCompareReg, val: u32) -> Result<(), Error> {

xtask/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub static EXAMPLES: &[(&str, &[&str])] = &[
2828
),
2929
("pwm-demo", &[]),
3030
("qdec-demo", &[]),
31+
("rtc-demo", &[]),
3132
("rtic-demo", &["51", "52810", "52811", "52832", "52840"]),
3233
("spi-demo", &[]),
3334
("spis-demo", &[]),

0 commit comments

Comments
 (0)