551: Updated the monotonic impl chapter r=AfoHT a=korken89



Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
This commit is contained in:
bors[bot] 2021-11-10 08:53:07 +00:00 committed by GitHub
commit 1859f44482
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -6,36 +6,42 @@ implement the [`rtic_monotonic::Monotonic`] trait.
Implementing time that supports a vast range is generally **very** difficult, and in RTIC 0.5 it was a Implementing time that supports a vast range is generally **very** difficult, and in RTIC 0.5 it was a
common problem how to implement time handling and not get stuck in weird special cases. Moreover common problem how to implement time handling and not get stuck in weird special cases. Moreover
it was difficult to understand the relation between time and the timers used for scheduling. From it was difficult to understand the relation between time and the timers used for scheduling. For
RTIC 0.6 we have moved to use [`embedded_time`] as the basis for all time-based operation and RTIC 0.6 we have moved to assume the user has a time library, e.g. [`fugit`] or [`embedded_time`],
abstraction of clocks. This is why from RTIC 0.6 it is almost trivial to implement the `Monotonic` as the basis for all time-based operations when implementing `Monotonic`. This is why in RTIC 0.6
trait and use any timer in a system for scheduling. it is almost trivial to implement the `Monotonic` trait and use any timer in a system for scheduling.
The trait documents the requirements for each method, however a small PoC implementation is provided The trait documents the requirements for each method, however a small PoC implementation is provided
below. below.
[`rtic_monotonic::Monotonic`]: https://docs.rs/rtic-monotonic/ [`rtic_monotonic::Monotonic`]: https://docs.rs/rtic-monotonic/
[`fugit`]: https://docs.rs/fugit/
[`embedded_time`]: https://docs.rs/embedded_time/ [`embedded_time`]: https://docs.rs/embedded_time/
```rust ```rust
use rtic_monotonic::{embedded_time::clock::Error, Clock, Fraction, Instant, Monotonic}; pub use fugit::{self, ExtU32};
use rtic_monotonic::Monotonic;
/// Example wrapper struct for a timer /// Example wrapper struct for a timer
pub struct Timer<const FREQ: u32> { pub struct Timer<const TIMER_HZ: u32> {
tim: TIM2, tim: TIM2,
} }
impl<const FREQ: u32> Clock for Timer<FREQ> { impl<const TIMER_HZ: u32> Monotonic for Timer<TIMER_HZ> {
const SCALING_FACTOR: Fraction = Fraction::new(1, FREQ); type Instant = fugit::TimerInstantU32<TIMER_HZ>;
type T = u32; type Duration = fugit::TimerDurationU32<TIMER_HZ>;
#[inline(always)] fn now(&mut self) -> Self::Instant {
fn try_now(&self) -> Result<Instant<Self>, Error> { // Read the timer count
Ok(Instant::new(Self::count())) Self::Instant::from_ticks(Self::count())
} }
fn zero() -> Self::Instant {
// This is used while the app is in `#[init]`, if the system cannot
// support time in `#[init]` this can also be a `panic!(..)`
Self::Instant::from_ticks(0)
} }
impl Monotonic for Timer<TIM2> {
unsafe fn reset(&mut self) { unsafe fn reset(&mut self) {
// Reset timer counter // Reset timer counter
self.tim.cnt.write(|_, w| w.bits(0)); self.tim.cnt.write(|_, w| w.bits(0));
@ -45,11 +51,11 @@ impl Monotonic for Timer<TIM2> {
self.tim.dier.modify(|_, w| w.cc1ie().set_bit()); self.tim.dier.modify(|_, w| w.cc1ie().set_bit());
} }
fn set_compare(&mut self, instant: Instant<Self>) {
// Use Compare channel 1 for Monotonic // Use Compare channel 1 for Monotonic
fn set_compare(&mut self, instant: &Instant<Self>) {
self.tim self.tim
.ccr1 .ccr1
.write(|w| w.ccr().bits(instant.duration_since_epoch().integer())); .write(|w| w.ccr().bits(instant.ticks()));
} }
fn clear_compare_flag(&mut self) { fn clear_compare_flag(&mut self) {