
Click the image to view the details of the conference.
The OS can support multitasking, performing context switching periodically and handling tasks in parallel architecture. A crash in a single task does not affect the entire system. Context switching requires a timer to interrupt program execution; the SysTick timer can provide the necessary clock pulses, offering a rhythmic “heartbeat” for OS task scheduling.
The SysTick timer, also known as the system tick timer or “heartbeat timer,” is a 24-bit countdown timer that automatically reloads the initial value from the reload register when it counts down to zero. It will run indefinitely as long as the enable bit in the SysTick control and status register is not cleared, even working in sleep mode.
The SysTick timer is bundled in the NVIC to generate SysTick exceptions (exception number: 15), and the priority of the SysTick interrupt can also be set.
It works based on beats, dividing the entire time period into many small time slices, where each task can only run for the length of one time slice at a time. If it times out, it exits to let other tasks run, ensuring that no single task monopolizes the various timing functions provided by the operating system, all of which relate to this tick timer.
When enabled, the timer counts down from the reload value to zero and reloads the value from SYST_RVR in the next clock cycle, then continues to count down in subsequent clock cycles. Writing a zero value to SYST_RVR will disable the counter at the next callback. When the counter reaches zero, the COUNTFLAG status bit is set to 1. Reading SYST_CSR will clear the COUNTFLAG bit to 0. Writing to SYST_CVR will clear the register and COUNTFLAG status bit to 0; writing does not trigger the SysTick exception logic, and reading this register will return its value upon access.
01
SysTick Registers
The SysTick timer mainly consists of 4 registers:

typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
__I uint32_t CALIB;/*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;
In Arm’s official documentation, the four registers are named SYST_CSR, SYST_RVR, SYST_CVR, and SYST_CALIB, but in CMSIS, the naming has been simplified for clarity.
1.1
SysTick Control and Status Register (SYST_CSR)

The CSR register uses 4 bits: bit0 is for enabling the timer, setting it to 1 enables the SysTick timer; bit1 controls whether to generate interrupts, setting it to 1 allows interrupts; and bit2 sets the timer’s clock source, setting it to 1 means the timer’s clock source is the main clock, while setting it to 0 means the timer’s clock source is one-fourth of the main clock.
The HCLK source for the SysTick of the MM32F0130 series comes from the AHB bus after hardware division by 4, while FCLK directly comes from the AHB clock bus.

When the SysTick timer counts down from 1 to 0, it sets the COUNTFLAG bit; the following methods can clear it:
Read the SysTick Control and Status Register (STCSR).
Write any data to the SysTick Current Value Register (STCVR).
1.2
SysTick Reload Register (SYST_RVR)

The RVR register uses bits 0 to 23, and this value is the initial countdown value of the timer. After enabling the timer, it counts down from the value set here to 0, and once it counts down to 0, it will start counting down again from this value.
1.3
SysTick Current Value Register (SYST_CVR)

The CVR register also uses bits 0 to 23. This is a status register that changes continuously when the timer starts operating, counting down to 0 after obtaining the initial value from the RVR register.
CURRENT: Reading this register returns the current value of the system timer. Writing a value to this register will reset the timer to 0 and clear the COUNTFLAG bit in CTRL.
1.4
SysTick Calibration Register (SYST_CALIB)

If the calibration information is unknown, the required calibration value can be calculated based on the processor clock or external clock frequency.
The calibration value register provides a solution: it allows the system to generate a constant SysTick interrupt frequency even when running on different CM0 products. The simplest approach is to directly write the value of TENMS to the reload register, ensuring that SysTick exceptions occur every 10ms, as long as the system limits are not exceeded. If other SysTick exception periods are required, they can be calculated proportionally based on the TENMS value.
Among the four registers of the system timer, SYST_CALIB is the calibration register, which is configured before leaving the factory, so we do not need to consider this register.
02
SysTick Programming
Configuring SysTick needs to follow a specific process:
1. Start
2. Disable SysTick
3. Set the reload value register
4. Clear the current value register
5. Enable SysTick
6. Complete
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks);
void SysTick_CLKSourceConfig(u32 systick_clk_source);
void RCC_SystickDisable(void);
void RCC_SystickEnable(u32 sys_tick_period);
; Enable SysTick timer and SysTick exception
LDR R0, =0xE000E010 ; Load the address of STCSR
MOV R1, #0
STR R1, [R0] ; First stop SysTick to prevent accidental exception requests
LDR R1, =0x3FF ; Let SysTick count down every 1024 cycles. Since it counts from 1023 to 0,
; a total of 1024 cycles, so the loaded value is 0x3FF
STR R1, [R0,#4] ; Write the reload value
STR R1, [R0,#8] ; Write any number to STCVR to ensure COUNTFLAG is cleared
MOV R1, #0x7 ; Select FCLK as the clock source and enable SysTick and its exception request
STR R1, [R0] ; Write the value to enable the timer
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
/* Reload value impossible */
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) {
return (1UL);
}
/* set reload register */
SysTick->LOAD = (uint32_t)(ticks - 1UL);
/* set Priority for Systick Interrupt */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
/* Load the SysTick Counter Value */
SysTick->VAL = 0UL;
/* Enable SysTick IRQ and SysTick Timer */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Function successful */
return (0UL);
}
SysTick can be operated in either polling or interrupt mode. The polling program can read the SysTick control and status register to check the COUNTFLAG. If this bit is set, it indicates that the SysTick count has reached 0.
static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void SysTick_Handler(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
int main(void)
{
// SysTick clock is HCLK, interrupt time interval is 1ms
if (SysTick_Config(SystemCoreClock / 1000))
{
while (1);
}
while(1)
{
Delay(200);//200ms
}
}
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div4); // Select external clock HCLK/4
// For system clock's 1/4, actually calculating the number of SysTick VAL decreases per 1us
fac_us=SystemCoreClock/4000000;
// Represents the number of SysTick clock cycles required for each ms, i.e., the number of SysTick VAL decreases per millisecond
fac_ms=(u16)fac_us*1000;
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; // Time loading (SysTick->LOAD is 24bit)
SysTick->VAL =0x00; // Clear the counter
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; // Start counting down
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); // Wait for the time to reach, check the 16th bit of CTRL (COUNTFLAG) is 1, check the 0th bit of STRL (ENABLE) is 1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; // Turn off the counter
SysTick->VAL =0X00; // Clear the counter
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; // Time loading
SysTick->VAL=0x00; // Clear the counter
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; // Start counting down
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); // Wait for the time to reach
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; // Turn off the counter
SysTick->VAL =0X00; // Clear the counter
}
The SysTick timer can also serve other purposes, such as time measurement, timing, or alarms.
Previous Highlights
About Lingdong
Lingdong was established in 2011 and is a leading local supplier of general-purpose 32-bit MCU products and solutions in China. The MM32 MCU products developed based on the Arm Cortex-M series cores have four major series: F/L/SPIN/W, with over 200 models, cumulatively delivering over 300 million units, ranking among the top in local general-purpose 32-bit MCU companies. MM32 MCUs are widely used in smart industry, automotive electronics, communication infrastructure, healthcare, smart appliances, IoT, personal devices, mobile phones, and computers, with tens of millions of excellent products equipped with Lingdong MM32 MCUs delivered to customers every year.

To date, Lingdong is the only local MCU company that has simultaneously obtained official support from development tools such as Arm-KEIL, IAR, and SEGGER, and is one of the few general-purpose MCU companies that has established an independent and complete ecosystem, committed to providing customers with comprehensive support from chip hardware to software algorithms, from reference solutions to system design, truly providing fundamental technical drive and support for China’s electronic information industry.

Lingdong Microelectronics
WeChat ID: MindMotion-MMCU


Long press to recognize the QR code to follow us

MORE
For more information, please visit: www.mm32mcu.com
WeChat official account search: Lingdong MM32MCU
QQ Technical Discussion Group: 294016370
Taobao Store: Shanghai Lingdong Microelectronics Co., Ltd.
Lingdong MM32MCU Technical Forum: bbs.21ic.com