1.STM32-Systick tick timer
-
Systick timer is a simple timer. For CM3,CM4,CM7 core chips of ST, there are Systick timers.
-
Systick timers are often used for delays or for the heartbeat clocks of real-time systems. This saves MCU resources without wasting a timer. For example, in UCOS, time-sharing reuse requires a minimum time stamp. Generally in STM32+UCOS systems, Systick is used to make the UCOS heartbeat clock.
-
Systick timer is the system tick timer, a 24-bit countdown timer that automatically reloads the initial timer value from the RELOAD register when 0 is counted. As long as it is not cleared in the SysTick control and status register, it will never stop and will work even in sleep mode.
-
SysTick timers are bundled in NVIC to produce SYSTICK exceptions (exception number: 15).
-
The priority of Systick interrupts can also be set.
-
Four Systick Registers
CTRL SysTick Control and Status Registers LOAD SysTick Automatic reload divide register VAL SysTick Current Value Register CALIB SysTick Calibration value register
Can be in core-core_ Cm7. Found in file H
typedef struct { __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type;
SysTick Control and Status Register - CTRL:
For STM32, the external clock source is 1/8 of the HCLK(AHB bus clock). The kernel clock is the HCLK clock. Configuration function: HAL_SYSTICK_CLKSourceConfig();
SysTick Reload Value Register-LOAD
SysTick Current Value Register-VAL
Systick-related functions in the HAL library:
stm32f7xx_hal_cortex.c File: HAL_ SYSTICK_ CLKSourceConfig (); // Systick Clock Source Selection
If SysTick's clock originates from HCLK, assuming the external crystal oscillation is 25M, doubling frequency to 216MHZ, then SysTick's clock is 216MHZ, that is, every minus 1 of SysTick's counter VAL, represents a time lapse of 1/216us.
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource) { /* Check the parameters */ assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource)); if (CLKSource == SYSTICK_CLKSOURCE_HCLK) { SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; } else { SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK; } }
Take a look at what CLKSources can be: find IS_ SYSTICK_ CLK_ Definition of SOURCE, found to be SYSTICK_CLKSOURCE_HCLK and SYSTICK_CLKSOURCE_HCLK_DIV8, that is, no crossover or 8 crossover.
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SYSTICK_CLKSOURCE_HCLK) || \ ((SOURCE) == SYSTICK_CLKSOURCE_HCLK_DIV8))
core_cm7.h File: SysTick_Config (uint32_t ticks)//Initialize systick, clock is HCLK, and interrupt is turned on.
Ticks: how many systick cycles have an interruption occurred. Used to configure how many ticks the SysTick timer has gone through for one interrupt.
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ }
First see SysTick_LOAD_RELOAD_Msk, since Systick is a 24-bit countdown timer, the value cannot be too large.
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/)
Systick interrupt service function: void SysTick_Handler (void);
2.delay function
//Initialization Delay Function //When ucos is used, this function initializes the clock beat of ucos //SYSTICK's clock is fixed at 1/8 of the AHB clock //SYSCLK: System clock frequency void delay_init(u8 SYSCLK) { #if SYSTEM_SUPPORT_OS // If OS support is required. u32 reload; #endif HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick frequency is HCLK fac_us=SYSCLK; //Fac_whether OS is used or not Us needs to be used #if SYSTEM_SUPPORT_OS // If OS support is required. reload=SYSCLK; //Counts per second in K reload*=1000000/delay_ostickspersec; //According to delay_ostickspersec sets overflow time //reload is a 24-bit register with a maximum value of 16777216, approximately 77.7ms at 216M fac_ms=1000/delay_ostickspersec; //Represents the smallest unit that the OS can delay SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//Turn on SYSTICK interrupt SysTick->LOAD=reload; //Every 1/OS_TICKS_PER_SEC interrupted once in seconds SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //Open SYSTICK #endif }
Call delay_in main Init(216);// Delayed initialization. 1 microsecond equals 10 minus 6 seconds and 1 MHZ equals 10^6 Hz.
fac_us=SYSCLK; System clock is 216MHZ, fac_us=216 means how many systick cycles it takes for a systick to run 1us. Since systick is 216MHZ, 216 cycles are required. If you need to delay n microseconds later, you only need n*fac_us is fine. Since the set SysTick frequency is HCLK, delay_is called The parameter SYSCLK in the init function is 216.
delay_us function ideas:
Detect the current value in the loop. If the current value is less than the previous value, it does not decrease to 0. You can tell how many cycles you are running by telling-tnow. Otherwise, the description has overflowed, that is, reload-tnow+told cycles are currently running. Finally, exit if the time exceeds/equals the time to be delayed.
//Delayed nus //nus: The number of us to delay. //Nus:0~204522252 (maximum 2^32/fac_us@fac_us=21) void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; u32 reload=SysTick->LOAD; //Value of LOAD ticks=nus*fac_us; //Number of beats required delay_osschedlock(); //Prevent OS scheduling and interrupt us latency told=SysTick->VAL; //Counter value at first entry while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow<told)tcnt+=told-tnow; //Notice here that SYSTICK is a decreasing counter. else tcnt+=reload-tnow+told; told=tnow; if(tcnt>=ticks)break; //If the time exceeds/equals the time to be delayed, exit. } }; delay_osschedunlock(); //Restore OS Scheduling }