仅适用于 ARM Cortex-M 移植的可选参数。
ARM Cortex-M 移植默认从 Cortex-M Sys滴答 定时器生成 RTOS 滴答 中断。大多数 Cortex-M MCU 以与 MCU 自身相同的频率运行 SysTick 定时器,如果这样,则不需要 configSYSTICK_CLOCK_HZ,而且它应保持未定义状态。如果 SysTick 定时器的频率与 MCU 核心不同,那么应将 configCPU_CLOCK_HZ 设置为正常的 MCU 时钟频率,将 configSYSTICK_CLOCK_HZ 设置为 SysTick 时钟频率。
这个参数在讲解STM32f103源码中的FreeRTOSConfig.h中设置
这个参数代表 SysTick 时钟频率,在正点原子的STM32F103和STM32F407的源码中有着不同的设置
我们先理一下系统时钟的设置流程
STM32F407具有两个PLL,用于产生不同的时钟信号。这里主要来讨论主PLL时钟。主PLL时钟的时钟源有两个信号,分别是上边提到的HIS信号和HSE信号。PLL通过把这两个信号倍频,分频等达到更高频率的时钟信号。一般来说,由于HIS和HSE的时钟频率较低,SYSCLK一般都不会选择HIS时钟和HSE时钟作为系统时钟,而主PLL产生的时钟一般会用作系统时钟。下面我们来看下主PLL的内部结构框图。
由图可以看出PLL的时钟源主要有两个:HSE时钟信号和HIS时钟信号。其中PLL_M,PLL_N,PLL_P,PLL_Q是一个分频器,而PLL_M是一个倍频器。假设图中经过PLL_N之后的时钟信号为PLL_VCO,PLL使用外部时钟信号HSE作为时钟源。那么有如下关系。
PLL_VCO = (HSE / PLL_M)* PLL_N
SYSCLK = PLL_VCO/ PLL_P
所以,如果外部晶振的频率已经确定了,那么确定PLL_M,PLL_N,PLL_P的系数就可以得到对应频率的系统时钟SYSCLK,其中PLL_M,PLL_N,PLL_P可以有多种组合,只要满足相应的条件即可。例如,假设外部晶振为8M,对STM32F407来说,系统时钟的最大频率为168M,那么久可以分别设置PLL_M = 8,PLL_N = 336,PLL_P = 2。来产生168M的时钟。即SYSCLK = ( 8 /8 ) * 336 / 2 = 168M。
通过配置主PLL,我们就得到了系统的主时钟SYSCLK,下一步我们就可以通过这个时钟来分频得到各个外设的时钟。
时钟的基本概念
1、实时时钟是指给日期及时间计数器累加的时钟,通常是32768Hz,
2、系统时钟是指单片机内部的主时钟,给各个模块提供工作时钟的基础
3、CPU时钟是指经过CPU的PLL后将系统时钟改变为CPU工作的时钟。
HSI是高速内部时钟,RC振荡器,频率为8MHz。
在正点原子STM32F407-freertos的源码.FreeRTOSConfig.h中
这里的SystemCoreClock右键跳转到可以知道CPU频率多少,这里是16Mhz
在正点原子STM32F103-freertos的源码.FreeRTOSConfig.h,可以看到CPU时钟频率,在主函数中没有对它再设置,所以103CPU 时钟频率就是这个
我们先来看看 STM32 的时钟树
The RCC feeds the Cortex System Timer (SysTick) external clock with the AHB clock(HCLK) divided by 8.
The SysTick can work either with this clock or with the Cortex clock(HCLK), configurable in the SysTick Control and Status Register.
上面这段话的意思是,SysTick的时钟来源可以是HCLK的8分频或就是HCLK,
具体是哪种可通过配置"控制和状态寄存器(CTRL)"来选择。
在delay.c中
右键跳转到定义,这里传入参数SysTick_CLKSource_HCLK
HCLK :AHB总线时钟,由系统时钟SYSCLK 分频得到,一般不分频,等于系统时钟
SysTick->CTRL |= SysTick_CLKSource_HCLK;
表示把BIT2位置1,表示使用内核时钟不分频作为SysTick的时钟源
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
表示把BIT2位置0,表示使用外部时钟源八分频作为的SysTick时钟源
SysTick_CLKSource_HCLK系统内核时钟,在这里数值代替HCLK
此时CPU时钟频率和系统时钟频率一样
在正点原子STM32F103和407中,在初始没有移植freertos的源码中,delay.c中均为
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
此时系统时钟频率为CPU时钟频率1/8
而移植freertos后的stm32f103设置使用内核时钟不分频作为SysTick的时钟源,这时候就不在需要把SystemCoreClock/8来得到SystemCoreClock的频率了。也就是由fac_us=SystemCoreClock/8/1000000; 变为fac_us=SystemCoreClock/1000000;
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init()
{
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用
reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M
reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右
fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}
重点是观察在delay.c文件函数中系统滴答定时器的频率是否和内核时钟频率相同,不过原子为了方便都没有选择分频,这个时候就注释或者删去那句话即可。