欢迎光临散文网 会员登陆 & 注册

时钟树:MCU 的总动脉

2022-12-07 02:08 作者:二木山人  | 我要投稿

这两天Inav 6 的移植已经和 @Apple树下  把inav 的主要功能调测通过,基本的spi、i2c、uart、pwm、dshot 等功能已经调测通过,后面就主要是完善功能。ATbetaflight的两个主要的bug也都已经修复完毕,回头另行总结。有点时间继续写bf 的专栏。

今天这一章讲Mcu的 时钟树,涉及一下几个点:

1、为什么要用时钟树,at32 的时钟树与STM 32 的时钟树有哪些异同

2、PLL 的计算 时钟频率、总线、分频,时钟配置工具

3、内外部时钟源的选择

4、bf 的时钟树初始化配置过程


    先说MCU 的时钟树,为什么C51 没有这么复杂的时钟树,就确定一个主频就可以工作的很好,而MCU我在用任何外设的时候都要时时刻刻的关心时钟? 其实这是一个功耗与性能的妥协。 MCU在不同的应用场景下,并不是频率越高性能越好就越好。MCU 的工作状态要随着场景变化的需要来决定自己的性能,必须时刻平衡整体设备的功耗与性能,尤其是使用电池供电的场景,如果需要达到较长的电池寿命,必须根据应用的场景调整自己的工作模式。 举个例子,我们的手机,在打游戏的时候这时候电池消耗不是问题,关键是要性能好不卡顿,这时候需要调整工作频率到最高频率,而我们晚上睡觉之后,手机扔一遍不能一直最高频率运行,这时候就要进入到休眠模式,降低cpu和各个设备的工作频率,关闭不需要的外设如屏幕、wifi、蓝牙甚至基带也会进入到低功耗的模式,然后定时器、看门狗又会定时的唤醒设备从休眠模式到低功耗模式。

MCU 也一样,一个好的设计一定是考虑了各种场景的应用。所以MCU 在设计之初,就把各个外设都设计为可以开关的、频率可调的。

另外不管MCU 内部的外设,如GPIO 、定时器等,还是MCU 的通过各种接口,如SPI、I2S 等,外接的外设,如果要正常工作,都必须在设计的频率下通过MCU 的时钟输出来保证工作在同一个节拍下,驱动外设正常的工作,所以mcu 的外设时钟树是所有外设工作的前提, 要想功能正常,必须时刻知道外设工作在那个频率上。我们做嵌入式相关的开发, 所有外设的基本使用模式都是:

使能外设时钟-》配置外设-》初始化外设-》使能外设-》失能外设-》关闭外设时钟

在不同的模式之间切换的时候要针对不同场景的需求,重新启用、使能、配置外设。


1、了解了为什么需要配置外设时钟树,我们来看下at32的时钟树与stm32f4 的时钟树异同 :

at32f435/7  与stm32f4 时钟树对比

可以看到,二者时钟树基本大同小异,

同:

    都提供了内部RC 高低速晶振、外部高低速晶振频率源

    都提供了PLL 锁相环

    都提供了usb 48M emac 频率以及频率输出功能

     定时器的频率都是在 ahb 总线 1分频情况下 与ahb总线相同,2分频情况下timer 频率自动*2 的设置


不同:

      stm32 针对 i2s 等频率敏感的外设提供了第二套PLL

      stm32 主频比较低,但是APB总线频率高(168m zh), AT32 主频比较高,但是APB 总线频率相对低(144Mhz),二者不构成优缺点,外设基本都不会需要这么高的频率。

     二者的系统架构不同,比如at32 的gpio 直接在ahb总线上,而STM32 是在apb1总线上,STM32 的APB总线区分高频、低频两个总线,AT32 的两个APB总线频率一样

    stm32 的外部时钟源更宽泛一些, 支持4-27mzh  at32 支持4-26 mhz

    

其他:

    stm32 时钟选择更为复杂,相应也可以更精确的控制系统功耗,

    二者都具备 时钟校准、外部高速时钟监控的功能,在外部时钟源失效的情况下产生中断,这时可以切换系统时钟源到内部时钟源避免系统直接死机。

    

2、PLL  与时钟配置工具

    PLL 的基础知识不讲,重点关注Sclk 的计算

二者                              PLL 输入时钟 x PLL 倍频系数 N

   都是 Sclk =      ------------------------------------------------------------------

                                  (PLL 预分频系数 m x PLL 后分频系数 R)


比如选择外部晶振 8M 输入的情况下,配置 倍频系数 N= 72 预分频系数m= 1 , 后分频系数 r=2


在at32 的时钟配置工具界面可以通过选择不同的开关、分频系数,来配置整个系统时钟树的时钟,当然如果有多个工作模式的情况下,可以配置多套时钟树配置参数,并自动按照对应的芯片来生成代码。

而 stm32 提供了更加强大的cubemx 工具进行时钟树的配置,由于主要目的是移植到at32 ,所以不做详细的介绍。



at32 时钟树配置


Sclk= 8*72/1/2= 288Mhz

AHB= 288mhz

apb1= 288mhz/2 = 144mhz

apb2= 288mhz/2 = 144mhz

USB= 288/6  = 48Mhz

由于移植的飞控我们追求的是极致的性能,并不关注整体系统的功耗(相对电机的数百瓦的功耗,MCU 的功耗微乎其微),因此我们在设计之初就讲at32f435/7 的整体系统频率配置到最高。

3、内外部时钟源的选择

芯片在内部设计了高速、低速两个时钟源,同时也支持外部晶振作为时钟源(32.khz , 8Mhz 、12、25Mhz 等)但是为什么这么设计呢?

主要的问题我不是特别清楚,说的可能不对,我个人理解如下:

1、内部时钟源使用RC 震荡方式提供内部基础时钟,内部时钟启动速度较快但是存在对于温度比较敏感,在芯片工作温度上来之后会出现“温飘“的现象,主要表现是整体系统时钟频率变化,有可能和外设外设工作不正常。

2、外部时钟源主要是使用石英振荡器或者其他设备的输出时钟源作为输入时钟源,具有频率精准,对温度不敏感(温补晶振),适合作为精准的工作时钟源,但是存在一个频率稳定的时钟过程,另外也有可能存在外部晶振失效的异常情况。

因此bf 里面在系统启动的时候先使用的是内部时钟源,然后在系统初始化过程中,切换到外部时钟源,并使用PLL 控制整体系统的各部分时钟。


4、bf 的时钟初始化配置过程:


bf 在mcu上电之后,启动过程如下

  Startup_at23F435_437.S    reset_handler 初始化 中断向量表、内存段、PG参数

Main.c  main()

src/main/fc/init.c  init 函数

src/main/drivers/System_at32f43x.c  SystemInit 函数

src/main/drivers/startup/at32f435_437_clock.c      system_clock_config 函数


其中system_clock_config 函数就是用 at的 时钟树配置工具生成的代码,具体如下



具体过程可以看详细注释,重点是最后一句: system_core_clock_update,重新配置systick 以及system_core_clock 全局变量为当前系统主频数。


以上是我们对于at32 移植过程中时钟树的配置。

时钟树:MCU 的总动脉的评论 (共 条)

分享到微博请遵守国家法律