STM32 系统滴答时钟启动过程 SysTick_Config
- 1. 系统滴答时钟
- 1.1 简介
- 1.2 配置
- 1.3 启动和更新
1. 系统滴答时钟
1.1 简介
SysTick:系统滴答时钟,属于Cortex-M4内核中的一个外设,24bit向下递减计数。
Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS心跳时钟
1.2 配置
用STM32CubeMX配置时钟树时,可以看到Cortex system timer就是滴答时钟
1.3 启动和更新
在STM32CubeMX生成的工程中,滴答时钟启动过程如下:
- HAL_Init() 初始化时:SystemCoreClock =16000000,
- HAL_InitTick()
- HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))
- SysTick_Config()
- HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))
- HAL_InitTick()
SystemCoreClock is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
//main()函数启动
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
//stm32f4xx_hal.c
HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch, Instruction cache, Data cache */
#if (INSTRUCTION_CACHE_ENABLE != 0U)
__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
#if (DATA_CACHE_ENABLE != 0U)
__HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */
#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
HAL_InitTick(TICK_INT_PRIORITY);
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
//stm32f4xx_hal.c
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
// stm32f4xx_hal_cortex.c
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
// core_cm4.h
__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 */
}
- SystemClock_Config() 时,调用HAL_RCC_ClockConfig()对系统SystemCoreClock更新
- SystemClock_Config();
- SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> RCC_CFGR_HPRE_Pos];
- HAL_InitTick (uwTickPrio);
// main()
/* Configure the system clock */
SystemClock_Config();
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
// stm32f4xx_hal_rcc.c
HAL_RCC_ClockConfig()
{
HAL_InitTick (uwTickPrio);
}
- 在中断中更新时钟计数
// stm32f4xx_it.c
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
// stm32f4xx_hal.c
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
}
参考:
- STM32入门:Systick(嘀嗒定时器)学习
- stm32f4xx-systick系统滴答时钟