STM32H7时钟
上图主要列出了 STM32H743 时钟的组成和走向,并没有给出具体外设时钟的设置方法,
外设时钟通过 SCGU(System Clock Generation Unit)、SCEU(System Clock Eable Unit)、PKSU(Peripheral Kernel clock Selection Unit)和 PKEU(Peripheral Kernel clock Enable Unit)等部分设置,这些内容我们待会再介绍。
我们挑选出 10 个重要的地方进行介绍(图 中标出的①~⑩)。
① 低速时钟源,包括 LSI 和 LSE 两个,LSI 属于 STM32H7 内部低速时钟源,频率约为 32Khz。LSE 则是外部低速时钟源,为 32.768Khz(使用 32.768Khz 外部晶振)。这两个时钟
源一般用于看门狗和 RTC。
② 高速时钟源,包括:HSE、HIS、CSI 和 HSI48。HSE 是外部高速时钟,我们使用 25M的外部晶振,所以 HSE 频率为 25Mhz;HSI 是内部高速时钟,频率为 64Mhz;CSI 是低功耗内部时钟,频率为 4Mhz;HSI48 是内部高精度时钟源,频率为 48Mhz,配合 CRS 可以直接作为 USB的时钟源使用。
③ PLL1~3 的时钟源选择器,我们一般选择 PLL 时钟源来自 hse_ck,一般为 25Mhz。
① PLL1 时钟源预分频器,用于对第③步选择的时钟源进行分频,取值范围是:2~63,根据实际需要设置。DIVM2 和DIVM3 分别用于 PLL2 和 PLL3 的预分频器。
② PLL1 锁相环,该 PLL 主要用到两路输出:pll1_p_ck 和 pll1_q_ck,其中:pll1_p_ck一般用于 sys_ck 的时钟源,最终作为 CPU、SysTick、AXI、AHB1~4 和 APB1~4 等的时钟源;
而 pll1_q_ck 则可以通过 PKSU 选择作为部分外设的内核时钟(perx_ker_ck),如 FMC、QSPI、SDMMC1/2 等,详见《STM32H7xx 参考手册》335 页,Table 51。至于图中的 pll1_r_ck,并没有用到。
图中,DIVN1 是主 PLL1 vco 的倍频系数,其取值范围是:4~512;DIVP1 是 PLL1 的 P 分频,用于得到 pll1_p_ck 的频率,其取值范围是:2、4、6…128(必须是偶数);DIVQ1 是 PLL1的 Q 分频,其取值范围是:1~128;DIVR1 则没有用到;FRACN1 是分数倍频系数,它和 DIVN1一起组成 PLL1 的倍频系数,但是我们一般并不需要用到分数倍频,因此不做介绍。同样的,PLL2 和 PLL3 也有类似的设置(倍频系数 N,分频值 P/Q/R),我们不再赘述。这里以 pll1_p_ck为例,简单介绍下 PLL 输出频率的计算公式(时钟 PLL 输入频率为 hse_ck):
假设外部晶振为 25Mhz,我们需要得到 400Mhz 的 pll1_p_ck 频率,则可以设置:DIVM1=5,DIVN1=160,DIVP1=2 即可。其他分频输出(pll1_q_ck/pll1_r_ck)计算方法与上式相似。
③ sys_ck 时钟选择器,可以选择 sys_ck 的时钟来自:hsi_ck、csi_ck、hse_ck 或 pll1_p_ck等,在 PLL1 还没设置好的时候,系统默认是选择 hsi_ck(64Mhz)作为时钟源的,当 PLL1 配置好以后,则系统时钟可以切换为plll1_q_ck(400Mhz),以得到最高性能。
④ SCGU(System Clock Generation Unit,系统时钟生成单元),用于将 sys_ck 分成各种时钟频率,比如:CPU 频率、SysTick、AXI、AHB1~4 和 APB1~4 等,待会详细介绍。
⑤ SCEU(System Clock Eable Unit,系统时钟使能单元),用于使能各个外设、总线等的时钟,是一个时钟开关。待会详细介绍。
⑥ PKSU(Peripheral Kernel clock Selection Unit,外设内核时钟选择单元),用于选择部分外设的内核时钟源,STM32H7 内部,很多外设都可以自由选择内核时钟来源,从而提高使用的灵活性,具体的选择关系,详见《STM32H7xx 参考手册》335 页,Table 51。待会详细介绍。
⑦ PKEU(Peripheral Kernel clock Enable Unit,外设内核时钟使能单元),用于使能部分外设的内核时钟,从而控制外设内核时钟的开/关。待会详细介绍。
SCEU 和 PKEU,一个用于控制外设的访问时钟(访问寄存器),一个用于控制外设的内核时钟(生成控制时序,如波特率等)。但是,并不是所有的外设都需要用到 PKEU,因为有些外设并不需要生成时序,没有所谓的外设内核时钟,比如 DMA、OPAMP 等,这些外设只需要在SCEU 进行使能即可。
图 5.2.2.1 我们就介绍到这,其他未做介绍的部分,请大家参考《STM32H7xx 参考手册》317 页,7.5 节进行学习。
接下来,我们介绍系统时钟生成图(非常重要),如图 4.3.1.2 所示;
上图主要列出了 STM32H743 系统时钟的生成原理,包括 CPU 时钟、SysTick 时钟、AXI时钟、AHB1~4 和 APB1~4 等,这些时钟对整个系统运行来说非常重要,所以该图必须要看懂。
图中,D1、D2 和 D3 域是 ST 为了支持动态能效管理,所设计的 3 个独立的电源域,每个
域都能独立开启/关闭。系统时钟由 SCGU 产生,然后经过 SCEU 做开关,最终输出到各个时钟
域(D1、D2 和 D3),从而能够控制和访问各类外设,保证系统的正常运行。
图中,我们挑选出 8 个重要的地方进行介绍(图中标出的①~⑧):
① SCGU 输入时钟(sys_ck),该时钟我们一般选择来自 pll1_p_ck,频率为 400Mz。
② sys_d1cpre_ck 时钟的分频系数,取值范围为 1~512,通过 RCC_ D1CFGR 寄存器的D1CPRE[3:0]位设置,我们一般设置为 1 分频,以得到最高的 sys_d1cpre_ck 频率,400Mhz。
③ CPU 时钟(rcc_c_ck、rcc_fclk_c),CPU 时钟是直接来自 sys_d1cpre_ck,没有分频器,频率为 400Mhz。
④ SysTick 时钟分频器(固定 8 分频),这个在图中是有错误的,实际上这个分频器是没有的(硬件 bug),因此 SysTick 的时钟频率,直接来自 sys_d1cpre_ck,频率为 400Mhz。
⑤ 系统时钟使能单元(SCEU),它能够对 D1、D2 和 D3 域内的所有外设时钟进行开/关控制,所以在使用外设的时候,必须设置 SCEU,使能其时钟,否则外设无法使用。这里所谓的
SCEU 设置,实际上就是通过 AHB1ENR 之类的寄存器设置的。
⑥ D1 域,是高性能域,CPU 可以从 TCM 和 Cache 中提取紧急的或优先级较高的用户程序,在 400M 的主频下执行,确保实现最快速响应。此域包括:CPU、SysTick、AXI、AHB3 和 APB3等时钟部分。
⑦ D2 域,通信接口域,主要进行数据通信工作,减轻 CPU 的负担。此域包括:AHB1、AHB2、APB1 和 APB2 等时钟部分。 注意:定时器的时钟都是在 D2 域进行控制,而且当 D2PPRE1或 或 D2PPRE2 的分频系数不为 1 的时候,定时器的时钟频率为 rcc_pclk1 或 rcc_pclk2 的 的 2 倍,详见《STM32H7xx 参考手册》331 页,Table 48 。
⑧ D3 域,数据批处理域,此部分中的 ADC 可以在整个系统深度休眠时仍然进行数据处理。在电池驱动的情况下,D3 可以保证在低功耗条件下仍然进行必要的数据处理工作。此域包括 AHB4 和 APB4 等时钟部分。
最后,我们看看外设时钟使能框图,如图所示:
图中,PERx(perx)代表外设 x(x 是 STM32H7 内部的外设,比如 USART、TIM、SPI等),通过此图,我们可以可以知道 STM32H7 内部外设时钟的由来。
图 中,我们挑选出 8 个重要的地方进行介绍(图 v 中标出的①~⑧):
① 系统时钟生成器(SCGU),此部分在图 4.3.1.2 我们进行了详细介绍,这里通过 SCGU产生了三大总线时钟:rcc_bus_d1_ck、rcc_bus_d2_ck、rcc_bus_d3_ck,这些时钟实际上是指AHB14(rcc_hclk14)、APB14(rcc_pclk14)等时钟。
② 系统时钟使能单元(SCEU),此部分将①处生成的时钟进行使能/禁止操作,最终控制是否输出时(rcc_perx_bus_ck)给外设。
③ 总线接口时钟控制逻辑(busif Control Logic),用于控制 SCEU 是否输出时钟给外设,它有很多控制信号,其中我们常用的是 PERxEN(图中红圈圈出部分),通过这个位的设置
就可以控制具体外设的时钟开/关。
④ 外设总线时钟(rcc_perx_bus_ck),该时钟主要用于访问外设寄存器,对外设进行设置。任何外设都必须使能该时钟才可以正常使用。
⑤ 外设内核时钟选择单元(PKSU,即:Peripheral Kernel clock Selection Unit),用于选择某个外设的内核时钟来源,具体的选择关系,详见《STM32H7xx 参考手册》335 页,Table 55。
⑥ 外设内核时钟使能单元(PKEU,即:Peripheral Kernel clock Enable Unit),此部分将⑤处选择的外设内核时钟进行使能/禁止操作,最终控制是否输出内核时钟(rcc_perx_ker_ck)给外设。
⑦ 内核时钟控制逻辑(Kernel Control Logic),用于控制 PKEU 是否输出内核时钟给外设,它有很多控制信号,其中我们常用的是 PERxEN(图中红圈圈出部分),通过这个位的设置就可以控制具体外设内核时钟的开/关。注意:③和⑦,都可以通过 PERxEN 控制使能。
⑧ 外设内核时钟(rcc_perx_ker_ck),该时钟用于驱动外设产生时序,如波特率、时钟脉冲等。大部分外设都需要用到 rcc_perx_ker_ck,比如串口、SPI、IIC、FMC、SAI、LTDC 和CAN 等,但是,并不是所有的外设都需要用内核时钟来产生时序,比如:OPAMP、DMA 等。因此,大部分外设的使用,需要同时用到外设总线时钟(rcc_perx_bus_ck)和外设内核时钟(rcc_perx_ker_ck),一般情况下,这两个时钟都是由 PERxEN 控制使能。至于哪些外设有内核时钟,请参考:《STM32H7xx 参考手册》335 页,Table 55。关于 STM32H7xx 时钟的详细介绍,请参考《STM32H7XX 参考手册》第 8.5 节,有不明白的地方,可以对照手册仔细研究。另外,对于 STM32H7xx 芯片,具体哪个外设是连接在哪个
时钟总线上,以及对应的时钟总线最高主频是多少,请参考 STM32H743IIT6 数据手册(A 盘→7,硬件资料→2,芯片资料→STM32H743IIT6.pdf),Figure 1. STM32H743xI block diagram。最后,提醒下大家,STM32H743 默认的情况下(比如串口 IAP 时或未初始化时钟时),使用的是内部 64M 的 HSI 作为时钟的,所以不需要外部晶振也可以下载和运行代码的。
通过以上内容的介绍,我们知道 STM32H743 的时钟设计的比较复杂,各个时钟基本都是可控的,任何外设都有对应的时钟控制开关,这样的设计,对降低功耗是非常有用的,不用的外设不开启时钟,就可以大大降低其功耗。