Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/drogue-iot/drogue-embedded-timer
https://github.com/drogue-iot/drogue-embedded-timer
embedded iot timer
Last synced: 4 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/drogue-iot/drogue-embedded-timer
- Owner: drogue-iot
- License: apache-2.0
- Created: 2020-09-29T17:39:28.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2021-12-23T00:42:07.000Z (almost 3 years ago)
- Last Synced: 2024-08-10T10:32:58.268Z (3 months ago)
- Topics: embedded, iot, timer
- Language: Rust
- Homepage:
- Size: 20.5 KB
- Stars: 3
- Watchers: 5
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `drogue-embedded-timer`
[![crates.io](https://img.shields.io/crates/v/drogue-embedded-timer.svg)](https://crates.io/crates/drogue-embedded-timer)
[![docs.rs](https://docs.rs/drogue-embedded-timer/badge.svg)](https://docs.rs/drogue-embedded-timer)
[![Matrix](https://img.shields.io/matrix/drogue-iot:matrix.org)](https://matrix.to/#/#drogue-iot:matrix.org)When 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.## Converting HAL `CountDown` to `embedded-time`
Generic 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`.
### Example
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:
1. The name of the struct to create.
2. The exposed units (usually an `embedded-time` duration) expected by the driver.
3. The HAL's units expected by the built-in `CountDown` structure being wrapped.
4. The 1-argument conversion routine to handle the conversion.```rust
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:
```rust
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
## Using straight `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:
* 1 microsecond
* 2 microsecond
* 5 microsecond
* 10 microseconds
* 25 microseconds
* 50 microseconds
* 100 microseconds
* 200 microseconds
* 250 microseconds
* 500 microseconds
* 1 millisecond
* 2 millisecond
* 5 millisecond
* 10 milliseconds
* 25 milliseconds
* 50 milliseconds
* 100 milliseconds
* 200 milliseconds
* 250 milliseconds
* 500 milliseconds
* 1 second
* 30 seconds
* 60 secondsEach clock type has a related _Ticker_ type that must also be used:
```rust
use drogue_embedded_timer::{
MillisecondsClock100,
MillisecondsTicker100,
}
```Define the clock as a static variable:
```rust
static CLOCK: MillisecondsClock100 = MillisecondsClock100::new();
```Configure one of your chip's timers to match the `CLOCK` you selected:
```rust
// STM32L4xx configuration, yours may vary:
let mut tim15 = Timer::tim15(device.TIM15, 100, clocks, &mut rcc.apb2);
```Enable the timer as an interrupt source:
```rust
tim15.listen(Event::TimeOut);
```Obtain a _ticker_ from the `CLOCK` to be used in the ISR. The `ticker(...)` method takes two arguments:
1. Some object you can use to clear the timeout (otherwise unconstrained).
2. A function-like thing that can use the object in (1) above, to clear the timeout.```rust
let ticker = CLOCK.ticker(
tim15,
(|t| { t.clear_interrupt(Event::TimeOut); }) as fn(&mut Timer));
```Using RTIC, you may wish to assign the _ticker_ into the shared resources object:
```rust
struct Resources {
ticker: MillisecondsTicker100<'static, MillisecondsClock100, Timer, fn(&mut Timer)>,
...
}
```However is appropriate, call `tick()` on the ticker each time the ISR fires.
In RTIC, it might look similar to:```rust
#[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.
# Creating timers
Once your clock is running and ticking over, you can create as many timers as you desire, using normal `embedded-time` functionality:
```rust
// 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();
```# Reusable Delays
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.```rust
let delay = &CLOCK.delay();
delay.delay(Milliseconds(50u32));
```Once a `Delay` has expired, it may be re-used.