STM32F1 Embedded C Programming
Blue Pill: SysTick programming
A comprehensive guide to generating time-accurate delays with SysTick timer on Cortex M3 microcontrollers.
Do you know that “delay” means “do something, whatever. I don’t care, just let time pass” and that can be even
for(int i=0;i<10000;i++) (void) 0;
?
SysTick is a 24bit system timer, that counts down from reload value to zero, reloads, and counts from the subsequent clocks. It generates interrupts requests on a regular basis and can be used for timekeeping, time measurement, or as an interrupt source for tasks that need to be executed regularly.
In this article, you are going to learn about the SysTick timer, its configuration, and how to use its interrupt requests to generate accurate time delays.
Configuration
We have to set the registers according to duration and interrupt requirements.
- Programming reload value
The reload value can be set usingRELOAD
register. This value is set to 1 less that the number of clock cycles needed for the interrupt as the timer counts both reload value as well as zero. e.g. If the SysTick interrupt is required every 100 clock pulses, setRELOAD
to 99. - Clear current value
This register can be accessed using theVAL
variable. Bits 24:31 are reserved and 24-bit value can be read from bits 23:0. Writing any value this register sets it to zero along with settingCOUNT_FLAG
to zero. - Select clock source-
The clock source can be set usingCLKSOURCE
bit (2) ofCTRL
register.
0 - AHB/8
1 - Processor Clock (AHB) - Enable Tick interrupt-
To enable Tick interrupt setTICKINT
bit (2) ofCTRL
register. - Start SysTick timer-
ENABLE
bit (0) ofCTRL
the register enables the counter. WhenENABLE
is set to 1, the counter loads theRELOAD
value from theLOAD
register and then counts down. On reaching 0, it sets theCOUNTFLAG
to 1 and optionally asserts theSysTick
depending on the value ofTICKINT
. It then loads theRELOAD
value again and begins counting.
Code
Configure pin C13 as output and add led blinking functionality
led_init()
`: This function enables the clock for PORT C on the APB2 bus, configures pin c13 as general-purpose output with push-pull, and sets the speed to 2MHz.
led_on()
: Turns the LED on by setting bit 13 of the BSRR
register.
led_off()
: Turns the LED off by setting bit 13 of the BRR
register.
Define the handler function for SysTick interrupt and define a delay function
msTicks
: It stores the tick count i.e. number of times the SysTick interrupt has been triggered. We use this as a reference in the delay function.
SysTick_Handler()
: The handler function for SysTick interrupt, updates/increments the global tick count.
delay()
: This is the definition of the function to generate a time-accurate delay. It waits for the tick count to increase by the ms
(milliseconds) specified from the initial tick count when the function was first invoked.
Main program body
In the main function, we are invoking the SysTick_Configure()
API provided by CMSIS. It takes care of all configurations mentioned in the Configuration section. It takes the value to be loaded in the RELOAD
register. For our specific application, the tick interrupt is required after every millisecond so we have passed SystemCoreClock/1000
(8MHz/1000) to it. It means that the interrupt will be triggered after the counter counts from 7999 to 0.
Explanation: For an 8MHz CPU clock the counter counts 800000 cycles in one second so it will count 8000 cycles in 1 millisecond. That’s why SysTick is configured to interrupt after counting 8000 cycles i.e. including 7999 and 0, thereby generating exactly a 1ms time base.
Source code and additional resources
Entire source code and information related to building and running code on the Blue Pill board can be found at SysTick Programming on STM32F1 Blue Pill by Rohit Nimkar.
Refer to the following article on How to get started with STM32 Blue Pill using Makefiles and VSCode.