Systick

systick timer

Systick timer (System Tick timer) is a 24-bit timer that counts from a given value N-1 (reload value) down to zero. It is nothing more than a counter that triggers some event when it reaches a given value.

SysTick is part of the “System Control Block”, SCB (page 221 PM0214 Programming manual) and is integrated into the Cortex-M core.

SysTick is a core peripheral, as are Nested Vectored Interrupt Controller (NVIC) and System Control Block (SCB).

SysTick information can be found, not in the reference manual, but in the programming manual PM0214, from page 246.

architecture

Belonging to the Cortex core, the SysTick timer does not need a clock enable control bit.

Three registers are used to control Systick:

address

name

register

e000 e010

control and status register CSR

CTRL

e000 e014

reload value register RVR

LOAD

e000 e018

current value register CVR

VAL

e000 e01c

calibration value register

CALIB

SysTick control and status register (STK_CTRL)
Address offset: 0x00
Reset value: 0x0000 0000
SysTick CTRL
bit 16 COUNTFLAG: returns 1 if timer counted to 0 since last time it was read.

bit 2 CLKSOURCE: selects the clock source.
* 0: AHB/8
* 1: Processor clock (AHB)

bit 1 TICKINT: SysTick exception request enable
bit 0 ENABLE: Counter enable
SysTick->VAL = 0x00000000U;            // set current value to 0
SysTick->LOAD = 4 000 000U - 1U;       // 4 MHz → 4 000 000 pulses 1 s
SysTick->CTRL |= 0x0007;               // set processor clock as source, enable timer + interrupt

The SysTick timer counts down from a set value to zero. This set value is stored in the reload value register (RVR or LOAD) in Cortex Microcontroller Software Interface Standard (CMSIS).

Then, the current value register (CVR or VAL) must be reset. The timer is started by setting ENABLE in the control and status register (CSR or CTRL).

When the CTRL_COUNTFLAG bit is set, it means that the timer has counted down to 0.

Finally, the CTRL register is set to zero to disable the timer.

SysTick reload value register (STK_LOAD)
Address offset: 0x04
Reset value: 0x0000 0000
systick

bits 23:0 RELOAD value

The RELOAD value can be any value in the range 0x00000001-0x00FFFFFF (24 bits).

SysTick current value register (STK_VAL)

VAL
Bits 23:0 CURRENT (or VAL): Current counter value
The VAL register contains the current value of the SysTick counter.

Reads return the current value of the SysTick counter.

Blinking code

ldr r1, =GPIOB_BASE        //  4800 0400
ldr r6, =GPIO_BSRR_BR_6
ldr r7, =GPIO_BSRR_BS_6

1:
str      r6, [r1,#GPIO_BSRR]

push {r1}
ldr r0, = 500000
bl delay
pop {r1}

str      r7, [r1,#GPIO_BSRR]

push {r1}
ldr r0, = 100000
bl delay
pop {r1}

b 1b

The delay subroutine is so implemented:

.global delay
.type delay, %function

delay:
       ldr r1, =SysTick_BASE
       str r0, [r1, #LOAD]      // SysTick reload value register RVR

       ldr r0, =0
       str r0, [r1, #VAL]              //  SysTick Current Value Register CVR

    // ldr r0, =SysTick_CTRL_CLKSOURCE_Msk|SysTick_CTRL_ENABLE_Msk      // rapid blink
       ldr r0, =SysTick_CTRL_ENABLE_Msk      // slow blink  (AHB clock/8)
       str r0, [r1, #CTRL]             //  SysTick Control and Status Register CSR

a:     ldr r0, [r1, #CTRL]
       tst r0, #SysTick_CTRL_COUNTFLAG_Msk  // wait until the countflag is set
       beq a

       ldr r0, =0
       str r0, [r1, #CTRL]

bx lr

SYSCLK with interrupt

Interrupt belongs is a type of exception. An exception can be seen as a software interruption, created for example by a division by zero operation or a memory access violation. An interrupt is triggered by an hardware event, such as the push of a button.

Exceptions and interrupts interrupt normal program flow, and branch into an exception handler or Interrupt Service Routine (ISR).

Without interrupt, the microcontroller had to poll periodically the CTRL register bit 16 COUNTFLAG:

a:     ldr r0, [r1, #CTRL]
       tst r0, #SysTick_CTRL_COUNTFLAG_Msk
       beq a

In the interrupt scheme, there is no such a waste of time.

SysTick CTRL

You can enable the SysTick interrupt by setting the bit 1 TICKINT (SysTick exception request enable) of the CTRL register.

With STM MPU, exception handlers are implemented as regular functions, like Reset_Handler:

.type SysTick_Handler, %function
.global SysTick_Handler
SysTick_Handler:
        ...
       bx lr

Until now, the vector table was defined as:

.word 0x20000400         // stack end
.word Reset_Handler
.space 0xf8

The first word contains the initial stack pointer address and the second word contains the address of the first instruction of the program (defined via ‘.word Reset_Handler’).

We now need to tell the MCU the address of the SysTick handler.

The first elements of the vector table in chapter 13.3 “Interrupt and exception vectors” of the reference manual shows this adddress:

SysTick CTRL

The SysTick handler address is at location 0x3c.

The code becomes:

.word 0x20000400         // stack end
.word Reset_Handler      // address 0x0004
.space 0x34
.word Systick_Handler    // address 0x003c
.space 0xc0

After compilation and linking, with arm-none-eabi-objdump -d gpio.elf:

Disassembly of section .text:

08000000 <Reset_Handler-0x100>:
 8000000:   20000400    andcs   r0, r0, r0, lsl #8
 8000004:   08000101    stmdaeq r0, {r0, r8}
   ...
 800003c:   08000135    .word   0x08000135

The last line shows that we have indeed the correct address 800 003c (SysTick vector), with the Systick Handler beginning at address 800 0135.

ldr r0, =TimerValue
bl StartSysTick
SleepLoop:
        wfi
        b SleepLoop