rtic icon indicating copy to clipboard operation
rtic copied to clipboard

[book] add an example how to use an `Instant` from monotonic

Open andresv opened this issue 3 years ago • 2 comments

It took me some time to figure out that it is possible to call monotonics::now() and it returns an Instant. Maybe there should be a paragraph about this and how to use it for various time operations like:

use rtic::app;
mod monotonic;

#[app(device = stm32l0xx_hal::pac, peripherals = true, dispatchers = [I2C1])]
mod app {
    use crate::monotonic::ExtendedMonotonicTimer;
    // notice that rtic::time is just reexported embedded_time
    use rtic::time::duration::*;
    use rtic::time::Instant;
    use stm32l0xx_hal::{adc::*, gpio::*, pac, prelude::*, rcc::Config};

    #[monotonic(binds = TIM21, default = true)]
    type MyMono = ExtendedMonotonicTimer<pac::TIM21>;

    #[shared]
    struct Shared {}

    #[local]
    struct Local {
        ts: Instant<ExtendedMonotonicTimer<pac::TIM21>>,
    }

    #[init]
    fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
        //....
        let mono = MyMono::new(dp.TIM21.timer(1000.Hz(), &mut rcc));
        foo::spawn_after(1.seconds()).unwrap();

        (
            Shared {},
            Local {
                ts: Instant::new(0),
            },
            init::Monotonics(mono),
        )
    }

    #[task(local = [ts])]
    fn foo(ctx: foo::Context) {
        use core::convert::TryInto;
    
        let diff: Option<Milliseconds> = monotonics::now()
            .checked_duration_since(ctx.local.ts)
            .and_then(|dur| dur.try_into().ok());
    
        match diff {
            Some(Milliseconds(t)) if t >= 1000 => {
                defmt::info!("t {}", t);
            }
            _ => {}
        }
    
        defmt::info!("tick");
        foo::spawn_at(monotonics::now() + 100.milliseconds()).unwrap();
    }
}

That is a mouthful. It is nontrivial to figure out such pattern (maybe there is better way).

andresv avatar Oct 07 '21 19:10 andresv

It turned out we can do this:

    #[task(local = [ts])]
    fn foo(ctx: foo::Context) {
        if monotonics::now() - *ctx.local.ts >= Milliseconds(1000).into() {
            defmt::info!("go");
            *ctx.local.ts = monotonics::now();
        }

        //defmt::info!("tick");
        foo::spawn_at(monotonics::now() + 100.milliseconds()).unwrap();
    }

andresv avatar Oct 08 '21 09:10 andresv

When the following PR is merged: https://github.com/FluenTech/embedded-time/pull/122

The following will work:

    #[task(local = [ts])]
    fn foo(ctx: foo::Context) {
        if monotonics::now() - *ctx.local.ts >= 1000.milliseconds() {
            defmt::info!("go");
            *ctx.local.ts = monotonics::now();
        }

        //defmt::info!("tick");
        foo::spawn_at(monotonics::now() + 100.milliseconds()).unwrap();
    }

korken89 avatar Oct 08 '21 12:10 korken89