Skip to content

System Clock via Cortex-M SysTick

lbuild module: modm:platform:clock

The SysTick timer is used to provide a time point at milli- and microsecond resolution to implement the modm::Clock::now() and modm::PreciseClock::now() interfaces defined in the modm:architecture:clock module.

For this, the timer is configured to run at ⅛th HCLK frequency and the 24-bit counter is loaded for an interrupt every 250ms (on ARMv7-M) or every 1ms (ARMv6-M). The interrupt increments the 32-bit counters by 250ms and 250'000us (or 1ms and 1000us) respectively.

Since this comes nowhere near the 1us resolution we want, the SysTick->VAL counter is used to interpolate the time between interrupts with this algorithm:

uint32_t milli_time{0};
uint32_t micro_time{0};
void SysTick_Handler()
{
    milli_time += 250;
    micro_time += 250'000;
}

modm::{Precise}Clock::now()
{
    float cycles_per_ms = (SystemClock::Frequency / 8) / 1e3;
    float cycles_per_us = (SystemClock::Frequency / 8) / 1e6;
    uint32_t val = SysTick->LOAD - SysTick->VAL; // SysTick->VAL counts down
    milliseconds = milli_time + val / cycles_per_ms;
    microseconds = micro_time + val / cycles_per_us;
}

The actual algorithm avoids the floating point division and is instead approximated with a 32x32=64-bit multiplication and a bit shift without loosing accuracy. This computation is very, very fast on ARMv7-M.

However, since ARMv6-M only has a 32x32=32-bit multiplication, the interrupt runs at 1ms, thus eliminating the multiplication for the millisecond clock, and allowing to fit into a 32-bit multiplication for the microsecond clock.

This module is only available for rp, sam, stm32.

Queries

reference_clock

The SysTick can be clocked from two sources controlled by the CLKSOURCE bit: 1=processor clock, or 0=reference clock. Since the reference clock is implementation defined, this query returns the prescaler of the reference clock or 1 if it does not exist.

:returns: Divider of the processor clock.

Dependencies

modm:platform:clock modm_platform_clock modm: platform: clock modm_architecture_atomic modm: architecture: atomic modm_platform_clock->modm_architecture_atomic modm_architecture_clock modm: architecture: clock modm_platform_clock->modm_architecture_clock modm_cmsis_device modm: cmsis: device modm_platform_clock->modm_cmsis_device modm_math_algorithm modm: math: algorithm modm_platform_clock->modm_math_algorithm

Limited availability: Check with 'lbuild discover' if this module is available for your target!