当前位置:网站首页>Learning record: understand systick system timer and write delay function

Learning record: understand systick system timer and write delay function

2022-07-06 15:32:00 Bitter tea seeds

Catalog

One 、Sys Tick Calculation of timing time

Two 、Sys Tick register

3、 ... and 、Sys Tick Interrupt priority

Four 、 Write the delay function

 


SysTick Tied to NVIC in , It's a 24 position Timer for , And can only decrease .

(NVIC It is a vector interrupt controller , It also contains MPU Control register of 、SysTick Timer and debugging control .)

And in the 《STM32 Chinese Reference Manual 》 in , Yes SysTick The introduction of is just a simple sentence :SysTick The calibration value is fixed to 9000, When SysTick The clock is set to 9MHz(HCLK/8 The maximum of ), produce 1ms Time base .

One 、Sys Tick Calculation of timing time

System timer reloading register

Let the time of a cycle count be t ;

Clk from CTRL Register configuration , The frequency is 72M and 9M

In the clock tree Sys Tick

 

misc.c The system clock  

If you choose SysTick_CLKSource_HCLK for 72M;

Otherwise, it would be SysTick_CLKSource_HCLK_Div8 for 9M;

/**
  * @brief  Configures the SysTick clock source.
  * @param  SysTick_CLKSource: specifies the SysTick clock source.
  *   This parameter can be one of the following values:
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  * @retval None
  */
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

misc.h The system clock  

/** @defgroup SysTick_clock_source 
  * @{
  */
/*/8, That is, select the kernel clock 9M*/
#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
/*72M*/
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))

 t=RELOAD*(1/clk)

Clk( Clock interrupt )=72M when ,t=(72)×(1/72M)=1 us; //1 us Enter an interrupt NVIC

Clk( The clock )=72M when ,t=(72000)×(1/72M)=1 Ms; //1 ms Enter an interrupt NVIC

Convert units according to time :1 s=1000 ms=1000000 us=1000000000 ns

Two 、Sys Tick register

Sys Tick Register structure

core_cm3.h:

/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
  memory mapped structure for SysTick
  @{
 */
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;

Sys Tick Configure library functions

/**
 * @brief  Initialize and start the SysTick counter and its interrupt.
 *
 * @param   ticks   number of ticks between two interrupts
 * @return  1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible reload  The register of 24bit, The maximum value is 2^24*/
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register  To configure reload The initial value of the ,'-1' Because when configuring , One has been consumed systick cycle */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts  Configure interrupt priority as 1<<4-1=15, The priority is the lowest */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value To configure counter The value of the counter  */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer  To configure systick The clock is 72M, To interrupt , Can make systick*/
  return (0);                                                  /* Function successful */
}

 NVIC_SetPriority function

static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if(IRQn < 0) {
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
  else {
    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
}

3、 ... and 、Sys Tick Interrupt priority

1.STM32 Both the kernel and peripherals are used 4 Binary bits to indicate interrupt priority .

2. The grouping of interrupt priority is also applicable to the kernel and peripherals . When comparing , Just group and parse the four bits of the interrupt priority of the peripheral device of the kernel according to the interrupt priority of the peripheral device , That is to say, artificially divide preemptive priority and sub priority . 

 

Four 、 Write the delay function

 1. Write a delay function

bsp_SysTick.h The header file

#ifndef __SYSTICK_H
#define __SYSTICK_H

#include "stm32f10x.h"

void SysTick_Init(void);
void Delay_us(__IO u32 nTime);
#define Delay_ms(x) Delay_us(100*x)	 // Company ms

void SysTick_Delay_Us( __IO uint32_t us);
void SysTick_Delay_Ms( __IO uint32_t ms);


#endif

 bsp_SysTick.c file

#include "bsp_SysTick.h"
#include "core_cm3.h"
#include "misc.h"

static __IO u32 TimingDelay;
 
/**
  * @brief   Start the system tick timer  SysTick
  * @param   nothing 
  * @retval  nothing 
  */
void SysTick_Init(void)
{
	/* SystemFrequency / 1000    1ms Break once 
	 * SystemFrequency / 100000	 10us Break once 
	 * SystemFrequency / 1000000 1us Break once 
	 */
//	if (SysTick_Config(SystemFrequency / 100000))	// ST3.0.0 Library version 
	if (SysTick_Config(SystemCoreClock / 100000))	// ST3.5.0 Library version 
	{ 
		/* Capture error */ 
		while (1);
	}
}

/**
  * @brief   us Delay program ,10us For a unit 
  * @param  
  *		@arg nTime: Delay_us( 1 )  Then the delay is  1 * 10us = 10us
  * @retval   nothing 
  */
void Delay_us(__IO u32 nTime)
{ 
	TimingDelay = nTime;	

	//  Enable tick timer   
	SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;

	while(TimingDelay != 0);
}

/**
  * @brief   Get the beat program 
  * @param   nothing 
  * @retval  nothing 
  * @attention   stay  SysTick  Interrupt function  SysTick_Handler() call 
  */
void TimingDelay_Decrement(void)
{
	if (TimingDelay != 0x00)
	{ 
		TimingDelay--;
	}
}

#if 0
//  This   Firmware library functions   stay  core_cm3.h in 
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  // reload  The register is 24bit, The maximum value is 2^24
	if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);
  
  //  To configure  reload  The initial value of the register 	
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
	
	//  Configure interrupt priority as  1<<4-1 = 15, The priority is the lowest 
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
	
	//  To configure  counter  The value of the counter 
  SysTick->VAL   = 0;
	
	//  To configure systick  The clock is  72M
	//  To interrupt 
	//  Can make systick
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    
  return (0); 
}
#endif

