Cortex-M4 上的 Systick 定时器:它的预分频器是什么?
Systick timer on Cortex-M4: What is its prescaler?
我对 Cortex-M4 上的 Cortex 系统定时器有点困惑 CPU。
比方说,我们有以下配置:
- 16MHz HSI作为时钟源;
- AHB1 预分频器设置为 1(即 HSI 除以 1);
表示主系统总线(即AHB1或AHB)以每秒16 000 000 ticks的速度运行。就我而言,系统计时器(所谓的 SysTick)以主系统总线的速度运行,因此它每秒应该计数到 16 000 000。这似乎很明显,但是当我查看 STM32F407xx 参考手册中的 Clock tree
图时,我看到了这个:
看起来 system timer
以以下速度运行:(main system bus speed) / 8
。
这是真的吗?我已将系统计时器配置为每 16 000 000 次滴答生成一次中断。基于上面提供的配置(即 HSI 作为时钟源和 AHB1 预分频器 = 1),它每秒产生一次中断,从而打开和关闭 LED。我试图测量“眨眼”之间的时间,它似乎恰好是 1 秒。如果有这个预分频器(即 /8),那么 LED 应该每 8 秒切换一次。
您可以在下面找到配置系统时钟源和系统定时器的代码。
- HSI 频率 = 16 [MHz]
- SYSTICKS_COUNT = 16 000 000
void system_clock_init(void)
{
LL_RCC_HSI_Enable();
while (LL_RCC_HSI_IsReady() != 1) {
;
}
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
;
}
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
}
void system_clock_systick_config_init(void)
{
SysTick_Config(SYSTICKS_COUNT);
}
void SysTick_Handler(void)
{
led_toggle(LED_PIN_BOARD_GREEN);
}
参考手册在本节末尾指出 “6.2 时钟”:
The RCC feeds the external clock of the Cortex System Timer (SysTick) 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.
根据STM32 Cortex-M4编程手册SysTick控制寄存器的第2位(STK_CTRL)选择时钟源:
Bit 2 CLKSOURCE: Clock source selection
0: AHB/8
1: Processor clock (AHB)
根据同一手册,默认值应为 0(使用 AHB/8)。显然在您的代码中某处此位设置为 1 !?!
我对 Cortex-M4 上的 Cortex 系统定时器有点困惑 CPU。
比方说,我们有以下配置:
- 16MHz HSI作为时钟源;
- AHB1 预分频器设置为 1(即 HSI 除以 1);
表示主系统总线(即AHB1或AHB)以每秒16 000 000 ticks的速度运行。就我而言,系统计时器(所谓的 SysTick)以主系统总线的速度运行,因此它每秒应该计数到 16 000 000。这似乎很明显,但是当我查看 STM32F407xx 参考手册中的 Clock tree
图时,我看到了这个:
看起来 system timer
以以下速度运行:(main system bus speed) / 8
。
这是真的吗?我已将系统计时器配置为每 16 000 000 次滴答生成一次中断。基于上面提供的配置(即 HSI 作为时钟源和 AHB1 预分频器 = 1),它每秒产生一次中断,从而打开和关闭 LED。我试图测量“眨眼”之间的时间,它似乎恰好是 1 秒。如果有这个预分频器(即 /8),那么 LED 应该每 8 秒切换一次。
您可以在下面找到配置系统时钟源和系统定时器的代码。
- HSI 频率 = 16 [MHz]
- SYSTICKS_COUNT = 16 000 000
void system_clock_init(void)
{
LL_RCC_HSI_Enable();
while (LL_RCC_HSI_IsReady() != 1) {
;
}
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
;
}
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
}
void system_clock_systick_config_init(void)
{
SysTick_Config(SYSTICKS_COUNT);
}
void SysTick_Handler(void)
{
led_toggle(LED_PIN_BOARD_GREEN);
}
参考手册在本节末尾指出 “6.2 时钟”:
The RCC feeds the external clock of the Cortex System Timer (SysTick) 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.
根据STM32 Cortex-M4编程手册SysTick控制寄存器的第2位(STK_CTRL)选择时钟源:
Bit 2 CLKSOURCE: Clock source selection
0: AHB/8
1: Processor clock (AHB)
根据同一手册,默认值应为 0(使用 AHB/8)。显然在您的代码中某处此位设置为 1 !?!