Skip to content
Tim edited this page Apr 18, 2024 · 5 revisions

Time by SysTick

Time on the ch32v003 is kept by the SysTick counter (32bit).

tick speed

By default, SysTick will operate at (SYSTEM_CORE_CLOCK / 8) = 6MHz.

To unlock 48MHz, you need to #define SYSTICK_USE_HCLK 1 before including ch32v003fun.h, for example this could be added to funconfig.h

formula 6MHz 48MHz
rollover ((2^32)-1)/f 715s 89.5s
time resolution 1/f 167ns 20.8333...ns

rollover

To handle rollover correctly, it is recommended to keep all the times in your program in Ticks since the lack of division allows for correct rollover of subtraction and addition.

tick calculations

To calculate how many ticks lie between two events, you can use us * DELAY_US_TIME or ms * DELAY_MS_TIME. Alternatively, the Ticks_from_Us(n) and Ticks_from_Ms(n) may be used, they achieve the same.

If the interval is known at compile time, no multiplication will need to take place on the micro controller at all:

#define INTERVAL_EVENT Ticks_from_Us(817)

USAGE

There are four ways to use SysTick to keep time.

plan a time in the future

uint32_t future_event = 0;

if ( ((int32_t)( SysTick->CNT - future_event )) > 0 ) {
    // do something
    future_event = SysTick->CNT + interval;
}

The trick here is that both SysTick->CNT and future_event are uint32_t, while the calculation is performed as int32_t via typecast, resulting in correct rollover behavior.
Additionally, the compiler knows optimized instructions for comparisons against 0.

compare elapsed against interval

Most will know this method from Arduino.

uint32_t last_time = 0;

if ((SysTick->CNT - last_time) > interval) {
    
}

The trick here is that, when SysTick->CNT rolls over, so does the subtraction and the result is correct again.

plan an interrupt in the future

You may rig SysTick to fire an interrupt at a specified tick.

SysTick->CMP = SysTick->CNT + interval

This requires that you provide an ISR that does something.

millis increment interrupt

You may also increment a variable every us or ms from the SysTick ISR.

uint32_t millis = 0;

And in the SysTick ISR:

SysTick->CMP += DELAY_MS_TIME;
millis++;