Skip to content

Commit 02be2f8

Browse files
authored
Use a timer instead of systick for Nordic clock (#929)
1 parent 2a77f42 commit 02be2f8

File tree

4 files changed

+58
-16
lines changed

4 files changed

+58
-16
lines changed

crates/runner-nordic/src/board.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{Board, with_state};
1919

2020
pub mod applet;
2121
pub mod button;
22-
mod clock;
22+
pub mod clock;
2323
#[cfg(feature = "_crypto")]
2424
mod crypto;
2525
mod debug;

crates/runner-nordic/src/board/clock.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,49 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use nrf52840_hal::Timer;
16+
use nrf52840_hal::pac::TIMER1;
17+
use nrf52840_hal::timer::Periodic;
1518
use wasefire_board_api::Error;
1619
use wasefire_board_api::clock::Api;
1720

21+
use crate::with_state;
22+
1823
pub enum Impl {}
1924

2025
impl Api for Impl {
2126
fn uptime_us() -> Result<u64, Error> {
22-
Ok(crate::systick::uptime_us())
27+
with_state(|state| Ok(state.clock.uptime_us()))
2328
}
2429
}
30+
31+
pub struct Clock {
32+
timer: Timer<TIMER1, Periodic>,
33+
base: u64,
34+
}
35+
36+
impl Clock {
37+
pub fn new(timer: TIMER1) -> Self {
38+
let mut timer = Timer::periodic(timer);
39+
timer.enable_interrupt();
40+
timer.start((PERIOD - 1) as u32);
41+
Clock { timer, base: 0 }
42+
}
43+
44+
pub fn tick(&mut self) {
45+
self.timer.reset_event();
46+
self.base += PERIOD;
47+
}
48+
49+
fn uptime_us(&self) -> u64 {
50+
let mut counter = self.timer.read() as u64;
51+
// We assume the timer can't wrap around twice without self.base being updated (this would
52+
// mean not processing interrupts for more than 1 hour).
53+
if self.timer.event_compare_cc0().read().events_compare().bit() {
54+
counter = self.timer.read() as u64 + PERIOD;
55+
}
56+
self.base + counter
57+
}
58+
}
59+
60+
const PERIOD: u64 = u32::MAX as u64 + 1;

crates/runner-nordic/src/board/timer.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use alloc::boxed::Box;
1717
use cortex_m::prelude::_embedded_hal_timer_CountDown;
1818
use embedded_hal_02::timer::Cancel;
1919
use nrf52840_hal::Timer;
20-
use nrf52840_hal::pac::{TIMER1, TIMER2, TIMER3, TIMER4};
20+
use nrf52840_hal::pac::{TIMER2, TIMER3, TIMER4};
2121
use nrf52840_hal::timer::{Instance, OneShot, Periodic};
2222
use wasefire_board_api::timer::{Api, Command};
2323
use wasefire_board_api::{Error, Id, Support};
@@ -28,7 +28,7 @@ use crate::with_state;
2828
pub enum Impl {}
2929

3030
impl Support<usize> for Impl {
31-
const SUPPORT: usize = 4;
31+
const SUPPORT: usize = 3;
3232
}
3333

3434
impl Api for Impl {
@@ -57,13 +57,8 @@ impl Api for Impl {
5757
pub struct Timers([ErasedTimer; <Impl as Support<usize>>::SUPPORT]);
5858

5959
impl Timers {
60-
pub fn new(t1: TIMER1, t2: TIMER2, t3: TIMER3, t4: TIMER4) -> Self {
61-
Timers([
62-
ErasedTimer::new(t1),
63-
ErasedTimer::new(t2),
64-
ErasedTimer::new(t3),
65-
ErasedTimer::new(t4),
66-
])
60+
pub fn new(t2: TIMER2, t3: TIMER3, t4: TIMER4) -> Self {
61+
Timers([ErasedTimer::new(t2), ErasedTimer::new(t3), ErasedTimer::new(t4)])
6762
}
6863

6964
pub fn tick(&mut self, index: usize) {

crates/runner-nordic/src/main.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extern crate alloc;
2323
mod allocator;
2424
mod board;
2525
mod storage;
26+
#[cfg(feature = "debug")]
2627
mod systick;
2728

2829
use core::cell::RefCell;
@@ -69,6 +70,7 @@ use wasefire_one_of::{at_most_one_of, exactly_one_of};
6970
use wasefire_scheduler::Scheduler;
7071

7172
use crate::board::button::{Button, Channels};
73+
use crate::board::clock::Clock;
7274
#[cfg(feature = "gpio")]
7375
use crate::board::gpio::Gpio;
7476
use crate::board::timer::Timers;
@@ -103,6 +105,7 @@ struct State {
103105
ctap: Ctap<'static, Usb>,
104106
#[cfg(feature = "usb-serial")]
105107
serial: Serial<'static, Usb>,
108+
clock: Clock,
106109
timers: Timers,
107110
#[cfg(feature = "ble-adv")]
108111
ble: Ble,
@@ -134,7 +137,9 @@ fn main() -> ! {
134137
static mut USB_BUS: MaybeUninit<UsbBusAllocator<Usb>> = MaybeUninit::uninit();
135138

136139
allocator::init();
140+
#[cfg(feature = "debug")]
137141
let c = nrf52840_hal::pac::CorePeripherals::take().unwrap();
142+
#[cfg(feature = "debug")]
138143
systick::init(c.SYST);
139144
log::debug!("Runner starts.");
140145
let p = nrf52840_hal::pac::Peripherals::take().unwrap();
@@ -183,7 +188,8 @@ fn main() -> ! {
183188
Gpio::new(port0.p0_30.degrade(), 0, 30),
184189
Gpio::new(port0.p0_31.degrade(), 0, 31),
185190
];
186-
let timers = Timers::new(p.TIMER1, p.TIMER2, p.TIMER3, p.TIMER4);
191+
let clock = Clock::new(p.TIMER1);
192+
let timers = Timers::new(p.TIMER2, p.TIMER3, p.TIMER4);
187193
let gpiote = Gpiote::new(p.GPIOTE);
188194
#[cfg_attr(not(feature = "fpc2534"), allow(unused_mut))]
189195
let mut channels = Channels::default();
@@ -255,6 +261,7 @@ fn main() -> ! {
255261
ctap,
256262
#[cfg(feature = "usb-serial")]
257263
serial,
264+
clock,
258265
timers,
259266
#[cfg(feature = "ble-adv")]
260267
ble,
@@ -300,10 +307,10 @@ interrupts! {
300307
RADIO = radio(),
301308
#[cfg(feature = "ble-adv")]
302309
TIMER0 = radio_timer(),
303-
TIMER1 = timer(0),
304-
TIMER2 = timer(1),
305-
TIMER3 = timer(2),
306-
TIMER4 = timer(3),
310+
TIMER1 = clock(),
311+
TIMER2 = timer(0),
312+
TIMER3 = timer(1),
313+
TIMER4 = timer(2),
307314
#[cfg(feature = "uart")]
308315
UARTE0_UART0 = uarte(0),
309316
#[cfg(feature = "uart")]
@@ -345,6 +352,10 @@ fn radio_timer() {
345352
with_state(|state| state.ble.tick_timer())
346353
}
347354

355+
fn clock() {
356+
with_state(|state| state.clock.tick())
357+
}
358+
348359
fn timer(timer: usize) {
349360
let timer = Id::new(timer).unwrap();
350361
with_state(|state| {

0 commit comments

Comments
 (0)