之前一直对stm32的上电后的system tick timer时钟配置存疑,为什么定时时间不随频率改变总能保持1ms,cude生成的两个函数HAL_Init()、SystemClock_Config()具体做了什么。趁着空闲把困惑已久又不起眼的问题解答了。
首先分析main中第一个调用的函数HAL_Init():
HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) ||
defined(STM32F102x6) || defined(STM32F102xB) ||
defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) ||
defined(STM32F105xC) || defined(STM32F107xC)
/* Prefetch buffer is not available on value line devices */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#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;
}
在stm32f1xx_hal_conf.h中可以看到PREFETCH_ENABLE被宏定义为1,STM32F103xE已经在keil的设置中被预定义
//stm32f1xx_hal_conf.h
#define PREFETCH_ENABLE 1U
所以函数__HAL_FLASH_PREFETCH_BUFFER_ENABLE()就能被调用,这个函数使能了flash的预取缓冲区
_
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE()
在cube中我对中断优先级设置了4bit主优先级,0bit的次优先级,所以 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)参数为NVIC_PRIORITYGROUP_4
然后就是函数HAL_InitTick(TICK_INT_PRIORITY)
__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;
}
SystemCoreClock 是个被初始化为16000000的变量,uwTickFreq被宏定义为1,所以调用参数为HAL_SYSTICK_Config(16000),经过重重查找找到
//stm32f1xx_hal_cortex.c
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
//core_cm3.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 */
}
ick(16000) < SysTick_LOAD_RELOAD_Msk(0xFFFFFF), 这里SySTick的重装寄存器LOAD设为16000-1,计数寄存器设为0,SysTick_CTRL_CLKSOURCE_Msk设置systick时钟源为AHB而不是AHB/8, SysTick_CTRL_TICKINT_Msk 使能systick中断,SysTick_CTRL_ENABLE_Msk使能systick timer。那么关于systick timer周期设置流程由此得出:系统后面调用SystemClock_Config()初始化完成OSC CLK和AHB CLK与systick时钟源为AHB后,SYSTICK CLK频率就固定为72MHZ,变量SystemCoreClock被改变为72MHZ, 通过再次调用HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq),timer定时器周期=(72000000/1000)*72000000=1/1000(s)==1ms