Struct r3_core::kernel::timer::Timer

source ·
#[repr(transparent)]
pub struct Timer<System: NotSupportedYet>(_);
Expand description

Represents a single timer in a system.

This type is ABI-compatible with System::RawTimerId.

See TimerRef for the borrowed counterpart. See TimerMethods for the operations provided by this handle type.

Relation to Other Specifications: A similar concept exists in almost every operating system.

Timer States

A timer may be in one of the following states:

  • Dormant — The timer is not running and can be started.

  • Active — The timer is running and can be stopped.

Timer Scheduling

The scheduling of a timer is determined by two state variables:

  • The delay is an optional non-negative duration value (Option<Duration>) that specifies the minimum period of time before the callback function gets called.

    If the delay is None, it’s treated as infinity and the function will never execute.

    While a timer is active, this value decreases at a steady rate. If the system can’t process a timer for an extended period of time, this value might temporarily fall negative.

  • The period is an optional non-negative duration value. On expiration, the system adds this value to the timer’s delay.

Overdue Timers

When scheduling a next tick, the system takes the observed timer handling latency into account and makes the new delay shorter than the period as needed to ensure that the callback function is called in a steady rate. This behavior is illustrated by the above figure. This is accomplished by adding the specified period to the timer’s absolute arrival time instead of recalculating the arrival time based on the current system time. The delay is a difference between the current system time and the arrival time.

Note that the system does not impose any limit on the extent of this behavior. To put this simply, if one second elapses, the system makes one second worth of calls no matter what. If a periodic timer’s callback function couldn’t complete within the timer’s period, the timer latency would steadily increase until it reaches the point where various internal assumptions get broken. While the system is processing overdue calls, the timer interrupt handler might not return. Some kernel timer drivers (most notably the Arm-M tickful SysTick driver) have much lower tolerance for this. To avoid this catastrophic situation, an application should take the precautions shown below:

  • Don’t perform an operation that might take an unbounded time in a timer callback function.

  • Off-load time-consuming operations to a task, which is activated or unparked by a timer callback function.

  • Don’t specify zero as period unless you know what you are doing.

  • Keep your target platform’s performance characteristics in your mind.

Start/Stop

When a timer is stopped, the timer will not fire anymore and the delay remains stationary at the captured value. If the captured value is negative, it’s rounded to zero. This means that if there are more than one outstanding call at the moment of stopping, they will be dropped.

Another way to stop a timer is to set the delay or the period to None (infinity).

Dynamic Period

The period can be changed anytime. The system reads it before calling a timer callback function and adds it to the timer’s current delay value.

It might be tricky to understand the outcome of changing the period when there are overdue calls. It could be explained in this way: If there are one second worth of calls pending, there will still be one second worth of calls pending after changing the period.

Infinite Delay and/or Period

If delay is set to None (infinity), the timer will stop firing. Note that the timer is still in the Active state, and the correct way to restart this timer is to reset the delay to a finite value.

If period is set to None instead, the timer will stop firing after the next tick.

Examples

Periodic Timer

use r3_core::{kernel::{Cfg, StaticTimer, traits}, time::Duration};

const fn configure<C>(b: &mut Cfg<C>) -> StaticTimer<C::System>
where
    C: ~const traits::CfgTimer,
{
    StaticTimer::define()
        .delay(Duration::from_millis(70))
        .period(Duration::from_millis(40))
        .active(true)
        .start(|| dbg!())
        .finish(b)
}

One-Shot Timer

use r3_core::{kernel::{Cfg, StaticTimer, traits, prelude::*}, time::Duration};

const fn configure<C>(b: &mut Cfg<C>) -> StaticTimer<C::System>
where
    C: ~const traits::CfgTimer,
{
    StaticTimer::define()
        .active(true)
        .start(|| dbg!())
        .finish(b)
}

Reset the delay to schedule a call.

use r3_core::{kernel::{TimerRef, traits, prelude::*}, time::Duration};

fn sched<System: traits::KernelTimer>(timer: TimerRef<'_, System>) {
    timer.set_delay(Some(Duration::from_millis(40))).unwrap();
}

Trait Implementations§

source§

impl<System: NotSupportedYet> Debug for Timer<System>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<System: NotSupportedYet> Hash for Timer<System>

source§

fn hash<H>(&self, state: &mut H)where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<System: NotSupportedYet> PartialEq<Timer<System>> for Timer<System>

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<System: NotSupportedYet> PartialEq<Timer<System>> for TimerRef<'_, System>

source§

fn eq(&self, other: &Timer<System>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<System: NotSupportedYet> PartialEq<TimerRef<'_, System>> for Timer<System>

source§

fn eq(&self, other: &TimerRef<'_, System>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<System: NotSupportedYet> TimerHandle for Timer<System>

§

type System = System

The system type this object pertains to.
source§

const unsafe fn from_id(id: <System as KernelTimer>::RawTimerId) -> Self

Construct a Timer from RawTimerId. Read more
source§

const fn id(&self) -> System::RawTimerId

Get the raw RawTimerId value representing this object.
source§

const fn borrow(&self) -> TimerRef<'_, Self::System>

Borrow self as TimerRef.
source§

impl<System: NotSupportedYet> Eq for Timer<System>

Auto Trait Implementations§

§

impl<System> RefUnwindSafe for Timer<System>where <System as KernelTimer>::RawTimerId: RefUnwindSafe,

§

impl<System> Send for Timer<System>

§

impl<System> Sync for Timer<System>

§

impl<System> Unpin for Timer<System>where <System as KernelTimer>::RawTimerId: Unpin,

§

impl<System> UnwindSafe for Timer<System>where <System as KernelTimer>::RawTimerId: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> TimerMethods for Twhere T: TimerHandle,

source§

fn start(&self) -> Result<(), StartTimerError>

Start the timer (transition it into the Active state). Read more
source§

fn stop(&self) -> Result<(), StopTimerError>

Stop the timer (transition it into the Dormant state). Read more
source§

fn set_delay(&self, delay: Option<Duration>) -> Result<(), SetTimerDelayError>

Set the duration before the next tick. Read more
source§

fn set_period( &self, period: Option<Duration> ) -> Result<(), SetTimerPeriodError>

Set the timer period, which is a quantity to be added to the timer’s absolute arrival time on every tick. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.