| Crates.io | drogue-embedded-timer |
| lib.rs | drogue-embedded-timer |
| version | 0.2.1 |
| created_at | 2020-09-29 17:38:56.563661+00 |
| updated_at | 2020-10-07 13:52:23.089276+00 |
| description | Macro to shim heterogeneous HAL timers to embedded-time |
| homepage | |
| repository | https://github.com/drogue-iot/drogue-embedded-timer |
| max_upload_size | |
| id | 294199 |
| size | 26,590 |
drogue-embedded-timerWhen writing device drivers against embedded-hal, a wall can be hit when attempting to work with CountDown timers due to the Time associated type.
The embedded-time crate is attempting to homogenous the concept of time, clocks, durations and rates.
At this point the various HALs have not adopted embedded-time, so this crate provides a simple macro to help accomodate drivers needing a consistent view of timers.
CountDown to embedded-timeGeneric drivers should be written in terms of CountDown that uses embedded-time flavors of time.
Application writers attempting to provision a concrete instance of the aforementioned drivers can use this macro to convert their HAL's timer into an embedded-time-centric CountDown.
Use the embedded_countdown!(...) macro to define a new struct that can consume a HAL-specific timer, and wrap it into an embedded-time timer.
The macro takes a few arguments:
embedded-time duration) expected by the driver.CountDown structure being wrapped.embedded_countdown!(MsToHertzCountDown,
embedded_time::duration::Milliseconds,
stm32l4xx_hal::time::Hertz
=> (ms) {
let hz: embedded_time::rate::Hertz = ms.to_rate().unwrap();
stm32l4xx_hal::time::Hertz(hz.0)
} );
Once a structure has been defined, you can then use it:
let mut hal_hz_timer = Timer::tim16(device.TIM16, 1, clocks, &mut rcc.apb2);
let mut embedded_ms_timer = MsToHertzCountDown::from(hal_hz_timer);
Now the embedded_ms_timer is a CountDown<Time=embedded_time::duration::Milliseconds> and is no longer tied to a specific HAL implementation.
embedded-time clocks and timers:This crate provides mechanisms for driving an embedded-time-centric Clock to be able to create embedded-time Timers.
You decide the precision of clock you want to use, first.
The available precisions are:
Each clock type has a related Ticker type that must also be used:
use drogue_embedded_timer::{
MillisecondsClock100,
MillisecondsTicker100,
}
Define the clock as a static variable:
static CLOCK: MillisecondsClock100 = MillisecondsClock100::new();
Configure one of your chip's timers to match the CLOCK you selected:
// STM32L4xx configuration, yours may vary:
let mut tim15 = Timer::tim15(device.TIM15, 100, clocks, &mut rcc.apb2);
Enable the timer as an interrupt source:
tim15.listen(Event::TimeOut);
Obtain a ticker from the CLOCK to be used in the ISR. The ticker(...) method takes two arguments:
let ticker = CLOCK.ticker(
tim15,
(|t| { t.clear_interrupt(Event::TimeOut); }) as fn(&mut Timer<TIM15>));
Using RTIC, you may wish to assign the ticker into the shared resources object:
struct Resources {
ticker: MillisecondsTicker100<'static, MillisecondsClock100, Timer<TIM15>, fn(&mut Timer<TIM15>)>,
...
}
However is appropriate, call tick() on the ticker each time the ISR fires.
In RTIC, it might look similar to:
#[task(binds = TIM15, priority = 15, resources = [ticker])]
fn ticker(mut ctx: ticker::Context) {
ctx.resources.ticker.tick();
}
The ISR should be relative high priority to ensure time marches on.
Once your clock is running and ticking over, you can create as many timers as you desire, using normal embedded-time functionality:
// effectively a blocking Delay type of action:
let my_timer = embedded_time::Timer::new(&CLOCK, Seconds(10u32));
let my_timer = my_timer.start().unwrap();
my_timer.wait().unwrap();
This crate also provides functionality similar to Embedded HAL's DelayMs and DelayUs objects.
A delay may be directly constructed, or created through a clock's delay() factory.
let delay = &CLOCK.delay();
delay.delay(Milliseconds(50u32));
Once a Delay has expired, it may be re-used.