STM32F0xx系列的时钟疑问

在ST的数据手册中查看STM32F0 系列的系统框图是看不到APB2的,但是不管是在STM32F0的LL库/HAL库中都会提到APB2。

在仔细查看时钟树之后可以发现(这里以F030的时钟树图举例,整个F0系列的外设和时钟树应该是差别不大),STM32F0系列的APB外设时钟分频之后还会再分出4路,其中一路直接进入APB外设,另外三路分别进入ADC、部分定时器、USART1,要注意的是这里的ADC和USART1都有CLK MUX,这表示这两个外设还可以切换不同的时钟源,并非一定要绑定在APBPCLK上。所以这里我们先不讨论这两部分外设,着重看这路进入定时器组的时钟。
image
在F0系列的LL库中,称呼APB2为High Speed APB,而在HAL库中,引用了部分LL库中的内容,但是将其重新命名为了APB1 GRP2 PERIPH,与之对应的就是在APB1 GRP1 PERIPH ,看起来ST自己也意识到了这部分内容的诡异,选择在HAL库中将之前F0系列上的“APB2” 更正回APB1 GRP2。

至于为什么称呼这部分为High SPeed APB,应该是在这些定时器之前有一路PLL,当APB1 预分频器不为1时,PLL会切换到x2模式,保持速度比正常APB更高,这部分只应用在APB的定时器上,以至于CubeMX中直接将这部分称为APB1 Timer Clocks。
image-1694187361870

到这里似乎疑问已经解决了大半,但是我翻查的时候发现,在LL库上,有部分Timer的初始化名称是绑在APB1上的

例如

#if defined(TIM2)
#define LL_APB1_GRP1_PERIPH_TIM2           RCC_APB1ENR_TIM2EN
#endif /*TIM2*/
#define LL_APB1_GRP1_PERIPH_TIM3           RCC_APB1ENR_TIM3EN
#if defined(TIM6)
#define LL_APB1_GRP1_PERIPH_TIM6           RCC_APB1ENR_TIM6EN

而不是我们这里猜测的这种名义上在APB2上的定义

#define LL_APB1_GRP2_PERIPH_TIM1           RCC_APB2ENR_TIM1EN

最后我只能猜测是在LL时期,APB1和APB2(即所谓的High Speed APB)之间区分其实并不严格,两者在MCU中的配置寄存器都是一个32bit的寄存器,部分挂载在Low Speed APB上的设备也会存储在APB2的寄存器中,而部分APB2的设备也会存储在APB1的寄存器中。这种命名混乱导致用户会在理解STM32F0系列的时钟时产生疑惑,所以也就有了后来的APB1 GRP1/2之分。

有论坛提到"APB2" 时钟误差较大,可能是"APB2"的PLL精度有问题? 也可能是他们用了APB1的时钟进行计算,实际上只有定时器在"APB2"中。

总结

STM32F0系列上不存在APB1/APB2 只有一个APB,而在这个APB中的定时器时钟,会和APB时钟保持一致或是通过定时器组前的PLL x2,早年LL库上的命名混乱导致了如今的HAL在上面继续缝补,出现了APB1 GRP2这样的奇怪命名,其实并不需要在意这些也能正常使用设备。