SysTick system timer (functional block diagram and priority configuration)

      SysTick — The system timer is a peripheral that belongs to the CM3embedded in the NVIC. The system timer is a 24bit (2^24) down-decrementing counter. The time for each count of the counter is 1/SYSCLK. Generally, we set the system clock SYSCLK equal to 72M. When the value of the reload value register is decremented to 0, the system timer generates an interrupt, and the cycle repeats.

     Because SysTick is a peripheral belonging to the CM3 core, all microcontrollers based on the CM3 core have this system timer, so that the software can be easily transplanted in the CM3 microcontroller. The system timer is generally used in the operating system to generate the time base and maintain the heartbeat of the operating system.

1

    The execution process of SysTick: driven by the clock, the counter counts down from the initial value of reload to 0 (the value can be viewed in STK_VAL during the decrementing process), generates an interrupt and sets the COUNTFLAG flag. Then start counting down again from the reload value, and so on.


SysTick related registers

     SysTick—The system timer has 4 registers (CTRL LOAD VAL CALIB) , which are briefly described below. When using SysTick to generate timing, only the first three registers need to be configured, and the last calibration register does not need to be used.

 2


SysTick register structure

      SysTick register (defined in firmware library file: core_cm3.h)

typedef struct{
   _IO uint32_t CTRL;       /*Control and Status Register*/ 
  _IO uint32_t LOAD;       /*Reload Value Register*/ 
  _IO uint32_t VAL;        /*Current Value Register*/ 
 _IO uint32_t CALIB;       /*Calibration Register*/


}

SysTick library function

      SysTick configuration library function (defined in firmware library file: core_cm3.h)

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
 {
 // Impossible reload value, out of range 
 if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) {
  return (1UL);
 }

 // set reload register
 SysTick->LOAD = (uint32_t)(ticks - 1UL);

 // Set the interrupt priority, the default priority is the lowest __NVIC_PRIO_BITS 4 (1111) The priority set by the system timer at this time is the lowest in the kernel peripherals
 NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);

 // set the current value register
 SysTick->VAL = 0UL;

 // Set the clock source of the system timer to AHBCLK=72M 
 // Enable the system timer interrupt 
 // Enable the timer
 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
21 SysTick_CTRL_TICKINT_Msk |
22 SysTick_CTRL_ENABLE_Msk;
23 return (0UL);
24 }

      When programming with the firmware library , we only need to call the library function SysTick_Config() . The formal parameter ticks is used to set the value of the reload register. The maximum value cannot exceed the value of the reload register 2^24. When the value of the reload register is decremented When it reaches 0, an interrupt is generated, and then the value of the reload register is reloaded and counted down, and this cycle repeats. Then set the interrupt priority , and finally configure the clock of the system timer equal to AHBCLK=72M , enable the timer and timer interrupt, so that the system timer is configured, and a library function is done. 

Configuring SysTick Interrupt Priority

     In the SysTick_Config() library function, the firmware library function NVIC_SetPriority() is also called to configure the interrupt priority of the system timer. This library function is also defined in core_m3.h. The prototype is as follows

__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
 {
 if ((int32_t)IRQn < 0) {
 SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] =(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
 } else {
 NVIC->IP[((uint32_t)(int32_t)IRQn)] =(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
 }
 }

      The function first judges the size of the formal parameter IRQn . If it is less than 0 , it means that this is a system exception . The priority of the system exception is controlled by the register SHPRx of the kernel peripheral SCB . If it is greater than 0 , it is an external interrupt and the priority of the external interrupt.by IPx registers in the core peripheral NVIC .

      Because SysTick is a kernel peripheral, it is somewhat different from the interrupt priority of ordinary peripherals, and there is no preemption priority and sub-priority. In STM32F103, the interrupt priority of the core peripheral is configured by the peripheral register of the core SCB: SHPRx (x=1.2.3).

      SPRH1-SPRH3 is a 32-bit register , but can only be accessed by bytes, and each 8 fields control the configuration of the interrupt priority of a core peripheral. In STM32F103, only the high four bits of bits 7:3 are valid, and the low four bits are not used, so the interrupt priority of the core peripheral can be programmed as: 0~15, there are only 16 programmable priorities, the smaller the value, higher priority . If the software priority configuration is the same, then the priority size is determined according to their position number in the interrupt vector table. The smaller the number, the higher the priority. (The priority set by the system timer at this time is the lowest among the core peripherals .)

     

Peripheral interrupt priority and core peripheral priority comparison

     The kernel priority is not divided into preemption priority and sub-priority, but not the priority of the kernel peripheral must be higher than the priority of the peripheral.

    Judgment method : Set the value of priority 0-15 according to the kernel peripherals, and group the four bits of the interrupt priority of the kernel peripherals according to the interrupt priority of the peripherals to analyze, that is, artificially separate the preemption priority. and subpriorities.

     For example, configure the interrupt priority group of a peripheral as 2, the preemption priority as 1, and the sub-priority as 1. The priority of systick is 15 by default in the firmware library. When we compare the interrupt priority of core peripherals and on-chip peripherals, we only need to grasp that the NVIC's interrupt priority grouping is not only valid for on-chip peripherals, but also for core peripherals. We convert the priority 15 of the systick into a binary value of 1111(0b), and because the priority of the NVIC is grouped as 2, then the first two digits of 11(0b) are 3, and the last two digits of 11(0b) are also 3. Both preemption and sub-priority are lower than the priority of the peripheral we set. If the two software priorities are configured to be the same, then compare their hardware numbers in the interrupt vector table, the smaller the number, the higher the priority.

SysTick initialization function

void SysTick_Init(void)
{
 /* SystemFrequency / 1000 1ms interrupt once
 * SystemFrequency / 100000 10us interrupt once
 * SystemFrequency / 1000000 1us interrupt once
 */
 if (SysTick_Config(SystemCoreClock / 100000)) {
 /* Capture error */
  while (1);
   }
}
     The SysTick initialization function is written by the user, which calls the firmware library function SysTick_Config(). By setting the formal parameters of the firmware library function, it determines how long the system timer will generate an interrupt.

SysTick timing calculation

    Time unit conversion: 1s = 1000ms = 1000 000 us = 1000 000 000ns

          t = reload * ( 1/clk )

  1. When Clk = 72M, t = (72) *(1/ 72 M ) = 1US
  2. When Clk = 72M, t = (72000) * (1/ 72 M ) = 1MS

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325028324&siteId=291194637