Crate systick_timer

Source
Expand description

Provides a SysTick based 64-bit timer implementation.

In addition, optionally wraps this into a basic Embassy time driver.

The timer is a standalone implementation that can be used from any Cortex-M0/M3/M4/M7 code.

Usage:

// Set up timer with 1ms resolution, reload at 100us, 8MHz clock
static INSTANCE : Timer = Timer::new(1_000, 799, 8_000_000);

#[cortex_m_rt::entry]
fn main() -> ! {
    // Configure and start SYST
    INSTANCE.start(&mut cortex_m::Peripherals::take().unwrap().SYST);
    // Get the current time in milliseconds
     let now = timer.now();
}

Call the timer from your Systick handler:

#[exception]
fn SysTick() {
    INSTANCE.systick_handler();
}

To reduce the frequency of overflow interrupts, you can use the maximum reload value:

let timer = Timer::new(1_000, 16_777_215, 48_000_000);

This generates an interrupt and reloads the timer every ~350ms, but the resolution is still 1ms


To use the Embassy driver, the setup needs to look as follows. First, create a static instance of the timer, passing in SysTick frequency and reload value. The constant <4> determines the number of concurrent wait tasks supported.

embassy_time_driver::time_driver_impl!(static DRIVER: SystickDriver<4>
  = SystickDriver::new(8_000_000, 7999));

Next, you must have a SysTick interrupt handler that calls the driver’s systick_interrupt() method on its static instance.

#[exception]
fn SysTick() {
    DRIVER.systick_interrupt();
}

And in main, before using any timer calls, initialize the driver with the actual SysTick peripheral:

#[embassy_executor::main]
async fn main(_s: embassy_executor::Spawner) {
  let mut periph = Peripherals::take().unwrap();
  DRIVER.start(&mut periph.SYST);
  // .. can use Timer::now() etc.
}

Structs§

SystickDriver
Very basic Embassy time driver that uses the SysTick timer.
Timer
A 64-bit timer based on SysTick.