nrf-hal
nrf-hal copied to clipboard
RTIC monotonic implementation
There is already a working implementation of RTIC monotonic timer for TIMER{0,1,2} here: https://github.com/kalkyl/nrf-play/blob/47f4410d4e39374c18ff58dc17c25159085fb526/src/mono.rs It would be nice for this to be part of the HAL so that the implementation does not need to be copied every time :) I'm trying to do this, but I'm not sure how.
I realize that this might be stale but, It would be relatively simple to add this. I made a draft implementation making the abstraction agnostic to whether you are using the RTC or the TIMER. Using the RTC yields much better power efficiency.
Using this would look something like this:
use nrf5284_hal as hal;
use hal::monotonic::*;
use hal::rtc::RTC0;
use hal::timer::TIMER0;
#[rtic::app(device = nrf52840_hal::pac,dispatchers=[TIMER2,TIMER3])]
mod app {
use super::*;
#[monotonic(binds = RTC0, default = true)]
type MyMono = MonotonicTimer<RTC0>;
// Or this if using timer
#[monotonic(binds = TIMER0, default = true)]
type MyMono = MonotonicTimer<TIMER0>;
#[shared]
struct Shared {}
#[local]
struct Local {}
#[init]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
let mono = MonotonicTimer::new(cx.device.RTC0);
// Or this if using timer
let mono = MonotonicTimer::new(cx.device.TIMER0);
// Return shared, local and mono
(
Shared {},
Local {},
init::Monotonics(mono),
)
}
}
Making it trivial to change clocks when writing your app
@barafael I think that I have finished an implementation for this
The API looks like this at the time of writing and it will not change much.
#![no_main]
#![no_std]
use core::panic::PanicInfo;
use nrf52840_hal as hal;
use hal::monotonic::MonotonicTimer;
use hal::pac;
#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
loop {}
}
#[rtic::app(device = pac, dispatchers = [TIMER2, TIMER3])]
mod app {
use super::*;
#[monotonic(binds = RTC0, default = true)]
type Mono = MonotonicTimer<pac::RTC0, 32_768u32>;
// Conversely
#[monotonic(binds = TIMER0, default = true)]
type Mono = MonotonicTimer<pac::TIMER0, 1_000_000u32>;
#[shared]
struct Shared {}
#[local]
struct Local {}
#[init]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
let clocks = hal::clocks::Clocks::new(cx.device.CLOCK)
.set_lfclk_src_external(hal::clocks::LfOscConfiguration::NoExternalNoBypass)
.start_lfclk()
.enable_ext_hfosc();
let mono = Mono::new(cx.device.RTC0, &clocks).unwrap();
// Conversely
let mono = Mono::new(cx.device.TIMER0, &clocks).unwrap();
// Return shared, local and mono
(Shared {}, Local {}, init::Monotonics(mono))
}
#[idle()]
fn idle(_cx: idle::Context) -> ! {
loop {}
}
}
I am still to test it as I do not have any hardware at hand but feel free to try it.