// couter  reduce 1 Time for   be equal to  1/systick_clk
//  When counter  from  reload  The value of is reduced to 0 When , For a cycle , If interrupt is turned on, the interrupt service program is executed ,
//  meanwhile  CTRL  Of  countflag  Position meeting position 1
//  The time of this cycle is  reload * (1/systick_clk)

void SysTick_Delay_Us( __IO uint32_t us)
{
	uint32_t i;
	SysTick_Config(SystemCoreClock/1000000);
	
	for(i=0;i<us;i++)
	{
		//  When the value of the counter decreases to 0 When ,CRTL Bit of register 16 I'll set 1	
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	//  close SysTick Timer 
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Delay_Ms( __IO uint32_t ms)
{
	uint32_t i;	
	SysTick_Config(SystemCoreClock/1000);
	
	for(i=0;i<ms;i++)
	{
		//  When the value of the counter decreases to 0 When ,CRTL Bit of register 16 I'll set 1
		//  Dangzhi 1 when , Reading this bit clears 0
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	//  close SysTick Timer 
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

 main.c

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_led.h"

/*
 * t :  Timing time  
 * Ticks :  How many clock cycles produce an interrupt  
 * f :  clock frequency  72000000
 * t = Ticks * 1/f = (72000000/100000) * (1/72000000) = 10us 
 */ 

/**
  * @brief   The main function 
  * @param   nothing   
  * @retval  nothing 
  */
int main(void)
{	
	/* LED  Port initialization  */
	LED_GPIO_Config();

#if 0
	/*  To configure SysTick  by 10us Break once  */
	SysTick_Init();	
	for(;;)
	{

		LED1( ON ); 
	    Delay_us(100000);    	// 100000 * 10us = 1000ms
		//Delay_ms(100);
		LED1( OFF );
	  
		LED0( ON );
	    Delay_us(100000);		// 100000 * 10us = 1000ms
		//Delay_ms(100);
		LED0( OFF );
	
	}     
#else //  Do not use interrupt , Use the method of query 
	for(;;)
	{

		LED1( ON ); 
		SysTick_Delay_Ms( 1000 );
		LED1( OFF );
	  
		LED0( ON );
		SysTick_Delay_Ms( 1000 );
		LED0( OFF );
	
	} 
#endif	
}

  Delay function library file

delay_init function

// Initialization delay function 
// When using  OS  When , This function initializes  OS  The beat of the clock 
//SYSTICK  The clock is fixed to  HCLK  The clock 
//SYSCLK: System clock frequency 
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS // If support is needed  OS.
u32 reload;
#endif
 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
//SysTick  The frequency is  HCLK
fac_us=SYSCLK; // Whether used or not  OS,fac_us  You need to use 
#if SYSTEM_SUPPORT_OS // If support is needed  OS.
reload=SYSCLK; // The number of counts per second   Unit is  K 
reload*=1000000/delay_ostickspersec; // according to  delay_ostickspersec  Set the overflow time 
//reload  by  24  Bit register , Maximum :16777216, stay  72M  Next , About us  0.233s  about 
fac_ms=1000/delay_ostickspersec; // representative  OS  The minimum unit that can delay  
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;// Turn on  SYSTICK  interrupt 
SysTick->LOAD=reload; // Every time  1/OS_TICKS_PER_SEC  Second break once 
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // Turn on  SYSTICK
#else
#endif
}

SysTick->CTRL Bit definition of ( Structure pointer )

SysTick-> VAL The definition of  

 delay_us function

// Time delay  nus
//nus  To delay  us  Count .
//nus:0~190887435( The maximum value is  2^32/[email protected]_us=22.5)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD  Value  
ticks=nus*fac_us; // The number of beats needed 
told=SysTick->VAL; // Counter value at the time of first entry 
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{ 
if(tnow<told)tcnt+=told-tnow;// Note here  SYSTICK  It's just a decreasing counter .
else tcnt+=reload-tnow+told; 
told=tnow;
if(tcnt>=ticks)break; // For more than / Equal to the time to delay , The exit .
} 
};
}
// Time delay  nus
//nus: To delay  us  Count .
//nus:0~190887435( The maximum value is  2^32/[email protected]_us=22.5) 
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD  Value  
ticks=nus*fac_us; // The number of beats needed  
delay_osschedlock(); // prevent  OS  Dispatch , Prevent interruptions  us  Time delay 
told=SysTick->VAL; // Counter value at the time of first entry 
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{ 
if(tnow<told)tcnt+=told-tnow; // Be careful  SYSTICK  Is a decrement counter .
else tcnt+=reload-tnow+told; 
told=tnow;
if(tcnt>=ticks)break; // For more than / Equal to the time to delay , The exit .
} 
};
delay_osschedunlock(); // recovery  OS  Dispatch  
}

delay_ms function  

// Time delay  nms
//nms: To delay  ms  Count 
void delay_ms(u16 nms)
{
u32 i;
for(i=0;i<nms;i++) delay_us(1000);
}
// Time delay  nms
//nms: To delay  ms  Count 
//nms:0~65535
void delay_ms(u16 nms)
{
if(delay_osrunning&&delay_osintnesting==0)// If  OS  Already running , And not in interruption 
{
if(nms>=fac_ms) // The delay time is longer than  OS  The minimum time period of 
{ 
 delay_ostimedly(nms/fac_ms); //OS  Time delay 
}
nms%=fac_ms; //OS  It is no longer possible to provide such a small delay , Delay in the normal way  
}
delay_us((u32)(nms*1000)); // Normal mode delay 
}

 

 

 

 

 

 

 

 

原网站

版权声明
本文为[Bitter tea seeds]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060919235885.html