Docs backport from #190

This commit is contained in:
Emil Fresk 2019-10-23 22:18:15 +02:00
parent 8d28b536c9
commit 6c6461a927
2 changed files with 50 additions and 0 deletions

View file

@ -95,3 +95,32 @@ Running the program on real hardware produces the following output in the consol
``` text ``` text
{{#include ../../../../ci/expected/baseline.run}} {{#include ../../../../ci/expected/baseline.run}}
``` ```
## Caveats
The `Instant` and `Duration` APIs are meant to be exclusively used with the
`schedule` API to schedule tasks *with a precision of a single core clock
cycle*. These APIs are *not*, for example, meant to be used to time external
events like a user pressing a button.
The timer queue feature internally uses the system timer, `SysTick`. This timer
is a 24-bit counter and it's clocked at the core clock frequency so tasks
scheduled more than `(1 << 24).cycles()` in the future will incur in additional
overhead, proportional to the size of their `Duration`, compared to task
scheduled with `Duration`s below that threshold.
If you need periodic tasks with periods greater than `(1 << 24).cycles()` you
likely don't need a timer with a resolution of one core clock cycle so we advise
you instead use a device timer with an appropriate prescaler.
We can't stop you from using `Instant` to measure external events so please be
aware that `Instant.sub` / `Instant.elapsed` will never return a `Duration`
equal or greater than `(1 << 31).cycles()` so you won't be able to measure
events that last more than `1 << 31` core clock cycles (e.g. seconds).
Adding a `Duration` equal or greater than `(1 << 31).cycles()` to an `Instant`
will effectively overflow it so it's not possible to schedule a task more than
`(1 << 31).cycles()` in the future. There are some debug assertions in place to
catch this kind of user error but it's not possible to prevent it with 100%
success rate because one can always write `(instant + duration) + duration` and
bypass the runtime checks.

View file

@ -124,6 +124,16 @@ pub struct Peripherals<'a> {
/// A measurement of a monotonically nondecreasing clock. Opaque and useful only with `Duration` /// A measurement of a monotonically nondecreasing clock. Opaque and useful only with `Duration`
/// ///
/// This data type is only available when the `timer-queue` feature is enabled /// This data type is only available when the `timer-queue` feature is enabled
///
/// **NOTE:** Both `Instant` and `Duration` are only meant to be used with the `schedule` API.
///
/// We can't stop you from using `Instant.sub` to measure things so please be aware that you won't
/// be able to measure events that span longer than `(1 << 31) - 1` core clock cycles.
///
/// Also note that adding a duration equal or greater than `(1 << 31).cycles()` to an `Instant` will
/// effectively overflow it. There's a debug assertion in place to prevent this user error but it's
/// not possible to catch this error with 100% success rate because one can write `(instant +
/// duration) + duration` to bypass runtime checks.<Paste>
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
pub struct Instant(i32); pub struct Instant(i32);
@ -217,6 +227,17 @@ impl PartialOrd for Instant {
/// A `Duration` type to represent a span of time. /// A `Duration` type to represent a span of time.
/// ///
/// This data type is only available when the `timer-queue` feature is enabled /// This data type is only available when the `timer-queue` feature is enabled
///
/// **NOTE:** Both `Instant` and `Duration` are only meant to be used with the `schedule` API.
///
/// `Duration` has a resolution of 1 core clock cycle and an effective (half-open) range of `0..(1
/// << 31)` (end not included) *core clock cycles*.
///
/// Be aware that scheduling a (periodic) task more than `(1 << 24).cycles()` in the future will
/// incur in additional overhead proportional to the value of the `Duration`. If you need periodic
/// tasks with periods greater than `1 << 24` (e.g. with periods in seconds) you likely don't a
/// resolution of one core clock cycle so we suggest you use a hardware timer with an appropriate
/// prescaler.
#[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)]
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
pub struct Duration(u32); pub struct Duration(u32);