Struct r3::kernel::Timer[][src]

#[repr(transparent)]
pub struct Timer<System>(_, _);
Expand description

Represents a single timer in a system.

This type is ABI-compatible with Id.

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 (such as TIME_HARD_HEADROOM) get broken. While the system is processing overdue calls, the timer interrupt handler will not return. Some port 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::{kernel::{cfg::CfgBuilder, Timer, Kernel}, time::Duration};

const fn configure<System: Kernel>(b: &mut CfgBuilder<System>) -> Timer<System> {
    Timer::build()
        .delay(Duration::from_millis(70))
        .period(Duration::from_millis(40))
        .active(true)
        .start(|_| dbg!())
        .finish(b)
}

One-Shot Timer

use r3::{kernel::{cfg::CfgBuilder, Timer, Kernel}, time::Duration};

const fn configure<System: Kernel>(b: &mut CfgBuilder<System>) -> Timer<System> {
    Timer::build()
        .active(true)
        .start(|_| dbg!())
        .finish(b)
}

Reset the delay to schedule a call.

use r3::{kernel::{Timer, Kernel}, time::Duration};

fn sched<System: Kernel>(timer: Timer<System>) {
    timer.set_delay(Some(Duration::from_millis(40))).unwrap();
}

Implementations

Construct a CfgTimerBuilder to define a timer in a configuration function.

Construct a Timer from Id.

Safety

The kernel can handle invalid IDs without a problem. However, the constructed Timer may point to an object that is not intended to be manipulated except by its creator. This is usually prevented by making Timer an opaque handle, but this safeguard can be circumvented by this method.

Get the raw Id value representing this timer.

Start the timer (transition it into the Active state).

This method has no effect if the timer is already in the Active state.

Stop the timer (transition it into the Dormant state).

This method has no effect if the timer is already in the Dormant state.

Set the duration before the next tick.

If the timer is currently in the Dormant state, this method specifies the duration between the next activation and the first tick following the activation.

None means infinity (the timer will never fire).

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

None means infinity.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Feeds this value into the given Hasher. Read more

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

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.