Could you provide an example to implement rtic_monotonic::Monotonic trait?
seanybaggins opened this issue · comments
It would be nice if there was an example to implement the Monotonic trait using the hal api calls.
Here is an example using the peripheral access crate.
https://github.com/kalkyl/f411-rtic/blob/c1c74d887e3620bddcaf9217c93767e9f743d7b1/src/mono.rs
Good idea. I personally haven't used Monotomic (have been using RTIC just for the interrupt and shared-state functionality), but agree that would be a good addition. Perhaps instead of an example, actually implementing it for timers, although I'm not sure that's how it works.
In the latest release. I think there's a bug with it; can't get it to work properly. Hopefully an easy fix; LMK if you have any ideas, or if you're able to get it working as-is.
I did manage to implement my own timer. Here is the code. Might circle back and open up a PR for an example. Currently don't have the bandwidth to check the default implementation for the stm32. I might be able to take a look at it during a weekend during the holidays.
use rtic::Monotonic;
use stm32_hal2::clocks::Clocks;
use stm32_hal2::pac::TIM2;
use stm32_hal2::timer::{Alignment, CaptureCompareDma, CountDir, Timer, TimerConfig, UpdateReqSrc};
pub struct MonoTimer<T, const FREQ: u32>(Timer<T>);
impl<const FREQ: u32> MonoTimer<TIM2, FREQ> {
pub fn new(timer: TIM2, clocks: &Clocks) -> Self {
let timer_config = TimerConfig {
one_pulse_mode: false,
update_request_source: UpdateReqSrc::Any,
auto_reload_preload: false,
alignment: Alignment::Edge,
capture_compare_dma: CaptureCompareDma::Update,
direction: CountDir::Up,
};
let mut timer = Timer::new_tim2(timer, FREQ as f32, timer_config, &clocks);
let prescaler = clocks.sysclk() / FREQ - 1;
timer.set_auto_reload(u32::MAX);
timer.set_prescaler(prescaler as u16);
timer.regs.egr.write(|w| w.ug().set_bit());
timer.regs.sr.write(|w| w.uif().clear_bit());
timer.regs.cr1.write(|w| w.cen().set_bit().udis().set_bit());
Self(timer)
}
pub fn counts(&self) -> u32 {
self.0.read_count()
}
}
impl<const FREQ: u32> Monotonic for MonoTimer<TIM2, FREQ> {
type Instant = fugit::TimerInstantU32<FREQ>;
type Duration = fugit::TimerDurationU32<FREQ>;
#[inline(always)]
fn now(&mut self) -> Self::Instant {
let ticks = self.0.read_count();
Self::Instant::from_ticks(ticks)
}
fn set_compare(&mut self, instant: Self::Instant) {
// No idea. Taken from https://github.com/kalkyl/f411-rtic/blob/a696fce7d6d19fda2356c37642c4d53547982cca/src/mono.rs#L87
self.0
.regs
.ccr1()
.write(|w| w.ccr().bits(instant.duration_since_epoch().ticks()))
}
fn clear_compare_flag(&mut self) {
self.0.regs.sr.write(|w| w.cc1if().clear_bit())
}
#[inline(always)]
fn zero() -> Self::Instant {
Self::Instant::from_ticks(0)
}
unsafe fn reset(&mut self) {
self.0.regs.dier.write(|w| w.cc1ie().set_bit())
}
}
Nice! Check the current impl here: https://github.com/David-OConnor/stm32-hal/blob/main/src/timer.rs#L791
Overall, same idea as what you posted, with the following exceptions:
- Uses
core::Duration
, and a customInstant
type (see the newly-addedinstant
module in this lib) - Delegates
now
to a non-trait-requiringtime_elapsed
fn: I think this function will be useful even without usingMonotonic
, for getting the time in seconds, ms, us, or ns since timer start. - Doesn't work when I try to spawn a Monotonic task in RTIC. Any ideas on that?
- Has some untested wrapping logic, to keep a continuous time even after the timer resets and starts again.
Are you calling spawn_after
or spawn
? It could be the timer is hitting the auto_reload value and resetting before it hits the value you asked to wait for.
Looks like spawn
works; tried increasing the timer timeout period, but something is still not working with spawn_after
.
I'm dropping further integration due to the direction RTIC is moving.
Can you elaborate on due to the direction RTIC is moving
?
Async for RTIC 2.
I wonder if it will play nice with embassy. It would be cool if you could use an RTIC 2 executor with embassy hals. Never used embassy's hals but have wanted to give them a try.
From what I gather from some chats, it should play nice with Embassy, although I don't know how the interactions will work. I think the intent is to keep the core RTIC functionality (Resource sharing and interrupts) the same, but to move everything else, which would include monotonic, to async.