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;

    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 sam, stm32.



modm_platform_clock modm: platform: clock

modm_architecture_atomic modm: architecture: atomic


modm_architecture_clock modm: architecture: clock


modm_cmsis_device modm: cmsis: device


modm_math_algorithm modm: math: algorithm


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