Systick Timer(SysTimer)

Click Nuclei Timer Unit to learn about Core Timer Unit in Nuclei ISA Spec.

SysTimer API

__STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)
__STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)
__STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)
__STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)
__STATIC_FORCEINLINE void SysTimer_Start(void)
__STATIC_FORCEINLINE void SysTimer_Stop(void)
__STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
__STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
__STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
__STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
__STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
__STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
__STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
__STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
__STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
group NMSIS_Core_SysTimer

Functions that configure the Core System Timer.

Functions

__STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)

Set system timer load value.

This function set the system timer load value in MTIMER register.

Remark

  • Load value is 64bits wide.

  • SysTimer_GetLoadValue

Parameters
  • [in] value: value to set system timer MTIMER register.

__STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)

Get system timer load value.

This function get the system timer current value in MTIMER register.

Return

current value(64bit) of system timer MTIMER register.

Remark

  • Load value is 64bits wide.

  • SysTimer_SetLoadValue

__STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)

Set system timer compare value.

This function set the system Timer compare value in MTIMERCMP register.

Remark

  • Compare value is 64bits wide.

  • If compare value is larger than current value timer interrupt generate.

  • Modify the load value or compare value less to clear the interrupt.

  • SysTimer_GetCompareValue

Parameters
  • [in] value: compare value to set system timer MTIMERCMP register.

__STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)

Get system timer compare value.

This function get the system timer compare value in MTIMERCMP register.

Return

compare value of system timer MTIMERCMP register.

Remark

  • Compare value is 64bits wide.

  • SysTimer_SetCompareValue

__STATIC_FORCEINLINE void SysTimer_Start(void)

Enable system timer counter running.

Enable system timer counter running by clear TIMESTOP bit in MTIMECTL register.

__STATIC_FORCEINLINE void SysTimer_Stop(void)

Stop system timer counter running.

Stop system timer counter running by set TIMESTOP bit in MTIMECTL register.

__STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)

Set system timer control value.

This function set the system timer MTIMECTL register value.

Remark

  • Bit TIMESTOP is used to start and stop timer. Clear TIMESTOP bit to 0 to start timer, otherwise to stop timer.

  • Bit CMPCLREN is used to enable auto MTIMER clear to zero when MTIMER >= MTIMERCMP. Clear CMPCLREN bit to 0 to stop auto clear MTIMER feature, otherwise to enable it.

  • Bit CLKSRC is used to select timer clock source. Clear CLKSRC bit to 0 to use mtime_toggle_a, otherwise use core_clk_aon

  • SysTimer_GetControlValue

Parameters
  • [in] mctl: value to set MTIMECTL register

__STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)

Get system timer control value.

This function get the system timer MTIMECTL register value.

Return

MTIMECTL register value

Remark

  • SysTimer_SetControlValue

__STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)

Trigger or set software interrupt via system timer.

This function set the system timer MSIP bit in MSIP register.

Remark

  • Set system timer MSIP bit and generate a SW interrupt.

  • SysTimer_ClearSWIRQ

  • SysTimer_GetMsipValue

__STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)

Clear system timer software interrupt pending request.

This function clear the system timer MSIP bit in MSIP register.

Remark

  • Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.

  • SysTimer_SetSWIRQ

  • SysTimer_GetMsipValue

__STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)

Get system timer MSIP register value.

This function get the system timer MSIP register value.

Return

Value of Timer MSIP register.

Remark

  • Bit0 is SW interrupt flag. Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.

  • SysTimer_SetSWIRQ

  • SysTimer_ClearSWIRQ

__STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)

Set system timer MSIP register value.

This function set the system timer MSIP register value.

Parameters
  • [in] msip: value to set MSIP register

__STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)

Do software reset request.

This function will do software reset request through MTIMER

  • Software need to write SysTimer_MSFRST_KEY to generate software reset request

  • The software request flag can be cleared by reset operation to clear

    Remark

  • The software reset is sent to SoC, SoC need to generate reset signal and send back to Core

  • This function will not return, it will do while(1) to wait the Core reset happened

__STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)

System Tick Configuration.

Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.

In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt when it matchs the ticks user set, during the timer interrupt user should reload the system tick using SysTick_Reload function or similar function written by user, so it can produce period timer interrupt.

Return

0 Function succeeded.

Return

1 Function failed.

Remark

  • For __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced, but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be auto cleared to 0 when MTIMER >= MTIMERCMP.

  • When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Config is not included.

  • In this case, the file <Device>.h must contain a vendor-specific implementation of this function.

  • If user need this function to start a period timer interrupt, then in timer interrupt handler routine code, user should call SysTick_Reload with ticks to reload the timer.

  • This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0

See

  • SysTimer_SetCompareValue; SysTimer_SetLoadValue

Parameters
  • [in] ticks: Number of ticks between two interrupts.

__STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)

System Tick Reload.

Reload the System Timer Tick when the MTIMECMP reached TIME value

Return

0 Function succeeded.

Return

1 Function failed.

Remark

  • For __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced, but for this SysTick_Config function, we assume this CMPCLREN bit is set to 0, so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload the system tick, if vendor want to use this timer’s auto clear feature, they can define __Vendor_SysTickConfig to 1, and implement SysTick_Config and SysTick_Reload functions.

  • When the variable __Vendor_SysTickConfig is set to 1, then the function SysTick_Reload is not included.

  • In this case, the file <Device>.h must contain a vendor-specific implementation of this function.

  • This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0

  • Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks

See

  • SysTimer_SetCompareValue

  • SysTimer_SetLoadValue

Parameters
  • [in] ticks: Number of ticks between two interrupts.

SysTick Code Example

The code below shows the usage of the function SysTick_Config() and SysTick_Reload() with an GD32VF103 SoC.

gd32vf103_systick_example.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "gd32vf103.h"

volatile uint32_t msTicks = 0;                              /* Variable to store millisecond ticks */

#define CONFIG_TICKS        (SOC_TIMER_FREQ / 1000)
#define SysTick_Handler     eclic_mtip_handler

void SysTick_Handler(void) {                                /* SysTick interrupt Handler. */
  SysTimer_Reload(CONFIG_TICKS);                            /* Call SysTick_Reload to reload timer. */
  msTicks++;                                                /* See startup file startup_gd32vf103.S for SysTick vector */
}

int main (void) {
  uint32_t returnCode;

  returnCode = SysTick_Config(CONFIG_TICKS);                /* Configure SysTick to generate an interrupt every millisecond */

  if (returnCode != 0) {                                    /* Check return code for errors */
    // Error Handling
  }

  while(1);
}

SysTimer Interrupt Code Example

The code below shows the usage of various NMSIS Timer Interrupt functions with an GD32VF103 device.

gd32vf103_timer_example1.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "gd32vf103.h"

void eclic_mtip_handler(void)
{
    uint64_t now =  SysTimer_GetLoadValue();
    SysTimer_SetCompareValue(now + SOC_TIMER_FREQ/100);
}

static uint32_t int_cnt = 0;
void eclic_msip_handler(void)
{
    SysTimer_ClearSWIRQ();
    int_cnt++;
}

void eclic_global_initialize(void)
{
    ECLIC_SetMth(0);
    ECLIC_SetCfgNlbits(3);
}

int eclic_register_interrupt(IRQn_Type IRQn, uint8_t shv, uint32_t trig_mode, uint32 lvl, uint32_t priority, void * handler)
{
    ECLIC_SetShvIRQ(IRQn, shv);
    ECLIC_SetTrigIRQ(IRQn, trig_mode);
    ECLIC_SetLevelIRQ(IRQn, lvl);
    ECLIC_SetPriorityIRQ(IRQn, priority);
    ECLIC_SetVector(IRQn, (rv_csr_t)(handler));
    ECLIC_EnableIRQ(IRQn);
    return 0;
}

void setup_timer(void)
{
    SysTimer_SetLoadValue(0);
    SysTimer_SetCompareValue(SOC_TIMER_FREQ/100);
}

int main (void)
{
    uint32_t returnCode;

    eclic_global_initialize();                                /* initialize ECLIC */

    setup_timer();                                            /* initialize timer */

    returnCode = eclic_register_interrupt(SysTimer_IRQn,1,2,8,0,eclic_mtip_handler);  /* register system timer interrupt */

    returnCode = eclic_register_interrupt(SysTimerSW_IRQn,1,2,8,0,eclic_msip_handler);  /* register system timer SW interrupt */

    __enable_irq();                                           /* enable global interrupt */

    SysTimer_SetSWIRQ();                                      /* trigger timer SW interrupt */

    if (returnCode != 0) {                                    /* Check return code for errors */
      // Error Handling
    }

    while(1);
}